1 /*
2 / spatialite_dem
3 /
4 / a tool for setting Z coordinates from XYZ files
5 /
6 / version 1.0, 2017-09-14
7 /
8 / Author: Mark Johnson, Berlin Germany mj10777@googlemail.com
9 /
10 / Copyright (C) 2017 Alessandro Furieri
11 /
12 / This program is free software: you can redistribute it and/or modify
13 / it under the terms of the GNU General Public License as published by
14 / the Free Software Foundation, either version 3 of the License, or
15 / (at your option) any later version.
16 /
17 / This program is distributed in the hope that it will be useful,
18 / but WITHOUT ANY WARRANTY; without even the implied warranty of
19 / MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 / GNU General Public License for more details.
21 /
22 / You should have received a copy of the GNU General Public License
23 / along with this program. If not, see <http://www.gnu.source_geom/licenses/>.
24 /
25 */
26 // -- -- ---------------------------------- --
27 // astyle spatialite_dem.c
28 // valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all --log-file=valgrind.spatialite_dem.utm_fetchz.txt ./spatialite_dem -fetchz_xy 24747.115253 20725.147344
29 // -- -- ---------------------------------- --
30 #if defined(_WIN32) && !defined(__MINGW32__)
31 /* MSVC strictly requires this include [off_t] */
32 #include <sys/types.h>
33 #endif
34
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <sys/time.h>
40 #include <time.h>
41
42 #if defined(_WIN32) && !defined(__MINGW32__)
43 #include "config-msvc.h"
44 #else
45 #include "config.h"
46 #endif
47
48 #if defined(_WIN32)
49 #include <io.h>
50 #include <direct.h>
51 #else
52 #include "config.h"
53 #include <dirent.h>
54 #endif
55
56 #ifdef SPATIALITE_AMALGAMATION
57 #include <spatialite/sqlite3.h>
58 #else
59 #include <sqlite3.h>
60 #endif
61
62 #include <spatialite/gaiaaux.h>
63 #include <spatialite/gaiageo.h>
64 #include <spatialite.h>
65
66 #ifdef _WIN32
67 #define strcasecmp _stricmp
68 #endif /* not WIN32 */
69 // -- -- ---------------------------------- --
70 #define ARG_NONE 0
71 #define ARG_DB_PATH 1
72 #define ARG_TABLE 2
73 #define ARG_COL 3
74 #define ARG_DEM_PATH 4
75 #define ARG_TABLE_DEM 5
76 #define ARG_COL_DEM 6
77 #define ARG_RESOLUTION_DEM 7
78 #define ARG_COPY_M 8
79 #define ARG_COMMAND_TYPE 9
80 #define ARG_FETCHZ_X 10
81 #define ARG_FETCHZ_Y 11
82 #define ARG_FETCHZ_XY 12
83 #define ARG_DEFAULT_SRID 13
84 // -- -- ---------------------------------- --
85 #define CMD_DEM_SNIFF 100
86 #define CMD_DEM_FETCHZ 101
87 #define CMD_DEM_CREATE 102
88 #define CMD_DEM_IMPORT_XYZ 103
89 #define CMD_DEM_UPDATEZ 104
90 // -- -- ---------------------------------- --
91 #define CONF_TYPE_DEM 1
92 #define CONF_TYPE_SOURCE 2
93 // -- -- ---------------------------------- --
94 // Definitions used for dem-conf
95 // -- -- ---------------------------------- --
96 #define MAXBUF 1024
97 #define DELIM "="
98 #ifdef _WIN32
99 #define LENGTHNL 2
100 #else
101 #define LENGTHNL 1
102 #endif /* not WIN32 */
103 // -- -- ---------------------------------- --
104 // Output of time elapse
105 // min = (int)(time_diff.tv_sec/60);
106 // secs = (int)(time_diff.tv_sec-(min*60));
107 // msecs = (int)(time_diff.tv_usec/1000);
108 // printf("%d mins %02d.%03d secs",min,sec,msecs);
109 // -- -- ---------------------------------- --
timeval_subtract(struct timeval * time_diff,struct timeval * time_end,struct timeval * time_start,char ** time_message)110 int timeval_subtract (struct timeval *time_diff, struct timeval *time_end, struct timeval *time_start, char **time_message)
111 {
112 int diff=0;
113 int days=0;
114 int hours=0;
115 int mins=0;
116 int secs=0;
117 int msecs=0;
118 // Perform the carry for the later subtraction by updating time_start.
119 if (time_end->tv_usec < time_start->tv_usec)
120 {
121 int nsec = (time_start->tv_usec - time_end->tv_usec) / 1000000 + 1;
122 time_start->tv_usec -= 1000000 * nsec;
123 time_start->tv_sec += nsec;
124 }
125 if (time_end->tv_usec - time_start->tv_usec > 1000000)
126 {
127 int nsec = (time_end->tv_usec - time_start->tv_usec) / 1000000;
128 time_start->tv_usec += 1000000 * nsec;
129 time_start->tv_sec -= nsec;
130 }
131 // Compute the time remaining to wait. tv_usec is certainly positive.
132 time_diff->tv_sec = time_end->tv_sec - time_start->tv_sec;
133 time_diff->tv_usec = time_end->tv_usec - time_start->tv_usec;
134 // -- -- ---------------------------------- --
135 diff = (int)time_diff->tv_sec;
136 if (diff > 86400 )
137 {// sec per day
138 days = diff / 86400;
139 diff = diff-(days*86400);
140 }
141 if (diff > 3660 )
142 {// sec per hour
143 hours = diff / 3660;
144 diff = diff -(hours*3660);
145 }
146 if (diff > 60 )
147 {
148 mins = diff / 60;
149 }
150 secs = diff - (mins * 60);
151 msecs = (int)(time_diff->tv_usec/1000);
152 // -- -- ---------------------------------- --
153 if (*time_message)
154 {
155 sqlite3_free(*time_message);
156 *time_message = NULL;
157 }
158 if ( days > 0)
159 {
160 *time_message = sqlite3_mprintf(">> time needed: %2 days %02d hours %02d mins %02d secs %02d milli-secs", days, hours, mins, secs,msecs);
161 } else if ( hours > 0)
162 {
163 *time_message = sqlite3_mprintf(">> time needed: %02d hours %02d mins %02d secs %02d milli-secs", hours, mins, secs,msecs);
164 } else if ( mins > 0)
165 {
166 *time_message = sqlite3_mprintf(">> time needed: %02d mins %02d secs %02d milli-secs", mins, secs,msecs);
167 }
168 else if (secs > 0 )
169 {
170 *time_message = sqlite3_mprintf(">> time needed: %02d secs %02d milli-secs", secs,msecs);
171 }
172 else
173 {
174 *time_message = sqlite3_mprintf(">> time needed: %02d milli-secs",msecs);
175 }
176 // -- -- ---------------------------------- --
177 // Return 1 if time_diff is negative.
178 return time_end->tv_sec < time_start->tv_sec;
179 // -- -- ---------------------------------- --
180 }
181 // -- -- ---------------------------------- --
182 // dem-conf structure
183 // -- -- ---------------------------------- --
184 struct config_dem
185 {
186 char dem_path[MAXBUF];
187 char dem_table[MAXBUF];
188 char dem_geometry[MAXBUF];
189 double dem_extent_minx;
190 double dem_extent_miny;
191 double dem_extent_maxx;
192 double dem_extent_maxy;
193 double dem_resolution;
194 int dem_srid;
195 unsigned int dem_rows_count;
196 int default_srid;
197 // Not to be used for conf_file [internal use only]
198 char *schema;
199 double fetchz_x;
200 double fetchz_y;
201 double dem_z;
202 double dem_m;
203 int has_z;
204 int has_m;
205 int has_spatial_index;
206 int is_spatial_table;
207 int config_type; // dem=0 ; source=1;
208 unsigned int id_rowid; // For debugging
209 unsigned int count_points; // For debugging
210 unsigned int count_points_nr; // For debugging
211 };
212 // -- -- ---------------------------------- --
213 // Reading dem-conf
214 // Environment var 'SPATIALITE_DEM'
215 // - with path to dem-conf
216 // -> must be created by
217 // (or using same syntax as) write_demconfig
218 // -- -- ---------------------------------- --
219 // if not found, the tool will look for a
220 // - 'spatialite_dem.conf' file in the active directory
221 // if not found, default values will be used
222 // -- -- ---------------------------------- --
223 // - any line not starting
224 // -> with a '#' [comment]
225 // -> not containing a '=' will be ignored
226 // - any other line will look for specific
227 // keywords before the '='
228 // -> unknown keywords will be ignored
229 // -- -- ---------------------------------- --
get_demconfig(char * conf_filename,int verbose)230 struct config_dem get_demconfig(char *conf_filename, int verbose)
231 {
232 struct config_dem config_struct;
233 // -- -- ---------------------------------- --
234 // Setting default values
235 // -- -- ---------------------------------- --
236 strcpy(config_struct.dem_path,"");
237 strcpy(config_struct.dem_table,"");
238 strcpy(config_struct.dem_geometry,"");
239 config_struct.dem_extent_minx=0.0;
240 config_struct.dem_extent_miny=0.0;
241 config_struct.dem_extent_maxx=0.0;
242 config_struct.dem_extent_maxy=0.0;
243 config_struct.dem_resolution=0.0;
244 config_struct.dem_srid=-2; // invalid
245 config_struct.default_srid=-2; // invalid
246 config_struct.dem_rows_count=0;
247 // -- -- ---------------------------------- --
248 // Not to be used for conf_file [internal use only]
249 // -- -- ---------------------------------- --
250 config_struct.fetchz_x=0.0;
251 config_struct.fetchz_y=0.0;
252 config_struct.dem_z=0.0;
253 config_struct.dem_m=0.0;
254 config_struct.has_z=0;
255 config_struct.has_m=0;
256 config_struct.has_spatial_index=0;
257 config_struct.is_spatial_table=0;
258 config_struct.schema=NULL;
259 config_struct.config_type=-1;
260 config_struct.id_rowid=0; // For debugging
261 config_struct.count_points=0; // For debugging
262 config_struct.count_points_nr=0; // For debugging
263 // -- -- ---------------------------------- --
264 if ((conf_filename) && (strlen(conf_filename) > 0) )
265 {
266 FILE *conf_file = fopen(conf_filename, "r");
267 if (conf_file != NULL)
268 {
269 char line[MAXBUF];
270 while(fgets(line, sizeof(line), conf_file) != NULL)
271 {
272 char *conf_parm=NULL;
273 char *conf_value=NULL;
274 conf_parm=(char *)line;
275 conf_value = strstr((char *)line,DELIM);
276 // Skip any comments (#) lines that may also contain a '='
277 if ( (conf_parm[0] != '#') && (conf_value) )
278 {
279 conf_parm[(int)(conf_value-conf_parm)]=0;
280 conf_value = conf_value + strlen(DELIM);
281 conf_value[strcspn(conf_value, "\r\n")] = 0;
282 // printf("parm[%s] value[%s]\n",conf_parm,conf_value);
283 if (strcmp(conf_parm,"dem_path") == 0)
284 {
285 strcpy(config_struct.dem_path,conf_value);
286 // printf("%s[%s]\n",conf_parm,config_struct.dem_path);
287 } else if (strcmp(conf_parm,"dem_table") == 0)
288 {
289 strcpy(config_struct.dem_table,conf_value);
290 // printf("%s[%s]\n",conf_parm,config_struct.dem_table);
291 } else if (strcmp(conf_parm,"dem_geometry") == 0)
292 {
293 strcpy(config_struct.dem_geometry,conf_value);
294 // printf("%s[%s]\n",conf_parm,config_struct.dem_geometry);
295 } else if (strcmp(conf_parm,"dem_extent_minx") == 0)
296 {
297 config_struct.dem_extent_minx=atof(conf_value);
298 //printf("%s[%2.7f]\n",conf_parm,config_struct.dem_extent_minx);
299 } else if (strcmp(conf_parm,"dem_extent_miny") == 0)
300 {
301 config_struct.dem_extent_miny=atof(conf_value);
302 //printf("%s[%2.7f]\n",conf_parm,config_struct.dem_extent_miny);
303 } else if (strcmp(conf_parm,"dem_extent_maxx") == 0)
304 {
305 config_struct.dem_extent_maxx=atof(conf_value);
306 //printf("%s[%2.7f]\n",conf_parm,config_struct.dem_extent_maxx);
307 } else if (strcmp(conf_parm,"dem_extent_maxy") == 0)
308 {
309 config_struct.dem_extent_maxy=atof(conf_value);
310 //printf("%s[%2.7f]\n",conf_parm,config_struct.dem_extent_maxy);
311 } else if (strcmp(conf_parm,"dem_resolution") == 0)
312 {
313 config_struct.dem_resolution=atof(conf_value);
314 //printf("%s[%2.7f]\n",conf_parm,config_struct.dem_resolution);
315 } else if (strcmp(conf_parm,"dem_srid") == 0)
316 {
317 config_struct.dem_rows_count=atol(conf_value);
318 // printf("%s[%d]\n",conf_parm,config_struct.dem_rows_count);
319 } else if (strcmp(conf_parm,"dem_srid") == 0)
320 {
321 config_struct.dem_srid=atoi(conf_value);
322 // printf("%s[%d]\n",conf_parm,config_struct.dem_srid);
323 } else if (strcmp(conf_parm,"default_srid") == 0)
324 {
325 config_struct.default_srid=atoi(conf_value);
326 // printf("%s[%d]\n",conf_parm,config_struct.default_srid);
327 }
328 }
329 } // End while
330 fclose(conf_file);
331 } // End if file
332 else
333 {
334 if (strcmp(conf_filename,"spatialite_dem.conf") != 0)
335 {
336 if (verbose)
337 {
338 fprintf(stderr, "-E-> spatialite_dem: not found: conf_filename[%s]\n",conf_filename);
339 }
340 }
341 }
342 }
343 return config_struct;
344 }
345 // -- -- ---------------------------------- --
346 // writing dem-conf
347 // - any line not starting
348 // -> with a '#' [comment]
349 // -> not containing a '=' will be ignored
350 // - any other line will look for specific
351 // keywords before the '='
352 // -> unknown keywords will be ignored
353 // -- -- ---------------------------------- --
354 // Saving dem-conf '-save_conf'
355 // - will save to files set in 'SPATIALITE_DEM'
356 // - if empty to the default 'spatialite_dem.conf'
357 // -- -- ---------------------------------- --
write_demconfig(char * conf_filename,struct config_dem config_struct)358 int write_demconfig(char *conf_filename, struct config_dem config_struct)
359 {
360 int rc=0;
361 FILE *conf_file = fopen(conf_filename, "w");
362 if (conf_file != NULL)
363 {
364 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
365 fprintf(conf_file, "# For use with spatialite_dem\n");
366 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
367 fprintf(conf_file, "# export SPATIALITE_DEM=%s\n",conf_filename);
368 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
369 fprintf(conf_file, "# Full path to Spatialite-Database containing a Dem-POINTZ (or POINTZM) Geometry\n");
370 fprintf(conf_file, "dem_path=%s\n", config_struct.dem_path);
371 fprintf(conf_file, "# Table-Name containing a Dem-POINTZ (or POINTZM) Geometry\n");
372 fprintf(conf_file, "dem_table=%s\n", config_struct.dem_table);
373 fprintf(conf_file, "# Geometry-Column containing a Dem-POINTZ (or POINTZM) Geometry\n");
374 fprintf(conf_file, "dem_geometry=%s\n", config_struct.dem_geometry);
375 fprintf(conf_file, "# Srid of the Dem-Geometry\n");
376 fprintf(conf_file, "dem_srid=%d\n", config_struct.dem_srid);
377 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
378 fprintf(conf_file, "# Area around given point to Query Dem-Geometry in units of Dem-Srid\n");
379 fprintf(conf_file, "# -> Rule: a Dem with 1m resolution: min=0.50\n");
380 fprintf(conf_file, "dem_resolution=%2.7f\n", config_struct.dem_resolution);
381 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
382 fprintf(conf_file, "# Default Srid to use for queries against Dem-Geometry [-fetchz_xy, -updatez]\n");
383 fprintf(conf_file, "default_srid=%d\n", config_struct.default_srid);
384 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
385 fprintf(conf_file, "# Count of rows in Dem-Geometry\n");
386 fprintf(conf_file, "dem_rows_count=%u\n", config_struct.dem_rows_count);
387 fprintf(conf_file, "# Min X of Dem-Geometry\n");
388 fprintf(conf_file, "dem_extent_minx=%2.7f\n", config_struct.dem_extent_minx);
389 fprintf(conf_file, "# Max X of Dem-Geometry\n");
390 fprintf(conf_file, "dem_extent_maxx=%2.7f\n", config_struct.dem_extent_maxx);
391 fprintf(conf_file, "# Min Y of Dem-Geometry\n");
392 fprintf(conf_file, "dem_extent_miny=%2.7f\n", config_struct.dem_extent_miny);
393 fprintf(conf_file, "# Max Y of Dem-Geometry\n");
394 fprintf(conf_file, "dem_extent_maxy=%2.7f\n", config_struct.dem_extent_maxy);
395 fprintf(conf_file, "# Width of Dem-Area in Srid-Units\n");
396 fprintf(conf_file, "dem_extent_width=%2.7f\n", (config_struct.dem_extent_maxx-config_struct.dem_extent_minx));
397 fprintf(conf_file, "# Height of Dem-Area in Srid-Units\n");
398 fprintf(conf_file, "dem_extent_height=%2.7f\n", (config_struct.dem_extent_maxy-config_struct.dem_extent_miny));
399 fprintf(conf_file, "# -- -- ---------------------------------- --\n");
400 fclose(conf_file);
401 rc=1;
402 }
403 return rc;
404 }
405 // -- -- ---------------------------------- --
406 // From a given point, build area around it by 'resolution_dem'
407 // - utm 0.999 meters, Solder Berlin 1.0375644 meters
408 // (resolution_dem/2) could also be done
409 // - but to insure that at least 1 point is returned, left as is
410 // The nearest point will always be retrieved, or none at all.
411 // -- -- ---------------------------------- --
412 static int
insert_dem_points(sqlite3 * db_handle,struct config_dem * dem_config,double * xx_source,double * yy_source,double * zz_source,int verbose)413 insert_dem_points(sqlite3 *db_handle, struct config_dem *dem_config, double *xx_source, double *yy_source, double *zz_source, int verbose)
414 {
415 /* checking for 3D geometries - version 4 */
416 int ret=0;
417 int ret_insert=SQLITE_OK;
418 int i=0;
419 char *sql_statement = NULL;
420 sqlite3_stmt *stmt = NULL;
421 char *sql_err = NULL;
422 if (zz_source)
423 {
424 sql_statement = sqlite3_mprintf("INSERT INTO \"%s\" (point_x,point_y, point_z,\"%s\") "
425 "VALUES(?,?,?,MakePointZ(?,?,?,%d)) ",dem_config->dem_table,dem_config->dem_geometry,dem_config->dem_srid);
426 ret = sqlite3_prepare_v2( db_handle, sql_statement, -1, &stmt, NULL );
427 if ( ret == SQLITE_OK )
428 {
429 sqlite3_free(sql_statement);
430 if (sqlite3_exec(db_handle, "BEGIN", NULL, NULL, &sql_err) == SQLITE_OK)
431 {
432 for (i=0; i<(int)(dem_config->count_points); i++)
433 {
434 if (ret_insert != SQLITE_ABORT )
435 {
436 // Note: sqlite3_bind_* index is 1-based, os apposed to sqlite3_column_* that is 0-based.
437 sqlite3_bind_double(stmt, 1, xx_source[i]);
438 sqlite3_bind_double(stmt, 2, yy_source[i]);
439 sqlite3_bind_double(stmt, 3, zz_source[i]);
440 sqlite3_bind_double(stmt, 4, xx_source[i]);
441 sqlite3_bind_double(stmt, 5, yy_source[i]);
442 sqlite3_bind_double(stmt, 6, zz_source[i]);
443 dem_config->count_points_nr=i;
444 ret_insert = sqlite3_step( stmt );
445 if ( ret_insert == SQLITE_DONE || ret_insert == SQLITE_ROW )
446 {
447 ret_insert=SQLITE_OK;
448 }
449 else
450 {
451 ret_insert=SQLITE_ABORT;
452 }
453 }
454 sqlite3_reset(stmt);
455 sqlite3_clear_bindings(stmt);
456 xx_source[i]=0.0;
457 yy_source[i]=0.0;
458 zz_source[i]=0.0;
459 }
460 ret=0;
461 if (ret_insert == SQLITE_ABORT )
462 {
463 if (sqlite3_exec(db_handle, "ROLLBACK", NULL, NULL, &sql_err) == SQLITE_OK)
464 {
465 ret=0;
466 }
467 }
468 else
469 {
470 if (sqlite3_exec(db_handle, "COMMIT", NULL, NULL, &sql_err) == SQLITE_OK)
471 {
472 ret = 1;
473 dem_config->dem_rows_count+=dem_config->count_points;
474 dem_config->count_points=0;
475 dem_config->count_points_nr=0;
476 }
477 }
478 }
479 sqlite3_finalize( stmt );
480 if (sql_err)
481 {
482 sqlite3_free(sql_err);
483 }
484 }
485 else
486 {
487 if (verbose)
488 {
489 fprintf(stderr, "-W-> insert_dem_points: rc=%d sql[%s]\n",ret,sql_statement);
490 }
491 sqlite3_free(sql_statement);
492 }
493 }
494 return ret;
495 }
496 // -- -- ---------------------------------- --
497 // From a given point, build area around it by 'resolution_dem'
498 // - utm 0.999 meters, Solder Berlin 1.0375644 meters
499 // (resolution_dem/2) could also be done
500 // - but to insure that at least 1 point is returned, left as is
501 // The nearest point will always be retrieved, or none at all.
502 // -- -- ---------------------------------- --
503 static int
retrieve_dem_points(sqlite3 * db_handle,struct config_dem * dem_config,int count_points,double * xx_source,double * yy_source,double * zz,double * mm,int * count_z,int * count_m,int verbose)504 retrieve_dem_points(sqlite3 *db_handle, struct config_dem *dem_config, int count_points, double *xx_source, double *yy_source, double *zz, double *mm, int *count_z, int *count_m, int verbose)
505 {
506 /* checking for 3D geometries - version 4 */
507 int ret=0;
508 int i=0;
509 char *sql_statement = NULL;
510 sqlite3_stmt *stmt = NULL;
511 int has_m = 0;
512 double x_source=0.0;
513 double y_source=0.0;
514 double z_source=0.0;
515 double m_source=0.0;
516 *count_z=0;
517 *count_m=0;
518 if (mm)
519 {
520 has_m = 1;
521 }
522 if (zz)
523 {
524 for (i=0; i<count_points; i++)
525 {
526 dem_config->count_points_nr=i;
527 x_source=xx_source[i];
528 y_source=yy_source[i];
529 /* checking the GEOMETRY_COLUMNS table */
530 if (has_m)
531 {
532 sql_statement = sqlite3_mprintf("SELECT ST_Z(\"%s\"), ST_M(\"%s\") "
533 "FROM '%s'.'%s' WHERE (ROWID IN ( "
534 "SELECT ROWID FROM SpatialIndex WHERE ( "
535 "(f_table_name = 'DB=%s.%s') AND "
536 "(f_geometry_column = '%s') AND "
537 "(search_frame = ST_Buffer(MakePoint(%2.7f,%2.7f,%d),%2.7f)))) AND "
538 "(ST_ClosestPoint(%s, MakePoint(%2.7f,%2.7f,%d)) IS NOT Null) ) "
539 "ORDER BY ST_Distance(%s,MakePoint(%2.7f,%2.7f,%d)) ASC LIMIT 1"
540 ,dem_config->dem_geometry,dem_config->dem_geometry,dem_config->schema,dem_config->dem_table,dem_config->schema,dem_config->dem_table
541 ,dem_config->dem_geometry,x_source,y_source,dem_config->dem_srid,dem_config->dem_resolution
542 ,dem_config->dem_geometry,x_source,y_source,dem_config->dem_srid,dem_config->dem_geometry,x_source,y_source,dem_config->dem_srid);
543 }
544 else
545 {
546 sql_statement = sqlite3_mprintf("SELECT ST_Z(\"%s\") "
547 "FROM '%s'.'%s' WHERE (ROWID IN ( "
548 "SELECT ROWID FROM SpatialIndex WHERE ("
549 "(f_table_name = 'DB=%s.%s') AND "
550 "(f_geometry_column = '%s') AND "
551 "(search_frame = ST_Buffer(MakePoint(%2.7f,%2.7f,%d),%2.7f)))) AND "
552 "(ST_ClosestPoint(%s, MakePoint(%2.7f,%2.7f,%d)) IS NOT Null) ) "
553 "ORDER BY ST_Distance(%s,MakePoint(%2.7f,%2.7f,%d)) ASC LIMIT 1"
554 ,dem_config->dem_geometry,dem_config->schema,dem_config->dem_table,dem_config->schema,dem_config->dem_table
555 ,dem_config->dem_geometry,x_source,y_source,dem_config->dem_srid,dem_config->dem_resolution
556 ,dem_config->dem_geometry,x_source,y_source,dem_config->dem_srid,dem_config->dem_geometry,x_source,y_source,dem_config->dem_srid);
557 }
558 ret = sqlite3_prepare_v2( db_handle, sql_statement, -1, &stmt, NULL );
559 #if 0
560 if ((dem_config->id_rowid == 354) && (dem_config->count_points == 207))
561 {
562 fprintf(stderr, "-III-> [EXTERIOR RING] -1a- cnt[%d,%d,%d] sql[%s] id_rowid[%d]\n",dem_config->count_points,dem_config->count_points_nr,ret,sql_statement,dem_config->id_rowid);
563 }
564 #endif
565 if ( ret == SQLITE_OK )
566 {
567 sqlite3_free(sql_statement);
568 while ( sqlite3_step( stmt ) == SQLITE_ROW )
569 {
570 if ( sqlite3_column_type( stmt, 0 ) != SQLITE_NULL )
571 {
572 z_source = sqlite3_column_double (stmt, 0);
573 if ( (z_source != 0.0 ) && (zz[i] != z_source ) )
574 {// Do not force an update if everything is 0 or has not otherwise changed
575 zz[i] = z_source;
576 *count_z += 1;
577 }
578 }
579 if ( sqlite3_column_type( stmt, 1 ) != SQLITE_NULL )
580 {
581 m_source = sqlite3_column_double (stmt, 1);
582 if ( (m_source != 0.0 ) && (mm[i] != m_source ) )
583 {// Do not force an update if everything is 0 or has not otherwise changed
584 mm[i] = m_source;
585 *count_m += 1;
586 }
587 mm[i] = sqlite3_column_double (stmt, 1);
588 }
589 }
590 sqlite3_finalize( stmt );
591 }
592 else
593 {
594 if (verbose)
595 {
596 fprintf(stderr, "-W-> retrieve_dem_points: rc=%d sql[%s]\n",ret,sql_statement);
597 }
598 sqlite3_free(sql_statement);
599 }
600 }
601 }
602 // printf("-I-> retrieve_dem_points: total[%d] not 0.0: z[%d] m[%d]\n",count_points,*count_z,*count_m);
603 if (*count_z > 0)
604 return 1;
605 return 0;
606 }
607 // -- -- ---------------------------------- --
608 //
609 // -- -- ---------------------------------- --
610 static int
callFetchZ(sqlite3 * db_handle,struct config_dem * dem_config,int verbose)611 callFetchZ(sqlite3 *db_handle, struct config_dem *dem_config, int verbose)
612 {
613 int ret=0;
614 char *sql_statement = NULL;
615 sqlite3_stmt *stmt = NULL;
616 int i_count_z=0;
617 int i_count_m=0;
618 double *xx_use = NULL;
619 double *yy_use = NULL;
620 double *mm_use = NULL;
621 double *zz = NULL;
622 // -- -- ---------------------------------- --
623 dem_config->dem_z=0;;
624 dem_config->dem_m=0;
625 // -- -- ---------------------------------- --
626 if (dem_config->dem_srid != dem_config->default_srid )
627 {
628 sql_statement = sqlite3_mprintf("SELECT ST_X(ST_Transform(MakePoint(%2.7f,%2.7f,%d),%d)), "
629 "ST_Y(ST_Transform(MakePoint(%2.7f,%2.7f,%d),%d))"
630 ,dem_config->fetchz_x, dem_config->fetchz_y, dem_config->default_srid,dem_config->dem_srid
631 ,dem_config->fetchz_x, dem_config->fetchz_y, dem_config->default_srid,dem_config->dem_srid);
632 ret = sqlite3_prepare_v2( db_handle, sql_statement, -1, &stmt, NULL );
633 if ( ret == SQLITE_OK )
634 {
635 sqlite3_free(sql_statement);
636 while ( sqlite3_step( stmt ) == SQLITE_ROW )
637 {
638 if (( sqlite3_column_type( stmt, 0 ) != SQLITE_NULL ) &&
639 ( sqlite3_column_type( stmt, 1 ) != SQLITE_NULL ) )
640 {
641 dem_config->fetchz_x = sqlite3_column_double(stmt, 0);
642 dem_config->fetchz_y = sqlite3_column_double(stmt, 1);
643 }
644 }
645 sqlite3_finalize( stmt );
646 }
647 else
648 {
649 if (verbose)
650 {
651 fprintf(stderr, "-W-> callFetchZ : rc=%d sql[%s]\n",ret,sql_statement);
652 }
653 sqlite3_free(sql_statement);
654 }
655 }
656 // -- -- ---------------------------------- --
657 ret=0;
658 if ((dem_config->fetchz_x >= dem_config->dem_extent_minx) && (dem_config->fetchz_x <= dem_config->dem_extent_maxx) &&
659 (dem_config->fetchz_y >= dem_config->dem_extent_miny) && (dem_config->fetchz_y <= dem_config->dem_extent_maxy ) )
660 {
661 xx_use = malloc(sizeof (double) * 1);
662 yy_use = malloc(sizeof (double) * 1);
663 zz = malloc(sizeof (double) * 1);
664 mm_use = malloc(sizeof (double) * 1);
665 xx_use[0] = dem_config->fetchz_x;
666 yy_use[0] = dem_config->fetchz_y;
667 zz[0] = dem_config->dem_z;
668 mm_use[0] = dem_config->dem_m;
669 dem_config->count_points=1;
670 if (retrieve_dem_points(db_handle, dem_config, 1, xx_use, yy_use,zz,mm_use,&i_count_z, &i_count_m,verbose))
671 {
672 ret=1;
673 dem_config->dem_z=zz[0];
674 dem_config->dem_m=mm_use[0];
675 }
676 free(xx_use);
677 free(yy_use);
678 free(zz);
679 free(mm_use);
680 xx_use = NULL;
681 yy_use = NULL;
682 mm_use = NULL;
683 zz = NULL;
684 }
685 // -- -- ---------------------------------- --
686 return ret;
687 }
688 // -- -- ---------------------------------- --
689 // GNU libc (Linux, and FreeBSD)
690 // - sys/param.h
691 // -- -- ---------------------------------- --
692 #define MIN(a,b) (((a)<(b))?(a):(b))
693 #define MAX(a,b) (((a)>(b))?(a):(b))
694 // -- -- ---------------------------------- --
695 // Based on gg_transform.c gaiaTransformCommon
696 // if the source geometry is out of range of the dem area, NULL is returned
697 // if the if the z or m values have not changed, NULL is returned
698 // - in both cases no update should be done and is not an error
699 // if the Dem-Database Geometry-Column uses a different Srid
700 // - a second Geometry will be sent with the transfored values
701 // --> those x,y values will be sent to retrieve_dem_points
702 // to retrieve the nearst point
703 // The retrieved z,m values will be copied WITHOUT any changes
704 // -- -- ---------------------------------- --
705 static gaiaGeomCollPtr
getDemCollect(sqlite3 * db_handle,gaiaGeomCollPtr source_geom,gaiaGeomCollPtr dem_geom,struct config_dem * dem_config,int * count_points_total,int * count_z_total,int * count_m_total,int verbose)706 getDemCollect(sqlite3 *db_handle, gaiaGeomCollPtr source_geom, gaiaGeomCollPtr dem_geom, struct config_dem *dem_config,
707 int *count_points_total, int *count_z_total, int *count_m_total, int verbose)
708 {
709 // creates a new GEOMETRY replacing found z-points from the original one
710 int ib=0;
711 int cnt=0;
712 int i=0;
713 double *xx = NULL;
714 double *yy = NULL;
715 double *xx_dem = NULL;
716 double *yy_dem = NULL;
717 double *zz = NULL;
718 double *mm = NULL;
719 double *xx_use = NULL;
720 double *yy_use = NULL;
721 double *mm_use = NULL;
722 int count_z=0;
723 int count_m=0;
724 int i_count_z=0;
725 int i_count_m=0;
726 double x = 0.0;
727 double y = 0.0;
728 double z = 0.0;
729 double m = 0.0;
730 double extent_minx=0.0;
731 double extent_miny=0.0;
732 double extent_maxx=0.0;
733 double extent_maxy=0.0;
734 int error = 0;
735 int isExtentWithin=0;
736 gaiaPointPtr pt = NULL;
737 gaiaPointPtr pt_dem = NULL;
738 gaiaLinestringPtr ln = NULL;
739 gaiaLinestringPtr ln_dem = NULL;
740 gaiaLinestringPtr dst_ln = NULL;
741 gaiaPolygonPtr pg = NULL;
742 gaiaPolygonPtr pg_dem = NULL;
743 gaiaPolygonPtr dst_pg = NULL;
744 gaiaRingPtr rng = NULL;
745 gaiaRingPtr rng_dem = NULL;
746 gaiaRingPtr dst_rng = NULL;
747 gaiaGeomCollPtr dst = NULL;
748 if (source_geom->DimensionModel == GAIA_XY_Z)
749 dst = gaiaAllocGeomCollXYZ();
750 else if (source_geom->DimensionModel == GAIA_XY_M)
751 dst = gaiaAllocGeomCollXYM();
752 else if (source_geom->DimensionModel == GAIA_XY_Z_M)
753 dst = gaiaAllocGeomCollXYZM();
754 else
755 dst = gaiaAllocGeomColl ();
756 cnt = 0;
757 dst->Srid = source_geom->Srid;
758 pt = source_geom->FirstPoint;
759 extent_minx=source_geom->MinX;
760 extent_miny=source_geom->MinY;
761 extent_maxx=source_geom->MaxX;
762 extent_maxy=source_geom->MaxY;
763 if (dem_geom)
764 {
765 extent_minx=dem_geom->MinX;
766 extent_miny=dem_geom->MinY;
767 extent_maxx=dem_geom->MaxX;
768 extent_maxy=dem_geom->MaxY;
769 }
770 // -- -- ---------------------------------- --
771 // Touches (partially within)
772 // -- -- ---------------------------------- --
773 int left_x = MAX(extent_minx, dem_config->dem_extent_minx);
774 int right_x = MIN(extent_maxx, dem_config->dem_extent_maxx);
775 int bottom_y = MAX(extent_miny, dem_config->dem_extent_miny);
776 int top_y = MIN(extent_maxy, dem_config->dem_extent_maxy);
777 if ((right_x > left_x) && (top_y > bottom_y))
778 {
779 isExtentWithin=1;
780 }
781 else if ((right_x == left_x) && (top_y == bottom_y))
782 {
783 // This is a point
784 isExtentWithin=1;
785 }
786 // -- -- ---------------------------------- --
787 #if 0
788 if (verbose)
789 {
790 fprintf(stderr, "-I-> getDemCollect: isExtentWithin[%d] left_x[%d] right_x[%d] bottom_y[%d] top_y[%d]\n",isExtentWithin,left_x,right_x,bottom_y,top_y);
791 }
792 #endif
793 if (!isExtentWithin)
794 {
795 error=1;
796 goto stop;
797 }
798 // -- -- ---------------------------------- --
799 // Call only if geometry is partially within the Dem extent
800 // -- -- ---------------------------------- --
801 // Points
802 // -- -- ---------------------------------- --
803 while (pt)
804 {
805 // counting POINTs
806 cnt++;
807 pt = pt->Next;
808 }
809 if (cnt)
810 {
811 // reprojecting POINTs
812 xx = malloc(sizeof (double) * cnt);
813 yy = malloc(sizeof (double) * cnt);
814 if (dem_geom)
815 {
816 xx_dem = malloc(sizeof (double) * cnt);
817 yy_dem = malloc(sizeof (double) * cnt);
818 xx_use = xx_dem;
819 yy_use = yy_dem;
820 }
821 else
822 {
823 xx_use = xx;
824 yy_use = yy;
825 }
826 zz = malloc(sizeof (double) * cnt);
827 if (source_geom->DimensionModel == GAIA_XY_M || source_geom->DimensionModel == GAIA_XY_Z_M)
828 mm = malloc(sizeof (double) * cnt);
829 i = 0;
830 pt = source_geom->FirstPoint;
831 if (dem_geom)
832 {
833 pt_dem = dem_geom->FirstPoint;
834 }
835 while (pt)
836 {
837 // inserting points to be converted in temporary arrays
838 xx[i] = pt->X;
839 yy[i] = pt->Y;
840 if (source_geom->DimensionModel == GAIA_XY_Z || source_geom->DimensionModel == GAIA_XY_Z_M)
841 zz[i] = pt->Z;
842 else
843 zz[i] = 0.0;
844 if (source_geom->DimensionModel == GAIA_XY_M || source_geom->DimensionModel == GAIA_XY_Z_M)
845 mm[i] = pt->M;
846 if (pt_dem)
847 {
848 xx_dem[i] = pt_dem->X;
849 yy_dem[i] = pt_dem->Y;
850 }
851 i++;
852 // -- -- ---------------------------------- --
853 // MultiPoints, next
854 // -- -- ---------------------------------- --
855 pt = pt->Next;
856 if (dem_geom)
857 {
858 pt_dem =pt_dem->Next;
859 }
860 }
861 if ((dem_config->has_m) && (mm) )
862 {
863 mm_use = mm;
864 }
865 // searching for nearest point
866 *count_points_total+=cnt;
867 i_count_z=0;
868 i_count_m=0;
869 dem_config->count_points=cnt;
870 if (retrieve_dem_points(db_handle, dem_config, cnt, xx_use, yy_use,zz,mm_use,&i_count_z, &i_count_m,verbose))
871 {
872 *count_z_total+=i_count_z;
873 *count_m_total+=i_count_m;
874 count_z+=i_count_z;
875 count_m+=i_count_m;
876 }
877 xx_use = NULL;
878 yy_use = NULL;
879 mm_use = NULL;
880 // inserting the reprojected POINTs in the new GEOMETRY
881 for (i = 0; i < cnt; i++)
882 {
883 x = xx[i];
884 y = yy[i];
885 if (source_geom->DimensionModel == GAIA_XY_Z || source_geom->DimensionModel == GAIA_XY_Z_M)
886 z = zz[i];
887 else
888 z = 0.0;
889 if (source_geom->DimensionModel == GAIA_XY_M || source_geom->DimensionModel == GAIA_XY_Z_M)
890 m = mm[i];
891 else
892 m = 0.0;
893 if (dst->DimensionModel == GAIA_XY_Z)
894 gaiaAddPointToGeomCollXYZ(dst, x, y, z);
895 else if (dst->DimensionModel == GAIA_XY_M)
896 gaiaAddPointToGeomCollXYM(dst, x, y, m);
897 else if (dst->DimensionModel == GAIA_XY_Z_M)
898 gaiaAddPointToGeomCollXYZM(dst, x, y, z, m);
899 else
900 gaiaAddPointToGeomColl(dst, x, y);
901 }
902 free(xx);
903 free(yy);
904 free(zz);
905 xx = NULL;
906 yy = NULL;
907 zz = NULL;
908 if (xx_dem)
909 {
910 free(xx_dem);
911 xx_dem = NULL;
912 free(yy_dem);
913 yy_dem = NULL;
914 }
915 if (source_geom->DimensionModel == GAIA_XY_M || source_geom->DimensionModel == GAIA_XY_Z_M)
916 {
917 free(mm);
918 mm = NULL;
919 }
920 }
921 if (error)
922 goto stop;
923 // -- -- ---------------------------------- --
924 // Linestrings
925 // -- -- ---------------------------------- --
926 ln = source_geom->FirstLinestring;
927 if (dem_geom)
928 {
929 ln_dem = dem_geom->FirstLinestring;
930 }
931 // Call only if geometry is inside the Dem extent
932 while (ln)
933 {
934 // reprojecting LINESTRINGs
935 cnt = ln->Points;
936 xx = malloc(sizeof (double) * cnt);
937 yy = malloc(sizeof (double) * cnt);
938 if (dem_geom)
939 {
940 xx_dem = malloc(sizeof (double) * cnt);
941 yy_dem = malloc(sizeof (double) * cnt);
942 xx_use = xx_dem;
943 yy_use = yy_dem;
944 }
945 else
946 {
947 xx_use = xx;
948 yy_use = yy;
949 }
950 zz = malloc(sizeof (double) * cnt);
951 if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M)
952 mm = malloc(sizeof (double) * cnt);
953 for (i = 0; i < cnt; i++)
954 {
955 // inserting points to be converted in temporary arrays
956 if (ln->DimensionModel == GAIA_XY_Z)
957 {
958 gaiaGetPointXYZ(ln->Coords, i, &x, &y, &z);
959 }
960 else if (ln->DimensionModel == GAIA_XY_M)
961 {
962 gaiaGetPointXYM(ln->Coords, i, &x, &y, &m);
963 }
964 else if (ln->DimensionModel == GAIA_XY_Z_M)
965 {
966 gaiaGetPointXYZM(ln->Coords, i, &x, &y, &z, &m);
967 }
968 else
969 {
970 gaiaGetPoint(ln->Coords, i, &x, &y);
971 }
972 xx[i] = x;
973 yy[i] = y;
974 if (ln_dem)
975 {
976 if (ln_dem->DimensionModel == GAIA_XY_Z)
977 {
978 gaiaGetPointXYZ(ln_dem->Coords, i, &x, &y, &z);
979 }
980 else if (ln_dem->DimensionModel == GAIA_XY_M)
981 {
982 gaiaGetPointXYM(ln->Coords, i, &x, &y, &m);
983 }
984 else if (ln_dem->DimensionModel == GAIA_XY_Z_M)
985 {
986 gaiaGetPointXYZM(ln_dem->Coords, i, &x, &y, &z, &m);
987 }
988 else
989 {
990 gaiaGetPoint(ln_dem->Coords, i, &x, &y);
991 }
992 xx_dem[i] = x;
993 yy_dem[i] = y;
994 }
995 if (ln->DimensionModel == GAIA_XY_Z || ln->DimensionModel == GAIA_XY_Z_M)
996 zz[i] = z;
997 else
998 zz[i] = 0.0;
999 if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M)
1000 mm[i] = m;
1001 }
1002 if ((dem_config->has_m) && (mm) )
1003 {
1004 mm_use = mm;
1005 }
1006 // searching for nearest point
1007 *count_points_total+=cnt;
1008 i_count_z=0;
1009 i_count_m=0;
1010 dem_config->count_points=cnt;
1011 if (retrieve_dem_points(db_handle, dem_config, cnt, xx_use, yy_use,zz,mm_use,&i_count_z, &i_count_m,verbose))
1012 {
1013 *count_z_total+=i_count_z;
1014 *count_m_total+=i_count_m;
1015 count_z+=i_count_z;
1016 count_m+=i_count_m;
1017 }
1018 xx_use = NULL;
1019 yy_use = NULL;
1020 mm_use = NULL;
1021 // inserting the reprojected LINESTRING in the new GEOMETRY
1022 dst_ln = gaiaAddLinestringToGeomColl (dst, cnt);
1023 for (i = 0; i < cnt; i++)
1024 {
1025 // setting LINESTRING points
1026 x = xx[i];
1027 y = yy[i];
1028 if (ln->DimensionModel == GAIA_XY_Z || ln->DimensionModel == GAIA_XY_Z_M)
1029 z = zz[i];
1030 else
1031 z = 0.0;
1032 if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M)
1033 m = mm[i];
1034 else
1035 m = 0.0;
1036 if (dst_ln->DimensionModel == GAIA_XY_Z)
1037 {
1038 gaiaSetPointXYZ (dst_ln->Coords, i, x, y, z);
1039 }
1040 else if (dst_ln->DimensionModel == GAIA_XY_M)
1041 {
1042 gaiaSetPointXYM(dst_ln->Coords, i, x, y, m);
1043 }
1044 else if (dst_ln->DimensionModel == GAIA_XY_Z_M)
1045 {
1046 gaiaSetPointXYZM(dst_ln->Coords, i, x, y, z, m);
1047 }
1048 else
1049 {
1050 gaiaSetPoint(dst_ln->Coords, i, x, y);
1051 }
1052 }
1053 free(xx);
1054 free(yy);
1055 xx = NULL;
1056 yy = NULL;
1057 if (xx_dem)
1058 {
1059 free(xx_dem);
1060 xx_dem = NULL;
1061 free(yy_dem);
1062 yy_dem = NULL;
1063 }
1064 free(zz);
1065 zz = NULL;
1066 if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M)
1067 {
1068 free(mm);
1069 mm = NULL;
1070 }
1071 if (error)
1072 goto stop;
1073 // -- -- ---------------------------------- --
1074 // MultiLinestrings, next
1075 // -- -- ---------------------------------- --
1076 ln = ln->Next;
1077 if (dem_geom)
1078 {
1079 ln_dem = ln_dem->Next;
1080 }
1081 }
1082 // -- -- ---------------------------------- --
1083 // Polygons
1084 // -- -- ---------------------------------- --
1085 pg = source_geom->FirstPolygon;
1086 if (dem_geom)
1087 {
1088 pg_dem = dem_geom->FirstPolygon;
1089 }
1090 while (pg)
1091 {
1092 // -- -- ---------------------------------- --
1093 // Polygons-ExteriorRing
1094 // -- -- ---------------------------------- --
1095 rng = pg->Exterior;
1096 cnt = rng->Points;
1097 dst_pg = gaiaAddPolygonToGeomColl(dst, cnt, pg->NumInteriors);
1098 xx = malloc(sizeof (double) * cnt);
1099 yy = malloc(sizeof (double) * cnt);
1100 if (dem_geom)
1101 {
1102 xx_dem = malloc(sizeof (double) * cnt);
1103 yy_dem = malloc(sizeof (double) * cnt);
1104 rng_dem = pg_dem->Exterior;
1105 xx_use = xx_dem;
1106 yy_use = yy_dem;
1107 }
1108 else
1109 {
1110 xx_use = xx;
1111 yy_use = yy;
1112 }
1113 zz = malloc(sizeof (double) * cnt);
1114 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1115 mm = malloc(sizeof (double) * cnt);
1116 for (i = 0; i < cnt; i++)
1117 {
1118 // inserting points to be converted in temporary arrays [EXTERIOR RING]
1119 if (rng->DimensionModel == GAIA_XY_Z)
1120 {
1121 gaiaGetPointXYZ(rng->Coords, i, &x, &y, &z);
1122 }
1123 else if (rng->DimensionModel == GAIA_XY_M)
1124 {
1125 gaiaGetPointXYM(rng->Coords, i, &x, &y, &m);
1126 }
1127 else if (rng->DimensionModel == GAIA_XY_Z_M)
1128 {
1129 gaiaGetPointXYZM(rng->Coords, i, &x, &y, &z, &m);
1130 }
1131 else
1132 {
1133 gaiaGetPoint(rng->Coords, i, &x, &y);
1134 }
1135 xx[i] = x;
1136 yy[i] = y;
1137 if (rng_dem)
1138 {
1139 if (rng_dem->DimensionModel == GAIA_XY_Z)
1140 {
1141 gaiaGetPointXYZ(rng_dem->Coords, i, &x, &y, &z);
1142 }
1143 else if (rng_dem->DimensionModel == GAIA_XY_M)
1144 {
1145 gaiaGetPointXYM(rng_dem->Coords, i, &x, &y, &m);
1146 }
1147 else if (rng_dem->DimensionModel == GAIA_XY_Z_M)
1148 {
1149 gaiaGetPointXYZM(rng_dem->Coords, i, &x, &y, &z, &m);
1150 }
1151 else
1152 {
1153 gaiaGetPoint(rng_dem->Coords, i, &x, &y);
1154 }
1155 xx_dem[i] = x;
1156 yy_dem[i] = y;
1157 }
1158 if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M)
1159 zz[i] = z;
1160 else
1161 zz[i] = 0.0;
1162 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1163 mm[i] = m;
1164 }
1165 if ((dem_config->has_m) && (mm) )
1166 {
1167 mm_use = mm;
1168 }
1169 // searching for nearest point
1170 *count_points_total+=cnt;
1171 i_count_z=0;
1172 i_count_m=0;
1173 dem_config->count_points=cnt;
1174 if (retrieve_dem_points(db_handle, dem_config, cnt, xx_use, yy_use,zz,mm_use,&i_count_z, &i_count_m,verbose))
1175 {
1176 *count_z_total+=i_count_z;
1177 *count_m_total+=i_count_m;
1178 count_z+=i_count_z;
1179 count_m+=i_count_m;
1180 }
1181 xx_use = NULL;
1182 yy_use = NULL;
1183 mm_use = NULL;
1184 // inserting the reprojected POLYGON in the new GEOMETRY
1185 dst_rng = dst_pg->Exterior;
1186 for (i = 0; i < cnt; i++)
1187 {
1188 // setting EXTERIOR RING points
1189 x = xx[i];
1190 y = yy[i];
1191 if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M)
1192 z = zz[i];
1193 else
1194 z = 0.0;
1195 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1196 m = mm[i];
1197 else
1198 m = 0.0;
1199 if (dst_rng->DimensionModel == GAIA_XY_Z)
1200 {
1201 gaiaSetPointXYZ (dst_rng->Coords, i, x, y, z);
1202 }
1203 else if (dst_rng->DimensionModel == GAIA_XY_M)
1204 {
1205 gaiaSetPointXYM(dst_rng->Coords, i, x, y, m);
1206 }
1207 else if (dst_rng->DimensionModel == GAIA_XY_Z_M)
1208 {
1209 gaiaSetPointXYZM(dst_rng->Coords, i, x, y, z, m);
1210 }
1211 else
1212 {
1213 gaiaSetPoint(dst_rng->Coords, i, x, y);
1214 }
1215 }
1216 free(xx);
1217 free(yy);
1218 xx = NULL;
1219 yy = NULL;
1220 if (xx_dem)
1221 {
1222 free(xx_dem);
1223 xx_dem = NULL;
1224 free(yy_dem);
1225 yy_dem = NULL;
1226 }
1227 free(zz);
1228 zz = NULL;
1229 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1230 {
1231 free(mm);
1232 mm = NULL;
1233 }
1234 if (error)
1235 goto stop;
1236 // -- -- ---------------------------------- --
1237 // Polygons-InteriorRings
1238 // -- -- ---------------------------------- --
1239 for (ib = 0; ib < pg->NumInteriors; ib++)
1240 {
1241 // processing INTERIOR RINGS
1242 rng = pg->Interiors + ib;
1243 cnt = rng->Points;
1244 xx = malloc(sizeof (double) * cnt);
1245 yy = malloc(sizeof (double) * cnt);
1246 if (dem_geom)
1247 {
1248 xx_dem = malloc(sizeof (double) * cnt);
1249 yy_dem = malloc(sizeof (double) * cnt);
1250 rng_dem = pg_dem->Interiors + ib;
1251 xx_use = xx_dem;
1252 yy_use = yy_dem;
1253 }
1254 else
1255 {
1256 xx_use = xx;
1257 yy_use = yy;
1258 }
1259 zz = malloc(sizeof (double) * cnt);
1260 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1261 mm = malloc(sizeof (double) * cnt);
1262 for (i = 0; i < cnt; i++)
1263 {
1264 // inserting points to be converted in temporary arrays [INTERIOR RING]
1265 if (rng->DimensionModel == GAIA_XY_Z)
1266 {
1267 gaiaGetPointXYZ(rng->Coords, i, &x, &y, &z);
1268 }
1269 else if (rng->DimensionModel == GAIA_XY_M)
1270 {
1271 gaiaGetPointXYM(rng->Coords, i, &x, &y, &m);
1272 }
1273 else if (rng->DimensionModel == GAIA_XY_Z_M)
1274 {
1275 gaiaGetPointXYZM(rng->Coords, i, &x, &y, &z, &m);
1276 }
1277 else
1278 {
1279 gaiaGetPoint(rng->Coords, i, &x, &y);
1280 }
1281 xx[i] = x;
1282 yy[i] = y;
1283 if (rng_dem)
1284 {
1285 if (rng_dem->DimensionModel == GAIA_XY_Z)
1286 {
1287 gaiaGetPointXYZ(rng_dem->Coords, i, &x, &y, &z);
1288 }
1289 else if (rng_dem->DimensionModel == GAIA_XY_M)
1290 {
1291 gaiaGetPointXYM(rng_dem->Coords, i, &x, &y, &m);
1292 }
1293 else if (rng_dem->DimensionModel == GAIA_XY_Z_M)
1294 {
1295 gaiaGetPointXYZM(rng_dem->Coords, i, &x, &y, &z, &m);
1296 }
1297 else
1298 {
1299 gaiaGetPoint(rng_dem->Coords, i, &x, &y);
1300 }
1301 xx_dem[i] = x;
1302 yy_dem[i] = y;
1303 }
1304 if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M)
1305 zz[i] = z;
1306 else
1307 zz[i] = 0.0;
1308 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1309 mm[i] = m;
1310 }
1311 if ((dem_config->has_m) && (mm) )
1312 {
1313 mm_use = mm;
1314 }
1315 // searching for nearest point
1316 *count_points_total+=cnt;
1317 i_count_z=0;
1318 i_count_m=0;
1319 dem_config->count_points=cnt;
1320 if (retrieve_dem_points(db_handle, dem_config, cnt, xx_use, yy_use,zz,mm_use,&i_count_z, &i_count_m,verbose))
1321 {
1322 *count_z_total+=i_count_z;
1323 *count_m_total+=i_count_m;
1324 count_z+=i_count_z;
1325 count_m+=i_count_m;
1326 }
1327 xx_use = NULL;
1328 yy_use = NULL;
1329 mm_use = NULL;
1330 // inserting the reprojected POLYGON in the new GEOMETRY
1331 dst_rng = gaiaAddInteriorRing(dst_pg, ib, cnt);
1332 for (i = 0; i < cnt; i++)
1333 {
1334 // setting INTERIOR RING points
1335 x = xx[i];
1336 y = yy[i];
1337 if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M)
1338 z = zz[i];
1339 else
1340 z = 0.0;
1341 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1342 m = mm[i];
1343 else
1344 m = 0.0;
1345 if (dst_rng->DimensionModel == GAIA_XY_Z)
1346 {
1347 gaiaSetPointXYZ(dst_rng->Coords, i, x, y, z);
1348 }
1349 else if (dst_rng->DimensionModel == GAIA_XY_M)
1350 {
1351 gaiaSetPointXYM(dst_rng->Coords, i, x, y, m);
1352 }
1353 else if (dst_rng->DimensionModel == GAIA_XY_Z_M)
1354 {
1355 gaiaSetPointXYZM(dst_rng->Coords, i, x, y, z, m);
1356 }
1357 else
1358 {
1359 gaiaSetPoint(dst_rng->Coords, i, x, y);
1360 }
1361 }
1362 free(xx);
1363 free(yy);
1364 xx = NULL;
1365 yy = NULL;
1366 if (xx_dem)
1367 {
1368 free(xx_dem);
1369 xx_dem = NULL;
1370 free(yy_dem);
1371 yy_dem = NULL;
1372 }
1373 free(zz);
1374 zz = NULL;
1375 if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M)
1376 {
1377 free(mm);
1378 mm = NULL;
1379 }
1380 if (error)
1381 goto stop;
1382 }
1383 // -- -- ---------------------------------- --
1384 // MultiPolygons, next
1385 // -- -- ---------------------------------- --
1386 pg = pg->Next;
1387 if (dem_geom)
1388 {
1389 pg_dem = pg_dem->Next;
1390 }
1391 }
1392 // -- -- ---------------------------------- --
1393 // -end- Geometry types
1394 // -- -- ---------------------------------- --
1395 stop:
1396 if ((count_z+count_m) == 0)
1397 {// Do not force an update if everything is 0 or has not otherwise changed
1398 error=1;
1399 }
1400 if (error)
1401 {
1402 // some error occurred, or no changes needed
1403 gaiaPointPtr pP;
1404 gaiaPointPtr pPn;
1405 gaiaLinestringPtr pL;
1406 gaiaLinestringPtr pLn;
1407 gaiaPolygonPtr pA;
1408 gaiaPolygonPtr pAn;
1409 pP = dst->FirstPoint;
1410 while (pP != NULL)
1411 {
1412 pPn = pP->Next;
1413 gaiaFreePoint(pP);
1414 pP = pPn;
1415 }
1416 pL = dst->FirstLinestring;
1417 while (pL != NULL)
1418 {
1419 pLn = pL->Next;
1420 gaiaFreeLinestring(pL);
1421 pL = pLn;
1422 }
1423 pA = dst->FirstPolygon;
1424 while (pA != NULL)
1425 {
1426 pAn = pA->Next;
1427 gaiaFreePolygon(pA);
1428 pA = pAn;
1429 }
1430 dst->FirstPoint = NULL;
1431 dst->LastPoint = NULL;
1432 dst->FirstLinestring = NULL;
1433 dst->LastLinestring = NULL;
1434 dst->FirstPolygon = NULL;
1435 dst->LastPolygon = NULL;
1436 gaiaFreeGeomColl(dst);
1437 dst = NULL;
1438 // -- -- ---------------------------------- --
1439 // if the source geometry is out of range of the dem area, NULL is returned
1440 // -- -- ---------------------------------- --
1441 return NULL;
1442 }
1443 if (dst)
1444 {
1445 gaiaMbrGeometry(dst);
1446 dst->DeclaredType = source_geom->DeclaredType;
1447 }
1448 return dst;
1449 }
1450 // -- -- ---------------------------------- --
1451 // if the source geometry is out of range of the dem area, NULL is returned
1452 // - no update should be done and is not an error
1453 // if the source geometry cannot be updated, when changed
1454 // - this is an error and the loop should stop
1455 // The source must be a SpatialTable,
1456 // - since ROWID is used for a (possibly) needed update
1457 // -- -- ---------------------------------- --
1458 static int
retrieve_geometries(sqlite3 * db_handle,struct config_dem * source_config,struct config_dem * dem_config,int * count_total_geometries,int * count_changed_geometries,int * count_points_total,int * count_z_total,int * count_m_total,int verbose)1459 retrieve_geometries(sqlite3 *db_handle, struct config_dem *source_config, struct config_dem *dem_config, int *count_total_geometries, int *count_changed_geometries,
1460 int *count_points_total, int *count_z_total, int *count_m_total, int verbose)
1461 {
1462 char *sql_statement = NULL;
1463 sqlite3_stmt *stmt = NULL;
1464 sqlite3_stmt *stmt_update = NULL;
1465 char *sql_err = NULL;
1466 unsigned char *blob_value = NULL;
1467 int blob_bytes=0;
1468 unsigned char *blob_update = NULL;
1469 int blob_bytes_update=0;
1470 int id_rowid=0;
1471 int ret=0;
1472 int ret_update=SQLITE_ABORT;
1473 unsigned int i_sleep=1; // 1 second
1474 int count_geometries_remainder=100;
1475 int transaction_update_changed_last=0;
1476 int transaction_count_loops=0;
1477 double remainder_calc=0.10;
1478 gaiaGeomCollPtr source_geom = NULL;
1479 gaiaGeomCollPtr geom_dem = NULL;
1480 gaiaGeomCollPtr geom_result = NULL;
1481 *count_total_geometries=0;
1482 *count_changed_geometries=0;
1483 *count_points_total=0;
1484 *count_z_total=0;
1485 *count_m_total=0;
1486 // -- -- ---------------------------------- --
1487 count_geometries_remainder=source_config->dem_rows_count/100;
1488 if (count_geometries_remainder > 1000)
1489 {// Display results every 1.25% of total geometries, when verbose
1490 remainder_calc=remainder_calc/8;
1491 } else if (source_config->dem_rows_count > 500)
1492 {// Display results every 2.5% of total geometries, when verbose
1493 remainder_calc=remainder_calc/4;
1494 } else if (source_config->dem_rows_count > 100)
1495 {// Display results every 5% of total geometries, when verbose
1496 remainder_calc=remainder_calc/2;
1497 } // else: Display results every 10% of total geometries, when verbose
1498 count_geometries_remainder=(int)(source_config->dem_rows_count*remainder_calc);
1499 // -- -- ---------------------------------- --
1500 if (verbose)
1501 {
1502 fprintf(stderr, "-I-> retrieve_geometries: results will be shown after each group of %d geometries, total[%u] \n",count_geometries_remainder,source_config->dem_rows_count);
1503 }
1504 if (dem_config->default_srid == dem_config->dem_srid)
1505 {
1506 sql_statement = sqlite3_mprintf("SELECT ROWID, \"%s\" FROM '%s'.'%s' WHERE \"%s\" IS NOT NULL",
1507 source_config->dem_geometry, source_config->schema,source_config->dem_table, source_config->dem_geometry);
1508 }
1509 else
1510 {
1511 sql_statement = sqlite3_mprintf("SELECT ROWID, \"%s\", ST_Transform(\"%s\",%d) FROM '%s'.'%s' WHERE \"%s\" IS NOT NULL",
1512 source_config->dem_geometry,source_config->dem_geometry, dem_config->dem_srid, source_config->schema,source_config->dem_table,source_config->dem_geometry);
1513 }
1514 #if 0
1515 if (verbose)
1516 {
1517 fprintf(stderr, "-I-> retrieve_geometries: sql[%s] \n",sql_statement);
1518 }
1519 #endif
1520 ret = sqlite3_prepare_v2(db_handle, sql_statement, -1, &stmt, NULL );
1521 if ( ret == SQLITE_OK )
1522 {
1523 sqlite3_free(sql_statement);
1524 while ( sqlite3_step( stmt ) == SQLITE_ROW )
1525 {
1526 if (( sqlite3_column_type( stmt, 0 ) != SQLITE_NULL ) &&
1527 ( sqlite3_column_type( stmt, 1 ) != SQLITE_NULL ) )
1528 {
1529 id_rowid = sqlite3_column_int (stmt, 0);
1530 dem_config->id_rowid=id_rowid; // for debugging
1531 blob_value = (unsigned char *)sqlite3_column_blob(stmt, 1);
1532 blob_bytes = sqlite3_column_bytes(stmt,1);
1533 source_geom = gaiaFromSpatiaLiteBlobWkb(blob_value, blob_bytes);
1534 *count_total_geometries+=1;
1535 }
1536 if ( sqlite3_column_type( stmt, 2 ) != SQLITE_NULL )
1537 {
1538 blob_value = (unsigned char *)sqlite3_column_blob(stmt, 2);
1539 blob_bytes = sqlite3_column_bytes(stmt,2);
1540 geom_dem = gaiaFromSpatiaLiteBlobWkb(blob_value, blob_bytes);
1541 }
1542 if (source_geom)
1543 {
1544 // if the source geometry is out of range of the dem area, NULL is returned: this is not an error, but no update
1545 geom_result=getDemCollect(db_handle, source_geom, geom_dem, dem_config, count_points_total,count_z_total,count_m_total,verbose);
1546 gaiaFreeGeomColl(source_geom);
1547 source_geom = NULL;
1548 if (geom_dem)
1549 {
1550 gaiaFreeGeomColl(geom_dem);
1551 geom_dem = NULL;
1552 }
1553 ret_update=SQLITE_OK;
1554 if (geom_result)
1555 {
1556 sql_statement = sqlite3_mprintf("UPDATE '%s'.'%s' SET '%s'=? WHERE ROWID=%d",
1557 source_config->schema,source_config->dem_table,source_config->dem_geometry,id_rowid);
1558 ret=sqlite3_prepare_v2(db_handle, sql_statement, -1, &stmt_update, NULL);
1559 if ( ret == SQLITE_OK)
1560 {
1561 sqlite3_free(sql_statement);
1562 gaiaToSpatiaLiteBlobWkb(geom_result, &blob_update, &blob_bytes_update);
1563 // Note: sqlite3_bind_* index is 1-based, os apposed to sqlite3_column_* that is 0-based.
1564 sqlite3_bind_blob(stmt_update, 1, blob_update, blob_bytes_update, free);
1565 ret_update = sqlite3_step( stmt_update );
1566 if ( ret_update == SQLITE_DONE || ret_update == SQLITE_ROW )
1567 {
1568 ret_update=SQLITE_OK;
1569 *count_changed_geometries += 1;
1570 }
1571 else
1572 {
1573 ret_update=SQLITE_ABORT;
1574 }
1575 sqlite3_finalize( stmt_update );
1576 }
1577 else
1578 {
1579 if (verbose)
1580 {
1581 fprintf(stderr, "-W-> retrieve_geometries [UPDATE]: rc=%d sql[%s]\n",ret,sql_statement);
1582 }
1583 sqlite3_free(sql_statement);
1584 }
1585 }
1586 gaiaFreeGeomColl(geom_result);
1587 geom_result = NULL;
1588 if (((*count_total_geometries % count_geometries_remainder) == 0))
1589 {
1590 if (*count_changed_geometries > transaction_update_changed_last)
1591 {// Store results only if something has changed
1592 // Note: while testing, this process stopped, with no further updates being reported.
1593 // The assumption was that there was a logical error else where, which was not the case.
1594 // This saving was build in to get to this point and analyse. [cause: missing Next for Linestrings/Polygon for dem_geom]
1595 // Since the logic exists, that UPDATEs are only done after changes have been made
1596 // This sporadic COMMIT/BEGIN has been retained. What is done is done.
1597 if (sqlite3_exec(db_handle, "COMMIT", NULL, NULL, &sql_err) == SQLITE_OK)
1598 {
1599 sleep(i_sleep);
1600 if (sqlite3_exec(db_handle, "BEGIN", NULL, NULL, &sql_err) == SQLITE_OK)
1601 {
1602 }
1603 }
1604 if (sql_err)
1605 {
1606 sqlite3_free(sql_err);
1607 }
1608 }
1609 if (verbose)
1610 {
1611 double procent_diff=(double)(*count_total_geometries)/source_config->dem_rows_count;
1612 remainder_calc=procent_diff*100;
1613 if (transaction_count_loops == 0)
1614 {// Show only once
1615 fprintf(stderr,"-I-> converted geometries committed to Database: \n");
1616 }
1617 transaction_count_loops++;
1618 if (dem_config->has_m)
1619 {// overwrite the previous message [\r]
1620 fprintf(stderr, "\r %02.2f%% total read[%d] changed[%d] ; points total[%d] changed z[%d] changed m[%d] ",remainder_calc,*count_total_geometries,*count_changed_geometries,*count_points_total,*count_z_total,*count_m_total);
1621 }
1622 else
1623 {// overwrite the previous message [\r]
1624 fprintf(stderr, "\r %02.2f%% total read[%d] changed[%d] ; points total[%d] changed z[%d] ",remainder_calc,*count_total_geometries,*count_changed_geometries,*count_points_total,*count_z_total);
1625 }
1626 }
1627 transaction_update_changed_last=*count_changed_geometries;
1628 }
1629 }
1630 if (ret_update == SQLITE_ABORT )
1631 {
1632 break;
1633 }
1634 }
1635 sqlite3_finalize( stmt );
1636 if (verbose)
1637 {// new line after last message [\n]
1638 fprintf(stderr, "\n");
1639 }
1640 }
1641 else
1642 {
1643 if (verbose)
1644 {
1645 fprintf(stderr, "-W-> retrieve_geometries [SELECT]: rc=%d sql[%s]\n",ret,sql_statement);
1646 }
1647 sqlite3_free(sql_statement);
1648 }
1649 if (ret_update == SQLITE_ABORT )
1650 {
1651 return 0;
1652 }
1653 return 1;
1654 }
1655 // -- -- ---------------------------------- --
1656 // Retrieve information about given
1657 // - table and geometry-column
1658 // -> for Source and Dem geometries
1659 // Dem
1660 // - must be a POINTZ or POINTZM
1661 // - SpatialIndex must exist
1662 // - Extent and row_count
1663 // -> to calculate resolution
1664 // Source
1665 // - must have a Z or ZM Dimension
1666 // Both
1667 // - Srid of geometries
1668 // -- -- ---------------------------------- --
1669 static int
check_geometry_dimension(sqlite3 * db_handle,struct config_dem * use_config,int * geometry_type,int verbose)1670 check_geometry_dimension(sqlite3 *db_handle, struct config_dem *use_config, int *geometry_type, int verbose)
1671 {
1672 /* checking the table, geometry exists and if the geometry supports z-values */
1673 int ret=0;
1674 char *sql_statement = NULL;
1675 sqlite3_stmt *stmt = NULL;
1676 int *srid_default = NULL;
1677 use_config->has_z = 0;
1678 use_config->has_m = 0;
1679 use_config->dem_extent_minx=0.0;
1680 use_config->dem_extent_miny=0.0;
1681 use_config->dem_extent_maxx=0.0;
1682 use_config->dem_extent_maxy=0.0;
1683 use_config->has_spatial_index=0;
1684 use_config->is_spatial_table=0;
1685 if (use_config->config_type == CONF_TYPE_DEM )
1686 {
1687 srid_default = &use_config->dem_srid;
1688 }
1689 else
1690 {
1691 srid_default = &use_config->default_srid;
1692 }
1693 *geometry_type = 0;
1694 *srid_default = 0;
1695 // 390718.000000 5818887.000000 392757.000000 5820847.000000
1696 // 392757-390718=2039
1697 // 5820847-5818887=1960
1698 // 1960*2039=3996440/4000440=0.99900011 resolution
1699 sql_statement = sqlite3_mprintf("SELECT a.geometry_type, a.srid, a.spatial_index_enabled, a.layer_type, "
1700 "b.extent_min_x, b.extent_min_y, b.extent_max_x, b.extent_max_y, b.row_count "
1701 "FROM '%s'.vector_layers AS a LEFT JOIN '%s'.vector_layers_statistics AS b "
1702 "ON a.table_name=b.table_name AND a.geometry_column=b.geometry_column "
1703 "WHERE a.table_name='%s' AND a.geometry_column='%s'", use_config->schema, use_config->schema,
1704 use_config->dem_table, use_config->dem_geometry);
1705 ret = sqlite3_prepare_v2(db_handle, sql_statement, -1, &stmt, NULL );
1706 if ( ret == SQLITE_OK )
1707 {
1708 sqlite3_free(sql_statement);
1709 while ( sqlite3_step( stmt ) == SQLITE_ROW )
1710 {
1711 if (( sqlite3_column_type( stmt, 0 ) != SQLITE_NULL ) &&
1712 ( sqlite3_column_type( stmt, 1 ) != SQLITE_NULL ) &&
1713 ( sqlite3_column_type( stmt, 2 ) != SQLITE_NULL ) &&
1714 ( sqlite3_column_type( stmt, 3 ) != SQLITE_NULL ))
1715 {
1716 *geometry_type = sqlite3_column_int( stmt, 0 );
1717 *srid_default = sqlite3_column_int( stmt, 1 );
1718 use_config->has_spatial_index = sqlite3_column_int( stmt, 2 );
1719 if (strcmp((const char *)sqlite3_column_text( stmt, 3 ),"SpatialTable") == 0)
1720 {
1721 // The source Database must be in a SpatialTable to be updated [no checking for writable SpatialView's]
1722 // will be using ROWID to UPDATE
1723 use_config->is_spatial_table = 1;
1724 }
1725 // printf("-I-> check_geometry_dimension: coord_dimension=%d GAIA_XY_*l[%d,%d,%d]\n",coord_dimension,GAIA_XY_Z,GAIA_XY_Z_M,GAIA_XY_M);
1726 switch (*geometry_type)
1727 {
1728 case GAIA_POINTZ:
1729 case GAIA_LINESTRINGZ:
1730 case GAIA_POLYGONZ:
1731 case GAIA_MULTIPOINTZ:
1732 case GAIA_MULTILINESTRINGZ:
1733 case GAIA_MULTIPOLYGONZ:
1734 case GAIA_GEOMETRYCOLLECTIONZ:
1735 use_config->has_z = 1;
1736 break;
1737 }
1738 switch (*geometry_type)
1739 {
1740 case GAIA_POINTZM:
1741 case GAIA_LINESTRINGZM:
1742 case GAIA_POLYGONZM:
1743 case GAIA_MULTIPOINTZM:
1744 case GAIA_MULTILINESTRINGZM:
1745 case GAIA_MULTIPOLYGONZM:
1746 case GAIA_GEOMETRYCOLLECTIONZM:
1747 use_config->has_z = 1;
1748 use_config->has_m = 1;
1749 break;
1750 }
1751 switch (*geometry_type)
1752 {
1753 case GAIA_POINTM:
1754 case GAIA_LINESTRINGM:
1755 case GAIA_POLYGONM:
1756 case GAIA_MULTIPOINTM:
1757 case GAIA_MULTILINESTRINGM:
1758 case GAIA_MULTIPOLYGONM:
1759 case GAIA_GEOMETRYCOLLECTIONM:
1760 use_config->has_m = 1;
1761 break;
1762 }
1763 }
1764 if (( sqlite3_column_type( stmt, 4 ) != SQLITE_NULL ) &&
1765 ( sqlite3_column_type( stmt, 5 ) != SQLITE_NULL ) &&
1766 ( sqlite3_column_type( stmt, 6 ) != SQLITE_NULL ) &&
1767 ( sqlite3_column_type( stmt, 7 ) != SQLITE_NULL ) &&
1768 ( sqlite3_column_type( stmt, 8 ) != SQLITE_NULL ))
1769 {
1770 use_config->dem_extent_minx = sqlite3_column_double( stmt, 4 );
1771 use_config->dem_extent_miny = sqlite3_column_double( stmt, 5 );
1772 use_config->dem_extent_maxx = sqlite3_column_double( stmt, 6 );
1773 use_config->dem_extent_maxy = sqlite3_column_double( stmt, 7 );
1774 use_config->dem_rows_count = sqlite3_column_int64( stmt, 8 );
1775 }
1776 }
1777 sqlite3_finalize( stmt );
1778 if ((use_config->is_spatial_table == 1) && (use_config->has_z) && (use_config->dem_rows_count > 0))
1779 {
1780 ret=1; // Valid for usage
1781 }
1782 }
1783 else
1784 {
1785 if (verbose)
1786 {
1787 fprintf(stderr, "-W-> check_geometry_dimension: rc=%d sql[%s]\n",ret,sql_statement);
1788 }
1789 sqlite3_free(sql_statement);
1790 }
1791 return ret;
1792 }
1793 static void
spatialite_autocreate(sqlite3 * db_handle)1794 spatialite_autocreate(sqlite3 *db_handle)
1795 {
1796 /* attempting to perform self-initialization for a newly created DB */
1797 int ret;
1798 char sql[1024];
1799 char *err_msg = NULL;
1800 int count;
1801 int i;
1802 char **results;
1803 int rows;
1804 int columns;
1805
1806 /* checking if this DB is really empty */
1807 strcpy(sql, "SELECT Count(*) from sqlite_master");
1808 ret = sqlite3_get_table(db_handle, sql, &results, &rows, &columns, NULL);
1809 if (ret != SQLITE_OK)
1810 return;
1811 if (rows < 1)
1812 ;
1813 else
1814 {
1815 for (i = 1; i <= rows; i++)
1816 count = atoi (results[(i * columns) + 0]);
1817 }
1818 sqlite3_free_table(results);
1819
1820 if (count > 0)
1821 return;
1822
1823 /* all right, it's empty: proceding to initialize */
1824 strcpy(sql, "SELECT InitSpatialMetadataFull(1)");
1825 ret = sqlite3_exec(db_handle, sql, NULL, NULL, &err_msg);
1826 if (ret != SQLITE_OK)
1827 {
1828 fprintf(stderr, "InitSpatialMetadataFull() error: %s\n", err_msg);
1829 sqlite3_free(err_msg);
1830 return;
1831 }
1832 }
1833 // -- -- ---------------------------------- --
1834 // Collecting a list of Dem-xyz file
1835 // - with checks on the first record
1836 // Case 1: a single xyz.file is given
1837 // -> the file will be checked and added to the list
1838 // Case 2: a directory is given
1839 // -> each file will be checked and added to the list
1840 // Case 3: a single list.file is given
1841 // - contains a list of single xyz.files to be read
1842 // -> expected to be inside the given directory
1843 // -> each file will be checked and added to the list
1844 // -- -- ---------------------------------- --
1845 // The list is the TABLE db_memory.xyz_files
1846 // Goal is to read the files in a specific order:
1847 // --> y='South to North' and x='West to East'
1848 // -- -- ---------------------------------- --
1849 static int
collect_xyz_files(sqlite3 * db_handle,const char * xyz_filename,int * count_xyz_files,int verbose)1850 collect_xyz_files(sqlite3 *db_handle,const char *xyz_filename, int *count_xyz_files, int verbose)
1851 {
1852 int ret=0;
1853 int i_count_fields=0;
1854 int i_count_fields_check=3;
1855 int ret_insert=SQLITE_OK;
1856 if (*count_xyz_files < 0)
1857 {
1858 *count_xyz_files=0;
1859 }
1860 double point_x=0.0;
1861 double point_y=0.0;
1862 double point_z=0.0;
1863 char *sql_statement = NULL;
1864 int result_file_type=0;
1865 char *directory_from_filename = NULL;
1866 // -- -- ---------------------------------- --
1867 FILE *xyz_file = fopen(xyz_filename, "rt");
1868 if (xyz_file != NULL)
1869 {
1870 if (verbose)
1871 {
1872 fprintf(stderr,"-I-> collect_xyz_files:reading xyz_filename[%s] \n", xyz_filename);
1873 }
1874 char line[MAXBUF];
1875 while(fgets(line, sizeof(line), xyz_file) != NULL)
1876 {
1877 if (strcmp(line, "SQLite format 3") != 0)
1878 {
1879 line[strcspn(line, "\r\n")] = 0;
1880 char *token;
1881 char *ptr_strtod;
1882 char *saveptr;
1883 i_count_fields=0;
1884 token = strtok_r(line, " ",&saveptr);
1885 point_x=strtod(token, &ptr_strtod);
1886 // atof will cause a signal 11 (SIGSEGV), if token does not contain a double
1887 if ((int)strlen(ptr_strtod) == 0)
1888 {
1889 i_count_fields++;
1890 while(token != NULL)
1891 {
1892 token = strtok_r(NULL," ",&saveptr);
1893 switch (i_count_fields)
1894 {
1895 case 1:
1896 point_y=strtod(token, &ptr_strtod);
1897 if ((int)strlen(ptr_strtod) == 0)
1898 {
1899 i_count_fields++;
1900 }
1901 break;
1902 case 2:
1903 point_z=strtod(token, &ptr_strtod);
1904 if ((int)strlen(ptr_strtod) == 0)
1905 {
1906 if (point_z < 0.0 || point_z > 0.0)
1907 {
1908 // suppressing stupid compiler warnings
1909 i_count_fields++;
1910 }
1911 }
1912 break;
1913 }
1914 }
1915 }
1916 if (i_count_fields == 0)
1917 {
1918 // This may be a list of xyz.file-names,
1919 // - contained in the same directory
1920 // - that should be read [possibly not all of the xyz.files should be read]
1921 // - order is not important, will be sorted by point_y ASC, point_x ASC of the first record
1922 if (!directory_from_filename)
1923 {
1924 const char *slash = strrchr(xyz_filename,'/');
1925 directory_from_filename=malloc(sizeof(char)*((slash-xyz_filename)+1));
1926 strncpy(directory_from_filename,xyz_filename,slash-xyz_filename);
1927 directory_from_filename[(slash-xyz_filename)]=0;
1928 }
1929 sql_statement = sqlite3_mprintf("%s/%s", directory_from_filename,token);
1930 // the first record will be read. If 3 doubles, seperated by a space, can be created
1931 // 1 : will be returned, after adding the path/file-name, point_x and point_y to db_memory.xyz_files
1932 result_file_type=collect_xyz_files(db_handle,sql_statement, count_xyz_files, 0);
1933 if (result_file_type == 1)
1934 {//file_name has been added to db_memory.xyz_files
1935 ret=1; // xyz-format
1936 }
1937 sqlite3_free(sql_statement);
1938 }
1939 if (i_count_fields == i_count_fields_check)
1940 {
1941 sql_statement = sqlite3_mprintf("INSERT INTO db_memory.xyz_files (point_x,point_y,file_name) "
1942 "VALUES(%2.7f,%2.7f,'%s') ",point_x,point_y,xyz_filename);
1943 if (db_handle)
1944 {
1945 if (sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL) == SQLITE_OK)
1946 {
1947 *count_xyz_files+=1; // xyz-format
1948 result_file_type=1;
1949 }
1950 }
1951 sqlite3_free(sql_statement);
1952 ret_insert = SQLITE_ABORT;
1953 }
1954 if (verbose)
1955 {
1956 fprintf(stderr,"-I-> collect_xyz_files: i_count_fields[%d] check[%d] count_files[%d]\n", i_count_fields,i_count_fields_check,*count_xyz_files);
1957 }
1958 }
1959 else
1960 {
1961 result_file_type=2; // Sqlite3-format
1962 }
1963 if (ret_insert == SQLITE_ABORT )
1964 {
1965 break;
1966 }
1967 if (ret_insert != SQLITE_ABORT )
1968 {
1969 // if this is a list of .xyz files that are being added,
1970 // result_file_type will be 1, but not SQLITE_ABORT
1971 // - since all entries must be read
1972 if (result_file_type != 1)
1973 {
1974 break; // unknown format
1975 }
1976 }
1977 } // End while
1978 fclose(xyz_file);
1979 if (directory_from_filename)
1980 {
1981 free(directory_from_filename);
1982 directory_from_filename=NULL;
1983 }
1984 } // Checking for a file
1985 else
1986 {
1987 #if defined(_WIN32)
1988 /* Visual Studio .NET */
1989 struct _finddata_t c_file;
1990 intptr_t hFile;
1991 char *name;
1992 int len;
1993 int ret;
1994 if (_chdir (xyz_filename) < 0)
1995 return ret;
1996 if ((hFile = _findfirst ("*.xyz", &c_file)) == -1L)
1997 ;
1998 else
1999 {
2000 while (1)
2001 {// A directory with .xyz files
2002 if ((c_file.attrib & _A_RDONLY) == _A_RDONLY || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
2003 {
2004 sql_statement = sqlite3_mprintf("%s/%s", xyz_filename,c_file.name);
2005 if (collect_xyz_files(db_handle,sql_statement, count_xyz_files, 0) == 1)
2006 {//file_name has been added to db_memory.xyz_files
2007 }
2008 sqlite3_free(sql_statement);
2009 }
2010 if (_findnext (hFile, &c_file) != 0)
2011 break;
2012 }
2013 _findclose (hFile);
2014 }
2015 #else
2016 DIR *xyz_dir = opendir(xyz_filename);
2017 struct dirent *dir;
2018 if (xyz_dir)
2019 {
2020 while ((dir = readdir(xyz_dir)) != NULL)
2021 {
2022 if (dir->d_type == DT_REG)
2023 {
2024 const char *ext = strrchr(dir->d_name,'.');
2025 if ((ext) || (ext != dir->d_name))
2026 {
2027 if (strcmp(ext, ".xyz") == 0)
2028 {// A directory with .xyz files
2029 // - order is not important, will be sorted by point_y ASC, point_x ASC of the first record
2030 sql_statement = sqlite3_mprintf("%s/%s", xyz_filename,dir->d_name);
2031 // the first record will be read. If 3 doubles, seperated by a space, can be created
2032 // 1 : will be returned, after adding the path/file-name, point_x and point_y to db_memory.xyz_files
2033 result_file_type=collect_xyz_files(db_handle,sql_statement, count_xyz_files, 0);
2034 if (result_file_type == 1)
2035 {//file_name has been added to db_memory.xyz_files
2036 }
2037 sqlite3_free(sql_statement);
2038 }
2039 }
2040 }
2041 }
2042 closedir(xyz_dir);
2043 } // Checking for a directory
2044 #endif
2045 }
2046 // -- -- ---------------------------------- --
2047 if (*count_xyz_files > 0)
2048 {
2049 ret=1; // xyz-format
2050 }
2051 else
2052 {
2053 ret=0; // not supported
2054 if (verbose)
2055 {
2056 fprintf(stderr,"-E-> collect_xyz_files: import.xyz file format not found [%s]\n", xyz_filename);
2057 }
2058 }
2059 // -- -- ---------------------------------- -
2060 return ret;
2061 }
2062 // -- -- ---------------------------------- --
2063 // Read list of Dem-xyz files
2064 // - from db_memory.xyz_files
2065 // Goal is to INSERT the points in a specific order:
2066 // --> y='South to North' and x='West to East'
2067 // -- -- ---------------------------------- --
2068 static int
import_xyz(sqlite3 * db_handle,struct config_dem * dem_config,int count_xyz_files,int verbose)2069 import_xyz(sqlite3 *db_handle, struct config_dem *dem_config, int count_xyz_files, int verbose)
2070 {
2071 int ret=0;
2072 int ret_select=0;
2073 sqlite3_stmt *stmt = NULL;
2074 char *sql_statement = NULL;
2075 int i_count_loop=100000;
2076 int i_count_fields=0;
2077 int i_count_fields_check=3;
2078 int i_count_in_loop=0;
2079 int i_file_count=0;
2080 const char *xyz_path_filename;
2081 // 18.446.744.073.709.551.615
2082 unsigned int i_sleep=1; // 1 second
2083 double point_x=0.0;
2084 double point_y=0.0;
2085 double point_z=0.0;
2086 double *xx = NULL;
2087 double *yy = NULL;
2088 double *zz = NULL;
2089 int ret_insert=SQLITE_OK;
2090 if (count_xyz_files > 0)
2091 {// input-files should be sorted from y='South to North' and x='West to East': sort -n -k2 -k1 input_file.xyz -o output_file.sort.xyz
2092 // Select files sorted by y='South to North' and x='West to East'
2093 sql_statement = sqlite3_mprintf("SELECT file_name FROM db_memory.xyz_files ORDER BY point_y ASC, point_x ASC");
2094 ret_select = sqlite3_prepare_v2(db_handle, sql_statement, -1, &stmt, NULL );
2095 sqlite3_free(sql_statement);
2096 if ( ret_select == SQLITE_OK )
2097 {
2098 while ( sqlite3_step( stmt ) == SQLITE_ROW )
2099 {
2100 if ( sqlite3_column_type( stmt, 0 ) != SQLITE_NULL )
2101 {
2102 xyz_path_filename=(const char *) sqlite3_column_text (stmt, 0);
2103 // -- -- ---------------------------------- --
2104 FILE *xyz_file = fopen(xyz_path_filename, "rt");
2105 if (xyz_file != NULL)
2106 {
2107 char line[MAXBUF];
2108 i_file_count++;
2109 i_count_in_loop=0;
2110 if (verbose)
2111 {
2112 // CPU: 4-11% ; memory 9.3 Ḿib ; normal working with mouse and applications
2113 fprintf(stderr,"import_xyz: reading xyz_filename[%s]\n (file %d of %d) in steps of [%u].\n",xyz_path_filename,i_file_count,count_xyz_files, i_count_loop);
2114 }
2115 xx = malloc(sizeof (double) * i_count_loop);
2116 yy = malloc(sizeof (double) * i_count_loop);
2117 zz = malloc(sizeof (double) * i_count_loop);
2118 while(fgets(line, sizeof(line), xyz_file) != NULL)
2119 {
2120 line[strcspn(line, "\r\n")] = 0;
2121 char *token;
2122 char *ptr_strtod;
2123 char *saveptr;
2124 i_count_fields=0;
2125 token = strtok_r(line, " ",&saveptr);
2126 point_x=strtod(token, &ptr_strtod);
2127 // atof will cause a signal 11 (SIGSEGV), if token does not contain a double
2128 if ((int)strlen(ptr_strtod) == 0)
2129 {
2130 i_count_fields++;
2131 while(token != NULL)
2132 {
2133 token = strtok_r(NULL," ",&saveptr);
2134 switch (i_count_fields)
2135 {
2136 case 1:
2137 point_y=strtod(token, &ptr_strtod);
2138 if ((int)strlen(ptr_strtod) == 0)
2139 {
2140 i_count_fields++;
2141 }
2142 break;
2143 case 2:
2144 point_z=strtod(token, &ptr_strtod);
2145 if ((int)strlen(ptr_strtod) == 0)
2146 {
2147 i_count_fields++;
2148 }
2149 break;
2150 }
2151 }
2152 }
2153 if (i_count_fields == i_count_fields_check)
2154 {
2155 if (i_count_in_loop < i_count_loop)
2156 {
2157 xx[i_count_in_loop]=point_x;
2158 yy[i_count_in_loop]=point_y;
2159 zz[i_count_in_loop]=point_z;
2160 i_count_in_loop++;
2161 }
2162 if (i_count_in_loop == i_count_loop)
2163 {
2164 dem_config->count_points=i_count_in_loop;
2165 if (!insert_dem_points(db_handle, dem_config, xx, yy, zz, verbose))
2166 {
2167 // Inserting failed, abort
2168 ret_insert = SQLITE_ABORT;
2169 }
2170 else
2171 {
2172 if (verbose)
2173 {
2174 fprintf(stderr,"\r inserted [%u] ... ", dem_config->dem_rows_count);
2175 }
2176 }
2177 // xx,yy,zz values are reset to 0.0 in insert_dem_points
2178 i_count_in_loop=0;
2179 sleep(i_sleep);
2180 }
2181 }
2182 else
2183 {
2184 ret_insert = SQLITE_ABORT;
2185 }
2186 if (ret_insert == SQLITE_ABORT )
2187 {
2188 break;
2189 }
2190 } // End while
2191 fclose(xyz_file);
2192 // -- -- ---------------------------------- --
2193 // Complete what is left over, when no abort
2194 // -- -- ---------------------------------- --
2195 if (ret_insert != SQLITE_ABORT )
2196 {
2197 ret=1;
2198 if ( i_count_in_loop < i_count_loop)
2199 {
2200 ret=0;
2201 dem_config->count_points=i_count_in_loop;
2202 fprintf(stderr,"import_xyz: calling insert_dem_points: i_count_in_loop[%d].\n",dem_config->count_points);
2203 if (insert_dem_points(db_handle, dem_config, xx, yy, zz, verbose))
2204 {
2205 ret=1;
2206 if (verbose)
2207 {
2208 fprintf(stderr,"\r file%d: inserting completed [%u]\n",i_file_count, dem_config->dem_rows_count);
2209 }
2210 }
2211 }
2212 }
2213 // -- -- ---------------------------------- --
2214 // clean up
2215 // -- -- ---------------------------------- --
2216 if (xx)
2217 {
2218 free(xx);
2219 xx=NULL;
2220 }
2221 if (yy)
2222 {
2223 free(yy);
2224 yy=NULL;
2225 }
2226 if (zz)
2227 {
2228 free(zz);
2229 zz=NULL;
2230 }
2231 }
2232 else
2233 {
2234 if (verbose)
2235 {
2236 fprintf(stderr,"-E-> import_xyz: import.xyz file not found [%s]\n", xyz_path_filename);
2237 }
2238 }
2239 }
2240 }
2241 sqlite3_finalize( stmt );
2242 }
2243 }
2244 // -- -- ---------------------------------- --
2245 return ret;
2246 }
2247 // -- -- ---------------------------------- --
2248 // Recover Dem-Geometry with SpatialIndex
2249 // - recovering a full Geometry Column
2250 // -- -- ---------------------------------- --
2251 static int
recover_geometry_dem(sqlite3 * db_handle,struct config_dem * dem_config,int verbose)2252 recover_geometry_dem(sqlite3 *db_handle, struct config_dem *dem_config, int verbose)
2253 {
2254 /* recovering a full Geometry Column */
2255 int ret;
2256 char *err_msg;
2257 char *sql_statement = NULL;
2258 if (verbose)
2259 {
2260 fprintf(stderr,"Recovering Geometry: %s(%s) as POINTZ with srid=%d\n", dem_config->dem_table,dem_config->dem_geometry, dem_config->dem_srid);
2261 }
2262 sql_statement = sqlite3_mprintf("SELECT RecoverGeometryColumn(%Q, %Q, %d, %Q, %Q)",
2263 dem_config->dem_table,dem_config->dem_geometry, dem_config->dem_srid, "POINT", "XYZ");
2264 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, &err_msg);
2265 sqlite3_free(sql_statement);
2266 if (ret != SQLITE_OK)
2267 {
2268 if (verbose)
2269 {
2270 fprintf(stderr, "RecoverGeometryColumn error: %s\n", err_msg);
2271 }
2272 sqlite3_free(err_msg);
2273 return 0;
2274 }
2275 if (verbose)
2276 {
2277 fprintf(stderr, "Creating Spatial Index: %s(%s)\n", dem_config->dem_table,dem_config->dem_geometry);
2278 }
2279 sql_statement = sqlite3_mprintf("SELECT CreateSpatialIndex(%Q, %Q)", dem_config->dem_table,dem_config->dem_geometry);
2280 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, &err_msg);
2281 sqlite3_free(sql_statement);
2282 if (ret != SQLITE_OK)
2283 {
2284 fprintf(stderr, "CreateSpatialIndex error: %s\n", err_msg);
2285 sqlite3_free(err_msg);
2286 return 0;
2287 }
2288 if (verbose)
2289 {
2290 fprintf(stderr,"UpdateLayerStatistics: %s(%s)\n", dem_config->dem_table,dem_config->dem_geometry);
2291 }
2292 sql_statement = sqlite3_mprintf("SELECT UpdateLayerStatistics(%Q, %Q)", dem_config->dem_table,dem_config->dem_geometry);
2293 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, &err_msg);
2294 sqlite3_free(sql_statement);
2295 if (ret != SQLITE_OK)
2296 {
2297 fprintf(stderr, "UpdateLayerStatistics error: %s\n", err_msg);
2298 sqlite3_free(err_msg);
2299 return 0;
2300 }
2301 return 1;
2302 }
2303 // -- -- ---------------------------------- --
2304 // Create the Database for Dem
2305 // - CREATE TABLE for minimal Dem-Data
2306 // -> db_memory.xyz_files
2307 // -- -- ---------------------------------- --
2308 static int
create_dem_db(const char * path_dem,sqlite3 ** handle,void * cache,const char * table_dem,const char * column_dem,int verbose)2309 create_dem_db(const char *path_dem, sqlite3 ** handle, void *cache, const char *table_dem, const char *column_dem, int verbose)
2310 {
2311 /* opening the DB */
2312 sqlite3 *db_handle = NULL;
2313 int ret=0;
2314 char *sql_statement = NULL;
2315 *handle = NULL;
2316 if ( verbose )
2317 {
2318 fprintf(stderr,"SQLite version: %s\n", sqlite3_libversion());
2319 fprintf(stderr,"SpatiaLite version: %s\n\n", spatialite_version());
2320 }
2321 FILE *db_file = fopen(path_dem, "r");
2322 if (db_file != NULL)
2323 {
2324 fclose(db_file);
2325 return ret;
2326 }
2327 ret = sqlite3_open_v2(path_dem, &db_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
2328 if (ret != SQLITE_OK)
2329 {
2330 fprintf(stderr, "cannot open '%s': %s\n", path_dem, sqlite3_errmsg (db_handle));
2331 sqlite3_close(db_handle);
2332 return ret;
2333 }
2334 spatialite_init_ex(db_handle, cache, 0);
2335 spatialite_autocreate(db_handle);
2336 if ( (table_dem) && ( column_dem ) )
2337 {
2338 sql_statement = sqlite3_mprintf("CREATE TABLE \"%s\" ("
2339 "id_dem INTEGER PRIMARY KEY AUTOINCREMENT, "
2340 "point_x DOUBLE DEFAULT 0, "
2341 "point_y DOUBLE DEFAULT 0, "
2342 "point_z DOUBLE DEFAULT 0, "
2343 "%s BLOB DEFAULT NULL)"
2344 ,table_dem, column_dem);
2345 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2346 if (ret != SQLITE_OK)
2347 {
2348 fprintf(stderr, "cannot CREATE Table: '%s' sql[%s]\n\t: %s\n", table_dem, sql_statement, sqlite3_errmsg (db_handle));
2349 sqlite3_free(sql_statement);
2350 sqlite3_close(db_handle);
2351 return ret;
2352 }
2353 sqlite3_free(sql_statement);
2354 if (verbose)
2355 {
2356 fprintf(stderr,"Created table(geometry): %s(%s)\n", table_dem, column_dem);
2357 }
2358 sql_statement = sqlite3_mprintf("ATTACH DATABASE ':memory:' AS db_memory");
2359 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2360 sqlite3_free(sql_statement);
2361 if (ret == SQLITE_OK)
2362 {
2363 sql_statement = sqlite3_mprintf("CREATE TABLE db_memory.xyz_files ("
2364 "file_name TEXT DEFAULT '', "
2365 "point_x DOUBLE DEFAULT 0, "
2366 "point_y DOUBLE DEFAULT 0)");
2367 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2368 sqlite3_free(sql_statement);
2369 if (ret != SQLITE_OK)
2370 {
2371 }
2372 }
2373 }
2374 *handle = db_handle;
2375 ret=1;
2376 return ret;
2377 }
2378 // -- -- ---------------------------------- --
2379 // Close the Database
2380 // - DETACH a connected Database if needed
2381 // -> db_memory
2382 // -- -- ---------------------------------- --
2383 static void
close_db(sqlite3 * db_handle,void * cache,const char * schema_dem)2384 close_db(sqlite3 *db_handle, void *cache, const char *schema_dem)
2385 {
2386 char *sql_statement = NULL;
2387 int ret=0;
2388 if (schema_dem)
2389 {
2390 if (strcmp(schema_dem, "main") != 0)
2391 {
2392 sql_statement = sqlite3_mprintf("DETACH DATABASE %s", schema_dem);
2393 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2394 sqlite3_free(sql_statement);
2395 }
2396 }
2397 sql_statement = sqlite3_mprintf("DETACH DATABASE db_memory");
2398 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2399 if (ret == SQLITE_OK)
2400 {
2401 // suppressing stupid compiler warnings
2402 }
2403 sqlite3_free(sql_statement);
2404 sqlite3_close(db_handle);
2405 if (cache)
2406 {
2407 spatialite_cleanup_ex(cache);
2408 }
2409 spatialite_shutdown();
2410 return;
2411 }
2412 // -- -- ---------------------------------- --
2413 // Open the Database
2414 // - ATTACH a connected Database if needed
2415 // While 'sniffing' a second source may not be needed
2416 // - CREATE TABLE for minimal Dem-Data
2417 // -> db_memory.xyz_files
2418 // -- -- ---------------------------------- --
2419 static int
open_db(sqlite3 ** handle,void * cache,struct config_dem * source_config,struct config_dem * dem_config,int verbose)2420 open_db(sqlite3 **handle, void *cache, struct config_dem *source_config, struct config_dem *dem_config, int verbose)
2421 {
2422 /* opening the DB */
2423 sqlite3 *db_handle = NULL;
2424 int ret=0;
2425 char *sql_statement = NULL;
2426 const char *path_db=NULL;
2427 const char *path_attach=NULL;
2428 const char *schema_attach=NULL;
2429 *handle = NULL;
2430 if ( verbose )
2431 {
2432 fprintf(stderr,"SQLite version: %s\n", sqlite3_libversion());
2433 fprintf(stderr,"SpatiaLite version: %s\n\n", spatialite_version());
2434 }
2435 if ((strlen(dem_config->dem_path) > 0) && ( (source_config) && (strlen(source_config->dem_path) == 0)))
2436 {
2437 // Open the Dem-Database as source [sniff without source or fetchz]
2438 path_db=dem_config->dem_path;
2439 dem_config->schema="main";
2440 schema_attach=dem_config->schema;
2441 }
2442 else
2443 {
2444 path_db=source_config->dem_path;
2445 path_attach=dem_config->dem_path;
2446 schema_attach=dem_config->schema;
2447 }
2448 ret = sqlite3_open_v2(path_db, &db_handle, SQLITE_OPEN_READWRITE, NULL);
2449 if (ret != SQLITE_OK)
2450 {
2451 fprintf(stderr, "cannot open '%s': %s\n", path_db, sqlite3_errmsg (db_handle));
2452 close_db(db_handle, cache, NULL);
2453 return 0;
2454 }
2455 if (path_attach)
2456 {
2457 sql_statement = sqlite3_mprintf("ATTACH DATABASE \"%s\" AS %s",path_attach, schema_attach);
2458 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2459 if (ret != SQLITE_OK)
2460 {
2461 fprintf(stderr, "cannot ATTACH Database: '%s' sql[%s]\n\t: %s\n", path_attach, sql_statement, sqlite3_errmsg (db_handle));
2462 sqlite3_free(sql_statement);
2463 close_db(db_handle, cache, NULL);
2464 return 0;
2465 }
2466 sqlite3_free(sql_statement);
2467 }
2468 sql_statement = sqlite3_mprintf("ATTACH DATABASE ':memory:' AS db_memory");
2469 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2470 sqlite3_free(sql_statement);
2471 if (ret == SQLITE_OK)
2472 {
2473 sql_statement = sqlite3_mprintf("CREATE TABLE db_memory.xyz_files ("
2474 "file_name TEXT DEFAULT '', "
2475 "point_x DOUBLE DEFAULT 0, "
2476 "point_y DOUBLE DEFAULT 0)");
2477 ret = sqlite3_exec(db_handle, sql_statement, NULL, NULL, NULL);
2478 sqlite3_free(sql_statement);
2479 if (ret != SQLITE_OK)
2480 {
2481 }
2482 }
2483 spatialite_init_ex(db_handle, cache, 0);
2484 *handle = db_handle;
2485 return 1;
2486 }
2487 // -- -- ---------------------------------- --
2488 // Help Messages
2489 // -- -- ---------------------------------- --
2490 static void
do_help()2491 do_help()
2492 {
2493 /* printing the argument list */
2494 fprintf(stderr, "\n\nusage: spatialite_dem ARGLIST\n");
2495 fprintf(stderr, "==============================================================\n");
2496 fprintf(stderr, "-h or --help print this help message\n");
2497 fprintf(stderr, "========================== Parameters ========================\n");
2498 fprintf(stderr, " -- -- ---------------- Dem-Data Database ---------------- --\n");
2499 fprintf(stderr, "-ddem or --dem-path pathname to the SpatiaLite Dem DB \n");
2500 fprintf(stderr, "-tdem or --table-dem table_name [SpatialTable or SpatialView]\n");
2501 fprintf(stderr, "-gdem or --geometry-dem-column col_name the Geometry column\n");
2502 fprintf(stderr, "\t must be a POINT Z or a POINT ZM type\n");
2503 fprintf(stderr, "-rdem or --dem-resolution of the dem points while searching\n");
2504 fprintf(stderr, "\t the automatic resolution calculation is based on the row_count\n");
2505 fprintf(stderr, "\t within the extent, which may not be correct!\n");
2506 fprintf(stderr, "\t Use '-rdem' to set a realistic value\n");
2507 fprintf(stderr, "\n -- -- -------------- Source-Update-Database ----------------- --\n");
2508 fprintf(stderr, "-d or --db-path pathname to the SpatiaLite DB\n");
2509 fprintf(stderr, "-t or --table table_name, must be a SpatialTable\n");
2510 fprintf(stderr, "-g or --geometry-column the Geometry column to update\n");
2511 fprintf(stderr, "\t must be a Z or a ZM Dimension type\n\t use CastToXYZ(geom) or CastToXYZM(geom) to convert \n");
2512 fprintf(stderr, " -- -- --------------- General Parameters ---------------- --\n");
2513 fprintf(stderr, "-mdem or --copy-m [0=no, 1= yes [default] if exists]\n");
2514 fprintf(stderr, "-default_srid or --srid for use with -fetchz\n");
2515 fprintf(stderr, "-fetchz_xy x- and y-value for use with -fetchz\n");
2516 fprintf(stderr, "-v or --verbose messages during -updatez and -fetchz\n");
2517 fprintf(stderr, "-save_conf based on active -ddem , -tdem, -gdem and -srid when valid\n");
2518 fprintf(stderr, "\n -- -- -------------------- Notes: ---------------------- --\n");
2519 fprintf(stderr, "-I-> the Z value will be copied from the nearest point found\n");
2520 fprintf(stderr, "-I-> the Srid of the source Geometry and the Dem-POINT can be different\n");
2521 fprintf(stderr, "-I-> when -fetchz_xy is used in a bash script, -v should not be used\n");
2522 fprintf(stderr, "\t the z-value will then be returned as the result\n");
2523 fprintf(stderr, "\n -- -- -------------------- Conf file: ------------------- --\n");
2524 fprintf(stderr, "-I-> if 'SPATIALITE_DEM' is set with the path to a file\n");
2525 fprintf(stderr, "-I--> 'export SPATIALITE_DEM=/long/path/to/file/berlin_dhh92.conf'\n");
2526 fprintf(stderr, "-I-> then '-save_conf' save the config to that file\n");
2527 fprintf(stderr, "-I-> this file will be read on each application start, setting those values\n");
2528 fprintf(stderr, "-I--> the parameters for :\n");
2529 fprintf(stderr, "\t which Dem-Database and Geometry and the default_srid to use for queries\n");
2530 fprintf(stderr, "\t -> would then not be needed\n");
2531 fprintf(stderr, "\n -- -- ---------------- Importing .xyz files: ------------------- --\n");
2532 fprintf(stderr, "-I-> a single xyz.file or a directory containing .xyz files can be given\n");
2533 fprintf(stderr, "\t for directories: only files with the extension .xyz will be searched for\n");
2534 fprintf(stderr, "-I-> a single list.file inside a directory containing .xyz files can be given\n");
2535 fprintf(stderr, "\t each line containing the file-name that must exist in that directory\n");
2536 fprintf(stderr, "-I-> validty checks are done before importing xyz-files\n");
2537 fprintf(stderr, "\t the first line may contain only 3 double values (point_x/y/z)\n");
2538 fprintf(stderr, "\t if valid, the file-name and the point_x/y points are stored\n");
2539 fprintf(stderr, "\t when importing, the list will be read based of the y/x points\n");
2540 fprintf(stderr, "\n -- -- ---------------- Sorting .xyz files: ---------------------- --\n");
2541 fprintf(stderr, "-I-> xyz.files should be sorted:\n");
2542 fprintf(stderr, "\t y='South to North' and x='West to East': \n");
2543 fprintf(stderr, "\t sort -n -k2 -k1 input_file.xyz -o output_file.sort.xyz");
2544 fprintf(stderr, "\n=========================== Commands ===========================\n");
2545 fprintf(stderr, "-sniff [default] analyse settings without UPDATE of z-values \n");
2546 fprintf(stderr, "-updatez Perform UPDATE of z-values \n");
2547 fprintf(stderr, "-fetchz Perform Query of z-values using -fetchz_x_y and default_srid\n");
2548 fprintf(stderr, "\t will be assumed when using -fetchz_x_y\n");
2549 fprintf(stderr, "-create_dem create Dem-Database using -ddem,-tdem, -gdem and -srid for the Database \n");
2550 fprintf(stderr, "\t -d as a dem.xyz file \n");
2551 fprintf(stderr, "-import_xyz import another .xyz file into a Dem-Database created with -create_dem \n");
2552 fprintf(stderr, "\t these points will not be sorted, but added to the end ");
2553 fprintf(stderr, "\n=========================== Sample ===========================\n");
2554 fprintf(stderr, "--> with 'SPATIALITE_DEM' set: \n");
2555 fprintf(stderr, "spatialite_dem -fetchz_xy 24700.55278283251 20674.74537357586\n");
2556 fprintf(stderr, "33.5600000 \n");
2557 fprintf(stderr, "==============================================================\n");
2558 }
2559 // -- -- ---------------------------------- --
2560 // Checking the status of the Dem-Database
2561 // - used by differenct command types
2562 // -- -- ---------------------------------- --
2563 static int
command_check_source_db(sqlite3 * db_handle,struct config_dem * source_config,int verbose)2564 command_check_source_db(sqlite3 *db_handle, struct config_dem*source_config, int verbose)
2565 {
2566 int ret=0;
2567 int geometry_type=0;
2568 // -- -- ---------------------------------- --
2569 if ((strlen(source_config->dem_path) > 0) && (strlen(source_config->dem_table) > 0) && (strlen(source_config->dem_geometry) > 0))
2570 {
2571 if (check_geometry_dimension(db_handle,source_config, &geometry_type,verbose))
2572 {
2573 if (verbose)
2574 {
2575 fprintf(stderr,"Source: srid %d\n", source_config->default_srid);
2576 fprintf(stderr,"Source: extent min x/y(%2.7f,%2.7f)\n\t max x/y(%2.7f,%2.7f)\n",
2577 source_config->dem_extent_minx,source_config->dem_extent_miny,
2578 source_config->dem_extent_maxx,source_config->dem_extent_maxy);
2579 fprintf(stderr,"Source: rows_count(%s) %d\n",source_config->dem_geometry, source_config->dem_rows_count);
2580 fprintf(stderr,"Source: geometry_type(%d) has_z[%d]\n",geometry_type,source_config->has_z);
2581 fprintf(stderr,"Source: spatial_index_enabled[%d]\n",source_config->has_spatial_index);
2582 }
2583 if (source_config->is_spatial_table == 1)
2584 {
2585 if (source_config->has_z)
2586 {// The source Database Table and geometry-columns exists and contains a z-value dimension.
2587 ret = 0;
2588 if (verbose)
2589 {
2590 fprintf(stderr,"Source '%s'\n", source_config->dem_path);
2591 fprintf(stderr," will set %s(%s) Z-Values\n\tfrom nearest POINT found in\n",source_config->dem_table, source_config->dem_geometry);
2592 }
2593 }
2594 else
2595 {
2596 ret = -1;
2597 if (verbose)
2598 {
2599 fprintf(stderr, "DB '%s'\n", source_config->dem_path);
2600 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] does not contained in a SpatialTable [will not update]\n",source_config->dem_table, source_config->dem_geometry);
2601 fprintf(stderr, "\t command_check_source_db failed: sorry, cowardly quitting\n\n");
2602 }
2603 }
2604 }
2605 else
2606 {
2607 ret = -1;
2608 if (verbose)
2609 {
2610 fprintf(stderr, "DB '%s'\n", source_config->dem_path);
2611 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] does not contain a Z-Dimension\n",source_config->dem_table, source_config->dem_geometry);
2612 fprintf(stderr, "\t command_check_source_db failed: sorry, cowardly quitting\n\n");
2613 }
2614 }
2615 }
2616 else
2617 {// The source Database Table or geometry-columns does not exist.
2618 ret = -1;
2619 if (verbose)
2620 {
2621 fprintf(stderr, "DB '%s'\n", source_config->dem_path);
2622 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] not found\n",source_config->dem_table, source_config->dem_geometry);
2623 fprintf(stderr, "\t check_geometry_dimension failed: sorry, cowardly quitting\n\n");
2624 }
2625 }
2626 if (ret == 0)
2627 {
2628 if (verbose)
2629 {
2630 fprintf(stderr, "Source Database: has passed all checks.\n\n");
2631 }
2632 }
2633 }
2634 else
2635 {
2636 if ((strlen(source_config->dem_path) > 0) && (strcmp(source_config->dem_path,".xyz") != 1))
2637 {
2638 if (verbose)
2639 {
2640 fprintf(stderr,"-E-> command_check_source_db: preconditions failed for check_source_db [%s(%s)]\n\t source[%s] \n",source_config->dem_table, source_config->dem_geometry,source_config->dem_path);
2641 }
2642 }
2643 }
2644 // -- -- ---------------------------------- --
2645 return ret;
2646 }
2647 // -- -- ---------------------------------- --
2648 // Checking the status of the Dem-Database
2649 // - used by differenct command types
2650 // -- -- ---------------------------------- --
2651 static int
command_check_dem_db(sqlite3 * db_handle,struct config_dem * dem_config,struct config_dem * source_config,int verbose)2652 command_check_dem_db(sqlite3 *db_handle, struct config_dem*dem_config, struct config_dem*source_config, int verbose)
2653 {
2654 int ret=0;
2655 double resolution_calc=0.0;
2656 double resolution_dem=dem_config->dem_resolution;
2657 int geometry_type=0;
2658 // -- -- ---------------------------------- --
2659 if ((strlen(dem_config->dem_path) > 0) && (strlen(dem_config->dem_table) > 0) && (strlen(dem_config->dem_geometry) > 0))
2660 {
2661 if (check_geometry_dimension(db_handle,dem_config, &geometry_type, verbose))
2662 {
2663 if (dem_config->dem_rows_count)
2664 {
2665 resolution_calc=(dem_config->dem_extent_maxx-dem_config->dem_extent_minx)*(dem_config->dem_extent_maxy-dem_config->dem_extent_miny)/(double)dem_config->dem_rows_count;
2666 }
2667 if (verbose)
2668 {
2669 fprintf(stderr,"Dem: srid %d\n", dem_config->dem_srid);
2670 if ( (dem_config->default_srid > 0) && (dem_config->default_srid != dem_config->dem_srid) )
2671 {
2672 fprintf(stderr, "Dem: default_srid[%d]\n",dem_config->default_srid);
2673 }
2674 fprintf(stderr,"Dem: extent min x/y(%2.7f,%2.7f)\n\t max x/y(%2.7f,%2.7f)\n",
2675 dem_config->dem_extent_minx,dem_config->dem_extent_miny,
2676 dem_config->dem_extent_maxx,dem_config->dem_extent_maxy);
2677 fprintf(stderr,"Dem: extent width(%2.7f)\n\t height(%2.7f)\n",
2678 (dem_config->dem_extent_maxx-dem_config->dem_extent_minx),
2679 (dem_config->dem_extent_maxy-dem_config->dem_extent_miny));
2680 fprintf(stderr,"Dem: rows_count(%s) %u\n",dem_config->dem_geometry, dem_config->dem_rows_count);
2681 fprintf(stderr,"Dem: resolution(%s) %2.7f\n",dem_config->dem_geometry, resolution_calc);
2682 fprintf(stderr,"Dem: geometry_type(%d) has_z[%d] has_m[%d]\n",geometry_type,dem_config->has_z, dem_config->has_m);
2683 fprintf(stderr,"Dem: spatial_index_enabled[%d]\n",dem_config->has_spatial_index);
2684 }
2685 if (dem_config->has_z)
2686 {// The dem Database Table and geometry-columns exist and contains a z-value dimension.
2687 switch (geometry_type)
2688 {
2689 case GAIA_POINTZ:
2690 case GAIA_POINTZM:
2691 {
2692 if (dem_config->has_spatial_index == 1)
2693 {
2694 if ( (source_config) && (strlen(source_config->dem_path) > 0) && (strlen(source_config->dem_table) > 0))
2695 {// No printing when .xyz file
2696 if (verbose)
2697 {
2698 fprintf(stderr,"Source '%s'\n", source_config->dem_path);
2699 fprintf(stderr," will set %s(%s) Z-Values\n\tfrom nearest POINT found in\n",source_config->dem_table, source_config->dem_geometry);
2700 }
2701 }
2702 if (verbose)
2703 {
2704 fprintf(stderr,"Dem '%s'\n", dem_config->dem_path);
2705 fprintf(stderr," TABLE[%s] with GEOMETRY-Column[%s]\n",dem_config->dem_table, dem_config->dem_geometry);
2706 }
2707 ret = 0;
2708 }
2709 else
2710 {
2711 if (verbose)
2712 {
2713 fprintf(stderr, "Dem '%s'\n", dem_config->dem_path);
2714 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] must be a POINT with a Z-Dimension with a SpatialIndex\n",dem_config->dem_table, dem_config->dem_geometry);
2715 fprintf(stderr, "\t command_check_dem_db failed: sorry, cowardly quitting\n\n");
2716 }
2717 ret = -1;
2718 }
2719 }
2720 break;
2721 default:
2722 if (verbose)
2723 {
2724 fprintf(stderr, "Dem '%s'\n", dem_config->dem_path);
2725 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] must be a POINT with a Z-Dimension\n",dem_config->dem_table, dem_config->dem_geometry);
2726 fprintf(stderr, "\t command_check_dem_db failed: sorry, cowardly quitting\n\n");
2727 }
2728 ret = -1;
2729 break;
2730 }
2731 }
2732 else
2733 {
2734 if (verbose)
2735 {
2736 fprintf(stderr, "Dem '%s'\n", dem_config->dem_path);
2737 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] does not contain a Z-Dimension\n",dem_config->dem_table, dem_config->dem_geometry);
2738 fprintf(stderr, "\t command_check_dem_db failed: sorry, cowardly quitting\n\n");
2739 }
2740 ret = -1;
2741 }
2742 }
2743 else
2744 {// The dem Database Table or geometry-columns does not exist.
2745 if (verbose)
2746 {
2747 fprintf(stderr, "Dem '%s'\n", dem_config->dem_path);
2748 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] not found\n",dem_config->dem_table, dem_config->dem_geometry);
2749 fprintf(stderr, "\t check_geometry_dimension failed: sorry, cowardly quitting\n\n");
2750 }
2751 ret = -1;
2752 }
2753 if (ret == 0)
2754 {
2755 if (resolution_dem <= 0.0)
2756 {
2757 if (verbose)
2758 {
2759 fprintf(stderr, "-W-> -rdem was not set. Using: resolution(%s) %2.7f\n",dem_config->dem_geometry, resolution_calc);
2760 }
2761 resolution_dem=resolution_calc;
2762 }
2763 else
2764 {
2765 if (verbose)
2766 {
2767 fprintf(stderr, "-W-> -rdem was set. Using: resolution(%2.7f), overriding the calculated value: %2.7f\n",resolution_dem, resolution_calc);
2768 }
2769 }
2770 dem_config->dem_resolution=resolution_dem;
2771 if ((source_config) && (source_config->has_z))
2772 {
2773 dem_config->default_srid=source_config->default_srid;
2774 if (verbose)
2775 {
2776 if (dem_config->dem_srid == source_config->default_srid)
2777 {
2778 fprintf(stderr, "Dem srid[%d]: is the same as the Source srid[%d].\n", dem_config->dem_srid,dem_config->default_srid);
2779 if ( ( source_config->dem_extent_minx >= dem_config->dem_extent_minx ) && (source_config->dem_extent_maxx <= dem_config->dem_extent_maxx ) &&
2780 ( source_config->dem_extent_miny >= dem_config->dem_extent_miny ) && (source_config->dem_extent_maxy <= dem_config->dem_extent_maxy ) )
2781 {
2782 fprintf(stderr, "The Source[%s]: is totally within the Dem[%s] area.\n", source_config->dem_geometry,dem_config->dem_geometry);
2783 }
2784 else if ( ( source_config->dem_extent_minx < dem_config->dem_extent_minx ) && (source_config->dem_extent_maxx > dem_config->dem_extent_maxx ) &&
2785 ( source_config->dem_extent_miny < dem_config->dem_extent_miny ) && (source_config->dem_extent_maxy > dem_config->dem_extent_maxy ) )
2786 {
2787 fprintf(stderr, "The Source[%s]: is totally covers the Dem[%s] area.\n", source_config->dem_geometry,dem_config->dem_geometry);
2788 fprintf(stderr, "\t only geometries totally within the Dem area will be updated.\n");
2789 }
2790 else if ( ( ( source_config->dem_extent_minx < dem_config->dem_extent_minx ) || ( source_config->dem_extent_minx > dem_config->dem_extent_maxx ) ) &&
2791 ( ( source_config->dem_extent_maxx > dem_config->dem_extent_maxx ) || ( source_config->dem_extent_maxx < dem_config->dem_extent_minx ) ) &&
2792 ( ( source_config->dem_extent_miny < dem_config->dem_extent_miny ) || (source_config->dem_extent_miny > dem_config->dem_extent_maxy) ) &&
2793 ( ( source_config->dem_extent_maxy > dem_config->dem_extent_maxy ) || ( source_config->dem_extent_maxy < dem_config->dem_extent_miny ) ) )
2794 {
2795 // ?? correct ??
2796 fprintf(stderr, "The Dem[%s]: is totally outside of the Source[%s] area.\n", dem_config->dem_geometry,source_config->dem_geometry);
2797 }
2798 else
2799 {
2800 fprintf(stderr, "The Source[%s]: is partially inside of the Dem[%s] area.\n", source_config->dem_geometry,dem_config->dem_geometry);
2801 }
2802 }
2803 else
2804 {
2805 fprintf(stderr, "Dem default_srid[%d]: is different from the Source default_srid[%d].\n", dem_config->dem_srid,dem_config->default_srid);
2806 fprintf(stderr, "\t When searching for the nearest point, the Source points will be transformed to srid[%d].\n", dem_config->dem_srid);
2807 }
2808 fprintf(stderr, "Dem Database: has passed all checks.\n");
2809 }
2810 }
2811 ret=1;
2812 }
2813 }
2814 else
2815 {
2816 if (strlen(dem_config->dem_path) > 0)
2817 {
2818 if (verbose)
2819 {
2820 fprintf(stderr,"-E-> command_check_dem_db: preconditions failed [%s(%s)] \n",dem_config->dem_table, dem_config->dem_geometry);
2821 }
2822 }
2823 }
2824 // -- -- ---------------------------------- --
2825 return ret;
2826 }
2827 // -- -- ---------------------------------- --
2828 // Implementation of command: updatez
2829 // - from a Table, geometry of Dem
2830 // --> update each z value with z value of
2831 // --> nearest Point of Dem
2832 // -- -- ---------------------------------- --
2833 static int
command_updatez_db(sqlite3 * db_handle,struct config_dem * source_config,struct config_dem * dem_config,int verbose)2834 command_updatez_db(sqlite3 *db_handle, struct config_dem*source_config, struct config_dem*dem_config, int verbose)
2835 {
2836 int ret=0;
2837 char *time_message = NULL;
2838 struct timeval time_start;
2839 struct timeval time_end;
2840 struct timeval time_diff;
2841 char *sql_err = NULL;
2842 int count_total_geometries=0;
2843 int count_changed_geometries=0;
2844 int count_points_total=0;
2845 int count_z_total=0;
2846 int count_m_total=0;
2847
2848 if ((strlen(dem_config->dem_path) > 0) && (strlen(dem_config->dem_table) > 0) && (strlen(dem_config->dem_geometry) > 0) &&
2849 (dem_config->dem_srid > 0) && (dem_config->has_z) &&
2850 (strlen(source_config->dem_path) > 0) && (strlen(source_config->dem_table) > 0) && (strlen(source_config->dem_geometry) > 0) &&
2851 (source_config->default_srid > 0) && (source_config->has_z))
2852 {// The dem Database Table and geometry-columns exist and contains a z-value dimension.
2853 // -- -- ---------------------------------- --
2854 if (verbose)
2855 {
2856 fprintf(stderr,"-I-> starting update of [%s(%s)] where Z-Values are different.\n",source_config->dem_table, source_config->dem_geometry);
2857 }
2858 /* ok, going to convert */
2859 /* the complete operation is handled as an unique SQL Transaction */
2860 gettimeofday(&time_start, 0);
2861 if (sqlite3_exec(db_handle, "BEGIN", NULL, NULL, &sql_err) == SQLITE_OK)
2862 {
2863 if (retrieve_geometries(db_handle, source_config, dem_config, &count_total_geometries,&count_changed_geometries,&count_points_total,&count_z_total,&count_m_total, verbose) )
2864 {
2865 /* committing the pending SQL Transaction */
2866 if (sqlite3_exec(db_handle, "COMMIT", NULL, NULL, &sql_err) == SQLITE_OK)
2867 {
2868 ret = 0;
2869 }
2870 else
2871 {
2872 if (verbose)
2873 {
2874 fprintf(stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
2875 }
2876 sqlite3_free(sql_err);
2877 if (sql_err)
2878 {
2879 sqlite3_free(sql_err);
2880 }
2881 ret = -1;
2882 }
2883 }
2884 else
2885 {
2886 ret = -1;
2887 if (sqlite3_exec(db_handle, "ROLLBACK", NULL, NULL, &sql_err) == SQLITE_OK)
2888 {
2889 }
2890 if (sql_err)
2891 {
2892 sqlite3_free(sql_err);
2893 }
2894 if (verbose)
2895 {
2896 fprintf(stderr, "DB '%s'\n", source_config->dem_path);
2897 fprintf(stderr, "TABLE[%s] or GEOMETRY-Column[%s] error during UPDATE\n",source_config->dem_table, source_config->dem_geometry);
2898 fprintf(stderr, "*** ERROR: conversion failed\n\n");
2899 }
2900 }
2901 gettimeofday(&time_end, 0);
2902 timeval_subtract(&time_diff,&time_end,&time_start,&time_message);
2903 if (ret == 0)
2904 {
2905 if (verbose)
2906 {
2907 fprintf(stderr,"-I-> geometries total[%d] changed[%d] ; points total[%d] changed z[%d] changed m[%d]\n",count_total_geometries,count_changed_geometries,count_points_total,count_z_total,count_m_total);
2908 fprintf(stderr,"\tDatabase-file successfully updated found, changed, Z-Values !!!\n");
2909 fprintf(stderr,"%s\n\n", time_message);
2910 }
2911 }
2912 }
2913 else
2914 {
2915 if (verbose)
2916 {
2917 fprintf(stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
2918 }
2919 sqlite3_free(sql_err);
2920 if (sql_err)
2921 {
2922 sqlite3_free(sql_err);
2923 }
2924 ret = -1;
2925 }
2926 }
2927 else
2928 {// preconditions not fulfilled
2929 if (verbose)
2930 {
2931 fprintf(stderr,"-E-> command_updatez_db: preconditions failed [%s(%s)] \n",source_config->dem_table, source_config->dem_geometry);
2932 }
2933 }
2934 // -- -- ---------------------------------- --
2935 if (time_message)
2936 {
2937 sqlite3_free(time_message);
2938 time_message = NULL;
2939 }
2940 // -- -- ---------------------------------- --
2941 return ret;
2942 }
2943 // -- -- ---------------------------------- --
2944 // Implementation of command: fetchz
2945 // - from a given srid, point_x,point_y
2946 // --> return point_z value
2947 // -- -- ---------------------------------- --
2948 static int
command_fetchz(sqlite3 * db_handle,struct config_dem * dem_config,int verbose)2949 command_fetchz(sqlite3 *db_handle, struct config_dem *dem_config, int verbose)
2950 {
2951 int ret=0;
2952 char *time_message = NULL;
2953 struct timeval time_start;
2954 struct timeval time_end;
2955 struct timeval time_diff;
2956 // -- -- ---------------------------------- --
2957 if ( (dem_config->fetchz_x != 0.0) && (dem_config->fetchz_x != dem_config->fetchz_y) && (dem_config->default_srid > 0) && (dem_config->dem_srid > 0))
2958 {
2959 if (verbose)
2960 {
2961 fprintf(stderr, "FetchZ modus: with default_srid[%d] x[%2.7f] y[%2.7f] has_m[%d]\n",dem_config->default_srid,dem_config->fetchz_x,dem_config->fetchz_y,dem_config->has_m);
2962 }
2963 gettimeofday(&time_start, 0);
2964 if (callFetchZ(db_handle,dem_config,verbose) )
2965 {
2966 ret=1;
2967 gettimeofday(&time_end, 0);
2968 timeval_subtract(&time_diff,&time_end,&time_start,&time_message);
2969 if (verbose)
2970 {
2971 if (dem_config->has_m)
2972 {
2973 fprintf(stderr, "FetchZ modus: with dem_srid[%d] x[%2.7f] y[%2.7f] z[%2.7f] m[%2.7f]\n",dem_config->dem_srid,dem_config->fetchz_x,dem_config->fetchz_y,dem_config->dem_z,dem_config->dem_m);
2974 fprintf(stderr,"%s\n", time_message);
2975 }
2976 else
2977 {
2978 fprintf(stderr, "FetchZ modus: with dem_srid[%d] x[%2.7f] y[%2.7f] z[%2.7f]\n",dem_config->dem_srid,dem_config->fetchz_x,dem_config->fetchz_y,dem_config->dem_z);
2979 fprintf(stderr,"%s\n", time_message);
2980 }
2981 }
2982 else
2983 {// Output for bash
2984 if (dem_config->has_m)
2985 {
2986 printf("%2.7f %2.7f\n", dem_config->dem_z,dem_config->dem_m);
2987 }
2988 else
2989 {
2990 printf("%2.7f\n", dem_config->dem_z);
2991 }
2992 }
2993 }
2994 else
2995 {
2996 // callFetchZ failed
2997 }
2998 }
2999 else
3000 {
3001 // preconditions failed
3002 if (verbose)
3003 {
3004 if ( dem_config->fetchz_x == 0.0)
3005 {
3006 fprintf(stderr, "did you forget setting the -fetchz_x argument ?\n");
3007 }
3008 if ( dem_config->fetchz_y == 0.0)
3009 {
3010 fprintf(stderr, "did you forget setting the -fetchz_y argument ?\n");
3011 }
3012 if ( dem_config->default_srid <= 0)
3013 {
3014 fprintf(stderr, "did you forget setting the -default_srid argument ?\n");
3015 }
3016 if ( dem_config->dem_srid <= 0)
3017 {
3018 fprintf(stderr, "The dem-srid is invalid\n");
3019 }
3020 fprintf(stderr, "-E command_fetchz: sorry, cowardly quitting\n\n");
3021 }
3022 }
3023 // -- -- ---------------------------------- --
3024 if (time_message)
3025 {
3026 sqlite3_free(time_message);
3027 time_message = NULL;
3028 }
3029 // -- -- ---------------------------------- --
3030 return ret;
3031 }
3032 // -- -- ---------------------------------- --
3033 // Implementation of command: fetchz
3034 // - from a given srid, point_x,point_y
3035 // --> return point_z value
3036 // -- -- ---------------------------------- --
3037 static int
command_dem_create(sqlite3 ** db_handle,void * cache,struct config_dem * source_config,struct config_dem * dem_config,int verbose)3038 command_dem_create(sqlite3 **db_handle, void *cache, struct config_dem *source_config, struct config_dem *dem_config, int verbose)
3039 {
3040 int ret=0;
3041 char *time_message = NULL;
3042 struct timeval time_start;
3043 struct timeval time_end;
3044 struct timeval time_diff;
3045 int count_xyz_files=0;
3046 // -- -- ---------------------------------- --
3047 if (cache)
3048 {
3049 if ( dem_config->dem_srid <= 0)
3050 {
3051 dem_config->dem_srid=dem_config->default_srid;
3052 }
3053 if ((strlen(dem_config->dem_path) > 0) && (strlen(dem_config->dem_table) > 0) && (strlen(dem_config->dem_geometry) > 0) && (dem_config->dem_srid > 0))
3054 {
3055 gettimeofday(&time_start, 0);
3056 if (create_dem_db(dem_config->dem_path, db_handle, cache, dem_config->dem_table, dem_config->dem_geometry,verbose))
3057 {
3058 if (verbose)
3059 {
3060 fprintf(stderr,"-I-> command_dem_createt: created [%s] \n", dem_config->dem_path);
3061 }
3062 if (collect_xyz_files(*db_handle,source_config->dem_path, &count_xyz_files, 0) == 1)
3063 {
3064 dem_config->dem_rows_count=0;
3065 if (import_xyz(*db_handle, dem_config,count_xyz_files,verbose))
3066 {// Import completed correctly
3067 gettimeofday(&time_end, 0);
3068 timeval_subtract(&time_diff,&time_end,&time_start,&time_message);
3069 if (verbose)
3070 {
3071 fprintf(stderr,"%s\n", time_message);
3072 }
3073 gettimeofday(&time_start, 0);
3074 if (recover_geometry_dem(*db_handle, dem_config,verbose))
3075 {// Task completed correctly
3076 }
3077 else
3078 {// Task failed
3079 if (verbose)
3080 {
3081 fprintf(stderr,"-W-> command_dem_created: recover_geometry_dem failed [%s(%s)] srid[%d] \n", dem_config->dem_table, dem_config->dem_geometry, dem_config->dem_srid);
3082 }
3083 }
3084 // Sniff the results, set schema_dem to 'main'
3085 dem_config->schema=source_config->schema;
3086 source_config->schema=NULL;
3087 gettimeofday(&time_end, 0);
3088 timeval_subtract(&time_diff,&time_end,&time_start,&time_message);
3089 if (verbose)
3090 {
3091 fprintf(stderr,"%s\n", time_message);
3092 }
3093 }
3094 else
3095 {// Import failed
3096 if (verbose)
3097 {
3098 fprintf(stderr,"-W-> command_dem_created: import_xyz failed [%d] [%s] \n", count_xyz_files,source_config->dem_path);
3099 }
3100 }
3101 }
3102 }
3103 else
3104 {
3105 // Database exits or cannot be created
3106 if (verbose)
3107 {
3108 fprintf(stderr, "Dem '%s'\n", dem_config->dem_path);
3109 fprintf(stderr, "Database exists and will not be overwritten, use -import_xyz to add new data\n");
3110 fprintf(stderr, "-E-> command_dem_create: sorry, cowardly quitting\n\n");
3111 }
3112 }
3113 }
3114 else
3115 {
3116 // preconditions failed
3117 if (verbose)
3118 {
3119 if (strlen(dem_config->dem_path) <= 0)
3120 {
3121 fprintf(stderr, "did you forget setting the -ddem argument ?\n");
3122 }
3123 if (strlen(dem_config->dem_table) <= 0)
3124 {
3125 fprintf(stderr, "did you forget setting the -tdem argument ?\n");
3126 }
3127 if (strlen(dem_config->dem_geometry) <= 0)
3128 {
3129 fprintf(stderr, "did you forget setting the -gdem argument ?\n");
3130 }
3131 if ( dem_config->default_srid <= 0)
3132 {
3133 fprintf(stderr, "did you forget setting the -default_srid argument ?\n");
3134 }
3135 if ( dem_config->dem_srid <= 0)
3136 {
3137 fprintf(stderr, "The dem-srid is invalid\n");
3138 }
3139 fprintf(stderr, "-E command_fetchz: sorry, cowardly quitting\n\n");
3140 }
3141 }
3142 }
3143 // -- -- ---------------------------------- --
3144 if (time_message)
3145 {
3146 sqlite3_free(time_message);
3147 time_message = NULL;
3148 }
3149 // -- -- ---------------------------------- --
3150 return ret;
3151 }
3152 // -- -- ---------------------------------- --
3153 // Implementation of command: -import_xyz
3154 // - from a given srid, point_x,point_y
3155 // --> return point_z value
3156 // -- -- ---------------------------------- --
3157 static int
command_import_xyz(sqlite3 * db_handle,struct config_dem * source_config,struct config_dem * dem_config,int verbose)3158 command_import_xyz(sqlite3 *db_handle, struct config_dem *source_config, struct config_dem *dem_config, int verbose)
3159 {
3160 int ret=0;
3161 char *time_message = NULL;
3162 char *sql_statement = NULL;
3163 char *err_msg = NULL;;
3164 struct timeval time_start;
3165 struct timeval time_end;
3166 struct timeval time_diff;
3167 int count_xyz_files=0;
3168 // -- -- ---------------------------------- --
3169 if ((strlen(source_config->dem_path) > 0) && (strlen(dem_config->dem_path) > 0) && (strlen(dem_config->dem_table) > 0) && (strlen(dem_config->dem_geometry) > 0))
3170 {
3171 if ((dem_config->has_z) && (dem_config->dem_srid > 0))
3172 {
3173 if (db_handle)
3174 {
3175 gettimeofday(&time_start, 0);
3176 if (verbose)
3177 {
3178 fprintf(stderr, "-import_xyz: with srid[%d] .xyz[%s] \n",source_config->default_srid,source_config->dem_path);
3179 }
3180 if (collect_xyz_files(db_handle,source_config->dem_path, &count_xyz_files, 0) == 1)
3181 {
3182 dem_config->dem_rows_count=0; // Set to 0, just in case
3183 if (import_xyz(db_handle, dem_config,count_xyz_files,verbose))
3184 {// Import completed correctly
3185 gettimeofday(&time_end, 0);
3186 timeval_subtract(&time_diff,&time_end,&time_start,&time_message);
3187 if (verbose)
3188 {
3189 fprintf(stderr,"%s\n", time_message);
3190 }
3191 gettimeofday(&time_start, 0);
3192 if (verbose)
3193 {
3194 fprintf(stderr,"UpdateLayerStatistics: %s(%s)\n", dem_config->dem_table,dem_config->dem_geometry);
3195 }
3196 sql_statement = sqlite3_mprintf("SELECT UpdateLayerStatistics(%Q, %Q)", dem_config->dem_table,dem_config->dem_geometry);
3197 int ret_update = sqlite3_exec(db_handle, sql_statement, NULL, NULL, &err_msg);
3198 sqlite3_free(sql_statement);
3199 if (ret_update != SQLITE_OK)
3200 {
3201 fprintf(stderr, "UpdateLayerStatistics error: %s\n", err_msg);
3202 sqlite3_free(err_msg);
3203 }
3204 else
3205 {
3206 ret=1;
3207 }
3208 gettimeofday(&time_end, 0);
3209 timeval_subtract(&time_diff,&time_end,&time_start,&time_message);
3210 if (verbose)
3211 {
3212 fprintf(stderr,"%s\n", time_message);
3213 }
3214 }
3215 }
3216 }
3217 }
3218 }
3219 // -- -- ---------------------------------- --
3220 if (time_message)
3221 {
3222 sqlite3_free(time_message);
3223 time_message = NULL;
3224 }
3225 // -- -- ---------------------------------- --
3226 return ret;
3227 }
3228 // -- -- ---------------------------------- --
3229 // Main
3230 // Commands
3231 // - sniff
3232 // -> allows the user to prepair the 'update' command
3233 // -> Source and Dem can be done separately or together
3234 // - update
3235 // -- -- ---------------------------------- --
3236 int
main(int argc,char * argv[])3237 main(int argc, char *argv[])
3238 {
3239 /* the MAIN function simply perform arguments checking */
3240 sqlite3 *db_handle = NULL;
3241 char *schema_db = "main";
3242 char *schema_dem = "db_dem";
3243 char *dem_geometry_default = "dem_point";
3244 void *cache = NULL;
3245 int verbose=0;
3246 int copy_m = 1;
3247 int next_arg = ARG_NONE;
3248 int i_command_type=CMD_DEM_SNIFF;
3249 int i_sniff_on=0;
3250 struct config_dem dem_config;
3251 struct config_dem source_config;
3252 int save_conf=0;
3253 int exit_code=1; // unix_exit_code: 0=correct, 1=error
3254 int i=0;
3255 int error = 0;
3256 // -- -- ---------------------------------- --
3257 // Will look for conf [not an error if nothing found]
3258 // - if not found, all arguments must be set
3259 // -- -- ---------------------------------- --
3260 char *dem_configfile = "spatialite_dem.conf";
3261 char *spatialite_dem = getenv("SPATIALITE_DEM");
3262 // -- -- ---------------------------------- --
3263 // Reading the configuration, if found
3264 // - setting default values
3265 // -- -- ---------------------------------- --
3266 if (spatialite_dem)
3267 {
3268 dem_configfile=spatialite_dem;
3269 }
3270 // -- -- ---------------------------------- --
3271 // Warning, if non default, conf is given but not found
3272 // -- -- ---------------------------------- --
3273 dem_config = get_demconfig(dem_configfile,1);
3274 dem_config.config_type = CONF_TYPE_DEM; // dem
3275 dem_config.schema = schema_dem; // dem
3276 // -- -- ---------------------------------- --
3277 // No external source config
3278 // - returns default values only
3279 // -- -- ---------------------------------- --
3280 source_config = get_demconfig(NULL,0);
3281 source_config.config_type = CONF_TYPE_SOURCE; // source
3282 source_config.schema = schema_db; // source
3283 // -- -- ---------------------------------- --
3284 if (strlen(dem_config.dem_path) > 0)
3285 {
3286 if (dem_config.dem_srid > 0)
3287 {
3288 source_config.dem_srid=dem_config.dem_srid;
3289 }
3290 if (dem_config.default_srid > 0)
3291 {
3292 source_config.default_srid=dem_config.default_srid;
3293 }
3294 }
3295 // -- -- ---------------------------------- --
3296 // Reading the arguments
3297 // -- -- ---------------------------------- --
3298 for (i = 1; i < argc; i++)
3299 {
3300 // parsing the invocation arguments
3301 if (next_arg != ARG_NONE)
3302 {
3303 switch (next_arg)
3304 {
3305 case ARG_DB_PATH:
3306 strcpy(source_config.dem_path,argv[i]);
3307 break;
3308 case ARG_TABLE:
3309 strcpy(source_config.dem_table,argv[i]);
3310 break;
3311 case ARG_COL:
3312 strcpy(source_config.dem_geometry,argv[i]);
3313 break;
3314 case ARG_DEM_PATH:
3315 strcpy(dem_config.dem_path,argv[i]);
3316 break;
3317 case ARG_TABLE_DEM:
3318 strcpy(dem_config.dem_table,argv[i]);
3319 break;
3320 case ARG_COL_DEM:
3321 strcpy(dem_config.dem_geometry,argv[i]);
3322 break;
3323 case ARG_RESOLUTION_DEM:
3324 // this will override the calculated value (which may not be correct)
3325 // - it also gives the user the choice to change the area around a point to search for.
3326 dem_config.dem_resolution = atof(argv[i]);
3327 break;
3328 case ARG_COPY_M:
3329 copy_m = atoi(argv[i]);
3330 if (copy_m != 1 )
3331 copy_m=0;
3332 break;
3333 case ARG_FETCHZ_X:
3334 dem_config.fetchz_x = atof(argv[i]);
3335 break;
3336 case ARG_FETCHZ_Y:
3337 dem_config.fetchz_y = atof(argv[i]);
3338 break;
3339 case ARG_FETCHZ_XY:
3340 dem_config.fetchz_x = atof(argv[i++]);
3341 dem_config.fetchz_y = atof(argv[i]);
3342 break;
3343 case ARG_DEFAULT_SRID:
3344 source_config.default_srid = atoi(argv[i]);
3345 dem_config.default_srid = atoi(argv[i]);
3346 break;
3347 };
3348 next_arg = ARG_NONE;
3349 continue;
3350 }
3351 if (strcasecmp (argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0)
3352 {
3353 do_help ();
3354 return exit_code;
3355 }
3356 if (strcmp(argv[i], "-d") == 0)
3357 {
3358 next_arg = ARG_DB_PATH;
3359 continue;
3360 }
3361 if (strcasecmp (argv[i], "--db-path") == 0)
3362 {
3363 next_arg = ARG_DB_PATH;
3364 continue;
3365 }
3366 if (strcasecmp (argv[i], "--table") == 0)
3367 {
3368 next_arg = ARG_TABLE;
3369 continue;
3370 }
3371 if (strcmp(argv[i], "-t") == 0)
3372 {
3373 next_arg = ARG_TABLE;
3374 continue;
3375 }
3376 if (strcasecmp (argv[i], "--geometry-column") == 0)
3377 {
3378 next_arg = ARG_COL;
3379 continue;
3380 }
3381 if (strcmp(argv[i], "-g") == 0)
3382 {
3383 next_arg = ARG_COL;
3384 continue;
3385 }
3386 if (strcasecmp (argv[i], "--dem-path") == 0)
3387 {
3388 next_arg = ARG_DEM_PATH;
3389 continue;
3390 }
3391 if (strcmp(argv[i], "-ddem") == 0)
3392 {
3393 next_arg = ARG_DEM_PATH;
3394 continue;
3395 }
3396 if (strcasecmp (argv[i], "--table-dem") == 0)
3397 {
3398 next_arg = ARG_TABLE_DEM;
3399 continue;
3400 }
3401 if (strcmp(argv[i], "-tdem") == 0)
3402 {
3403 next_arg = ARG_TABLE_DEM;
3404 continue;
3405 }
3406 if (strcasecmp (argv[i], "--geometry-dem-column") == 0)
3407 {
3408 next_arg = ARG_COL_DEM;
3409 continue;
3410 }
3411 if (strcmp(argv[i], "-gdem") == 0)
3412 {
3413 next_arg = ARG_COL_DEM;
3414 continue;
3415 }
3416 if (strcasecmp (argv[i], "--dem-resolution") == 0)
3417 {
3418 next_arg = ARG_RESOLUTION_DEM;
3419 continue;
3420 }
3421 if (strcmp(argv[i], "-rdem") == 0)
3422 {
3423 next_arg = ARG_RESOLUTION_DEM;
3424 continue;
3425 }
3426 if (strcasecmp (argv[i], "--m-copy") == 0)
3427 {
3428 next_arg = ARG_COPY_M;
3429 continue;
3430 }
3431 if (strcmp(argv[i], "-mdem") == 0)
3432 {
3433 next_arg = ARG_COPY_M;
3434 continue;
3435 }
3436 if (strcmp(argv[i], "-sniff") == 0)
3437 {
3438 i_command_type=CMD_DEM_SNIFF;
3439 i_sniff_on=1;
3440 continue;
3441 }
3442 if (strcmp(argv[i], "-updatez") == 0)
3443 {
3444 i_command_type=CMD_DEM_UPDATEZ;
3445 continue;
3446 }
3447 if (strcmp(argv[i], "-fetchz") == 0)
3448 {
3449 i_command_type=CMD_DEM_FETCHZ;
3450 continue;
3451 }
3452 if (strcmp(argv[i], "-create_dem") == 0)
3453 {
3454 i_command_type=CMD_DEM_CREATE;
3455 continue;
3456 }
3457 if (strcmp(argv[i], "-import_xyz") == 0)
3458 {
3459 i_command_type=CMD_DEM_IMPORT_XYZ;
3460 continue;
3461 }
3462 if (strcmp(argv[i], "-fetchz_x") == 0)
3463 {
3464 next_arg = ARG_FETCHZ_X;
3465 continue;
3466 }
3467 if (strcmp(argv[i], "-fetchz_y") == 0)
3468 {
3469 next_arg = ARG_FETCHZ_Y;
3470 continue;
3471 }
3472 if (strcmp(argv[i], "-fetchz_xy") == 0)
3473 {
3474 next_arg = ARG_FETCHZ_XY;
3475 continue;
3476 }
3477 if ( (strcmp(argv[i], "-default_srid") == 0) || (strcmp(argv[i], "--srid") == 0) )
3478 {
3479 next_arg = ARG_DEFAULT_SRID;
3480 continue;
3481 }
3482 if ( (strcmp(argv[i], "-v") == 0) || (strcmp(argv[i], "--verbose") == 0) )
3483 {
3484 verbose = 1;
3485 continue;
3486 }
3487 if ( (strcmp(argv[i], "-save_conf") == 0) || (strcmp(argv[i], "--dem_conf") == 0) )
3488 {
3489 save_conf=1;
3490 continue;
3491 }
3492 fprintf(stderr, "unknown argument: %s\n", argv[i]);
3493 error = 1;
3494 }
3495 // -- -- ---------------------------------- --
3496 // Setting the default argument of dem_geometry
3497 // - dem_point
3498 // -- -- ---------------------------------- --
3499 if (strlen(dem_config.dem_geometry) == 0)
3500 {
3501 strcpy(dem_config.dem_geometry,dem_geometry_default);
3502 }
3503 // -- -- ---------------------------------- --
3504 // checking, resetting the arguments
3505 // -- -- ---------------------------------- --
3506 if ( (i_command_type == CMD_DEM_SNIFF) || (i_sniff_on == 1) )
3507 {
3508 if ((strlen(dem_config.dem_path) > 0) && (strlen(dem_config.dem_table) > 0) && (strlen(dem_config.dem_geometry) > 0) &&
3509 (dem_config.fetchz_x != 0.0) && (dem_config.fetchz_x != dem_config.fetchz_y) )
3510 {// -fetchz was intended but forgotten, be tolerant to the lazy user
3511 i_command_type = CMD_DEM_FETCHZ;
3512 }
3513 // for -sniff -v is always active
3514 verbose=1;
3515 }
3516 if (verbose)
3517 {
3518 if (strlen(dem_config.dem_path) == 0)
3519 {
3520 if (i_command_type == CMD_DEM_UPDATEZ)
3521 {
3522 fprintf(stderr, "did you forget setting the --dem-path argument ?\n");
3523 error = 1;
3524 }
3525 else
3526 {
3527 fprintf(stderr, "Warning: --dem-path argument has not been set [assuming -sniff only]\n");
3528 }
3529 }
3530 if (strlen(source_config.dem_path) == 0)
3531 {
3532 if (i_command_type == CMD_DEM_UPDATEZ)
3533 {
3534 fprintf(stderr, "did you forget setting the --db-path argument ?\n");
3535 error = 1;
3536 }
3537 }
3538 }
3539 // -- -- ---------------------------------- --
3540 // Bale out on errors
3541 // -- -- ---------------------------------- --
3542 if (error)
3543 {
3544 do_help();
3545 return exit_code;
3546 }
3547 // -- -- ---------------------------------- --
3548 // opening the DB
3549 // - method 1: create a new Database
3550 // - method 2: input is not a Database, only Dem
3551 // - method 3: both input and dem are a Database, when given
3552 // -- -- ---------------------------------- --
3553 cache = spatialite_alloc_connection();
3554 if (i_command_type == CMD_DEM_CREATE)
3555 {
3556 if (command_dem_create(&db_handle, cache, &source_config, &dem_config, verbose))
3557 {
3558 // Sniff the results, set schema_dem to 'main'
3559 i_command_type = CMD_DEM_SNIFF;
3560 dem_config.schema=schema_db;
3561 }
3562 }
3563 else
3564 {
3565 if (i_command_type == CMD_DEM_IMPORT_XYZ)
3566 {// Open the Dem-Database as the main source [not attached ; since db_path=import.xyz]
3567 open_db(&db_handle, cache, NULL, &dem_config,verbose);
3568 }
3569 else
3570 {// Open the Dem-Database as the main source if there is no source [otherwise attached, with source as main ]
3571 open_db(&db_handle, cache, &source_config, &dem_config,verbose);
3572 }
3573 }
3574 // -- -- ---------------------------------- --
3575 // Bale out if no connection
3576 // -- -- ---------------------------------- --
3577 if (!db_handle)
3578 {
3579 spatialite_cleanup_ex(cache);
3580 cache=NULL;
3581 return exit_code;
3582 }
3583 // -- -- ---------------------------------- --
3584 // checking the Source-Database
3585 // -- -- ---------------------------------- --
3586 command_check_source_db(db_handle,&source_config, verbose);
3587 // -- -- ---------------------------------- --
3588 // checking the Dem-Database
3589 // -- -- ---------------------------------- --
3590 if (command_check_dem_db(db_handle,&dem_config, &source_config, verbose) )
3591 {
3592 if ( save_conf == 1)
3593 {
3594 if (write_demconfig(dem_configfile, dem_config))
3595 {
3596 fprintf(stderr, "Dem-conf: with default_srid[%d] was saved to\n\t[%s].\n",dem_config.default_srid,dem_configfile);
3597 }
3598 }
3599 }
3600 // -- -- ---------------------------------- --
3601 // After checking, the called functions
3602 // will check the result before running
3603 // -- -- ---------------------------------- --
3604 if ( (i_sniff_on == 1) && (dem_config.has_z) && (source_config.has_z) )
3605 {
3606 if (verbose)
3607 {
3608 fprintf(stderr, "Sniffing modus: All pre-conditions have been fulfilled.\n");
3609 fprintf(stderr, "\t to start update, use the '-updatez' parameter without '-sniff'.\n");
3610 fprintf(stderr, "\t to save dem-conf, use the '-save_conf' parameter.\n");
3611 }
3612 exit_code = 0; // correct
3613 }
3614 if (i_sniff_on == 0)
3615 {
3616 // -- -- ---------------------------------- --
3617 // Run only if 'sniff' is off
3618 // -- -- ---------------------------------- --
3619 // Start --update
3620 // -- -- ---------------------------------- --
3621 if (i_command_type == CMD_DEM_UPDATEZ)
3622 {
3623 if (!copy_m)
3624 {// The User desires that m values be ignored
3625 dem_config.has_m=0;
3626 }
3627 if (command_updatez_db(db_handle, &source_config,&dem_config, verbose) )
3628 {
3629 exit_code = 0; // correct
3630 }
3631 }
3632 // -- -- ---------------------------------- --
3633 // Start -import_xyz
3634 // -- -- ---------------------------------- --
3635 if (i_command_type == CMD_DEM_IMPORT_XYZ)
3636 {
3637 if (command_import_xyz(db_handle, &source_config, &dem_config, verbose))
3638 {
3639 exit_code = 0; // correct
3640 }
3641 }
3642 // -- -- ---------------------------------- --
3643 // Start -fetchz
3644 // -- -- ---------------------------------- --
3645 if (i_command_type == CMD_DEM_FETCHZ)
3646 {
3647 if (command_fetchz(db_handle, &dem_config, verbose) )
3648 {
3649 exit_code = 0; // correct
3650 }
3651 }
3652 }
3653 else
3654 {
3655 if (i_command_type == CMD_DEM_UPDATEZ)
3656 {
3657 if (verbose)
3658 {
3659 fprintf(stderr, "Sniffing modus: '-updatez' will not be called.\n");
3660 }
3661 }
3662 else if (i_command_type == CMD_DEM_IMPORT_XYZ)
3663 {
3664 if (verbose)
3665 {
3666 fprintf(stderr, "Sniffing modus: '-import_xyz' will not be called.\n");
3667 }
3668 }
3669 else if (i_command_type == CMD_DEM_FETCHZ)
3670 {
3671 if (verbose)
3672 {
3673 fprintf(stderr, "Sniffing modus: '-fetchz' will not be called.\n");
3674 }
3675 }
3676 }
3677 // -- -- ---------------------------------- --
3678 // Close Application
3679 // - DETACH when needed
3680 // -- -- ---------------------------------- --
3681 if (db_handle)
3682 {
3683 close_db(db_handle,cache, schema_dem);
3684 cache=NULL;
3685 }
3686 return exit_code;
3687 // -- -- ---------------------------------- --
3688 }
3689
3690