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