PageRenderTime 59ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/otbliblas/apps/txt2las.c

https://bitbucket.org/olahlou/otb
C | 917 lines | 712 code | 93 blank | 112 comment | 537 complexity | 95900601a3201dbfa49f8913af49be4b MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, LGPL-2.0, CC-BY-SA-3.0, BSD-3-Clause, LGPL-2.1
  1. /***************************************************************************
  2. * $Id$
  3. * $Date$
  4. *
  5. * Project: libLAS -- C/C++ read/write library for LAS LIDAR data
  6. * Purpose: ASCII text to LAS translation
  7. * Author: Martin Isenburg isenburg@cs.unc.edu
  8. ***************************************************************************
  9. * Copyright (c) 2007, Martin Isenburg isenburg@cs.unc.edu
  10. *
  11. * See LICENSE.txt in this source distribution for more information.
  12. **************************************************************************/
  13. #include <liblas.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #define LAS_FORMAT_10 0
  18. #define LAS_FORMAT_11 1
  19. #define LAS_FORMAT_12 2
  20. void usage()
  21. {
  22. fprintf(stderr,"----------------------------------------------------------\n");
  23. fprintf(stderr," txt2las (version %s) usage:\n", LAS_GetVersion());
  24. fprintf(stderr,"----------------------------------------------------------\n");
  25. fprintf(stderr,"\n");
  26. fprintf(stderr,"Parse a text file with a given format:\n");
  27. fprintf(stderr," txt2las -parse tsxyz lidar.txt\n");
  28. fprintf(stderr,"\n");
  29. fprintf(stderr,"Set the scale:\n");
  30. fprintf(stderr," txt2las --parse xyz --scale 0.02 -i lidar.txt -o lidar.laz\n");
  31. fprintf(stderr,"\n");
  32. fprintf(stderr,"Set the xyz scale:\n");
  33. fprintf(stderr," txt2las --parse xsysz --verbose --xyz_scale 0.02 0.02 0.01 lidar.txt\n");
  34. fprintf(stderr,"\n");
  35. fprintf(stderr,"----------------------------------------------------------\n");
  36. fprintf(stderr," The '--parse txyz' flag specifies how to format each\n");
  37. fprintf(stderr," each line of the ASCII file. For example, 'txyzia'\n");
  38. fprintf(stderr," means that the first number of each line should be the\n");
  39. fprintf(stderr," gpstime, the next three numbers should be the x, y, and\n");
  40. fprintf(stderr," z coordinate, the next number should be the intensity\n");
  41. fprintf(stderr," and the next number should be the scan angle.\n");
  42. fprintf(stderr," The supported entries are:\n");
  43. fprintf(stderr," a - scan angle\n");
  44. fprintf(stderr," i - intensity\n");
  45. fprintf(stderr," n - number of returns for given pulse\n");
  46. fprintf(stderr," r - number of this return\n");
  47. fprintf(stderr," c - classification\n");
  48. fprintf(stderr," u - user data (does not currently work)\n");
  49. fprintf(stderr," p - point source ID\n");
  50. fprintf(stderr," e - edge of flight line\n");
  51. fprintf(stderr," d - direction of scan flag\n");
  52. fprintf(stderr," R - red channel of RGB color\n");
  53. fprintf(stderr," G - green channel of RGB color\n");
  54. fprintf(stderr," B - blue channel of RGB color\n\n");
  55. fprintf(stderr,"\n----------------------------------------------------------\n");
  56. fprintf(stderr," The '-scale 0.02' flag specifies the quantization. The\n");
  57. fprintf(stderr," default value of 0.01 means that the smallest increment\n");
  58. fprintf(stderr," two between coordinates is 0.01. If measurements are in\n");
  59. fprintf(stderr," meters this corresponds to centimeter accuracy, which is\n");
  60. fprintf(stderr," commonly considered sufficient for LIDAR data.\n");
  61. fprintf(stderr,"\n----------------------------------------------------------\n");
  62. fprintf(stderr," Other parameters such as '--xyz_offset 500000 2000000 0'\n");
  63. fprintf(stderr," or '-xyz_scale 0.02 0.02 0.01' or '-file_creation 67 2003'\n");
  64. fprintf(stderr," or '-system_identifier \"Airborne One Leica 50,000 Hz\"'\n");
  65. fprintf(stderr," or '-generating_software \"TerraScan\"' are available too.\n");
  66. fprintf(stderr, "For more information, see the full documentation for txt2las at:\n"
  67. " http://liblas.org/browser/trunk/doc/txt2las.txt\n");
  68. fprintf(stderr,"----------------------------------------------------------\n");
  69. }
  70. static void VecUpdateMinMax3dv(double min[3], double max[3], const double v[3])
  71. {
  72. if (v[0]<min[0]) min[0]=v[0]; else if (v[0]>max[0]) max[0]=v[0];
  73. if (v[1]<min[1]) min[1]=v[1]; else if (v[1]>max[1]) max[1]=v[1];
  74. if (v[2]<min[2]) min[2]=v[2]; else if (v[2]>max[2]) max[2]=v[2];
  75. }
  76. static void VecCopy3dv(double v[3], const double a[3])
  77. {
  78. v[0] = a[0];
  79. v[1] = a[1];
  80. v[2] = a[2];
  81. }
  82. static int parse(const char* parse_string, const char* line, double* xyz, LASPointH point, double* gps_time)
  83. {
  84. int temp_i;
  85. float temp_f;
  86. const char* p = parse_string;
  87. const char* l = line;
  88. LASColorH color = LASColor_Create();
  89. while (p[0])
  90. {
  91. /* // we expect the x coordinate */
  92. if (p[0] == 'x')
  93. {
  94. /* // first skip white spaces */
  95. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  96. if (l[0] == 0) return FALSE;
  97. if (sscanf(l, "%lf", &(xyz[0])) != 1) return FALSE;
  98. /* // then advance to next white space */
  99. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  100. }
  101. /* // we expect the y coordinate */
  102. else if (p[0] == 'y')
  103. {
  104. /* // first skip white spaces */
  105. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  106. if (l[0] == 0) return FALSE;
  107. if (sscanf(l, "%lf", &(xyz[1])) != 1) return FALSE;
  108. /* // then advance to next white space */
  109. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  110. }
  111. /* // we expect the x coordinate */
  112. else if (p[0] == 'z')
  113. {
  114. /* // first skip white spaces */
  115. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  116. if (l[0] == 0) return FALSE;
  117. if (sscanf(l, "%lf", &(xyz[2])) != 1) return FALSE;
  118. /* // then advance to next white space */
  119. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  120. }
  121. /* // we expect a string or a number that we don't care about */
  122. else if (p[0] == 's')
  123. {
  124. /* // first skip white spaces */
  125. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  126. if (l[0] == 0) return FALSE;
  127. /* // then advance to next white space */
  128. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  129. }
  130. /* // we expect the intensity */
  131. else if (p[0] == 'i')
  132. {
  133. /* // first skip white spaces */
  134. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  135. if (l[0] == 0) return FALSE;
  136. if (sscanf(l, "%f", &temp_f) != 1) return FALSE;
  137. if (temp_f < 0.0f || temp_f > 65535.0f)
  138. fprintf(stderr,
  139. "WARNING: intensity %g is out of range of unsigned short\n",
  140. temp_f);
  141. LASPoint_SetIntensity(point, (int)temp_f);
  142. /* point->intensity = (unsigned short)temp_f; */
  143. /* // then advance to next white space*/
  144. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  145. }
  146. /* // we expect the scan angle */
  147. else if (p[0] == 'a')
  148. {
  149. /* // first skip white spaces */
  150. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  151. if (l[0] == 0) return FALSE;
  152. if (sscanf(l, "%f", &temp_f) != 1) return FALSE;
  153. if (temp_f < -128.0f || temp_f > 127.0f)
  154. fprintf(stderr,
  155. "WARNING: scan angle %g is out of range of char\n",
  156. temp_f);
  157. LASPoint_SetScanAngleRank(point, (int)temp_f);
  158. /* point->scan_angle_rank = (char)temp_f; */
  159. /* // then advance to next white space*/
  160. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  161. }
  162. /* // we expect the number of returns of given pulse */
  163. else if (p[0] == 'n')
  164. {
  165. /* // first skip white spaces */
  166. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  167. if (l[0] == 0) return FALSE;
  168. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  169. if (temp_i < 0 || temp_i > 7)
  170. fprintf(stderr,
  171. "WARNING: return number %d is out of range of three bits\n",
  172. temp_i);
  173. LASPoint_SetNumberOfReturns(point, temp_i);
  174. /* point->number_of_returns_of_given_pulse = temp_i & 7; */
  175. /* // then advance to next white space */
  176. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  177. }
  178. /* // we expect the number of the return */
  179. else if (p[0] == 'r')
  180. {
  181. /* // first skip white spaces */
  182. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  183. if (l[0] == 0) return FALSE;
  184. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  185. if (temp_i < 0 || temp_i > 7)
  186. fprintf(stderr,
  187. "WARNING: return number %d is out of range of three bits\n",
  188. temp_i);
  189. /* point->return_number = temp_i & 7; */
  190. LASPoint_SetReturnNumber(point, temp_i);
  191. /* // then advance to next white space */
  192. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  193. }
  194. /* // we expect the classification */
  195. else if (p[0] == 'c')
  196. {
  197. /* // first skip white spaces */
  198. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  199. if (l[0] == 0) return FALSE;
  200. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  201. if (temp_i < 0 || temp_i > 255)
  202. fprintf(stderr,
  203. "WARNING: classification %d is out of range of unsigned char\n",
  204. temp_i);
  205. LASPoint_SetClassification(point, temp_i);
  206. /* point->classification = (unsigned char)temp_i; */
  207. /* // then advance to next white space */
  208. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  209. }
  210. /* // we expect the user data */
  211. else if (p[0] == 'u')
  212. {
  213. /* // first skip white spaces */
  214. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  215. if (l[0] == 0) return FALSE;
  216. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  217. if (temp_i < 0 || temp_i > 255)
  218. fprintf(stderr,
  219. "WARNING: user data %d is out of range of unsigned char\n",
  220. temp_i);
  221. LASPoint_SetUserData(point, temp_i);
  222. /* point->user_data = temp_i & 255; */
  223. /* // then advance to next white space */
  224. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  225. }
  226. /* // we expect the point source ID */
  227. else if (p[0] == 'p')
  228. {
  229. /* // first skip white spaces */
  230. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  231. if (l[0] == 0) return FALSE;
  232. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  233. if (temp_i < 0 || temp_i > 65535)
  234. fprintf(stderr,
  235. "WARNING: point source ID %d is out of range of unsigned short\n",
  236. temp_i);
  237. /* point->point_source_ID = temp_i & 65535; */
  238. LASPoint_SetPointSourceId(point, temp_i);
  239. /*// then advance to next white space */
  240. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  241. }
  242. /* // we expect the edge of flight line flag */
  243. else if (p[0] == 'e')
  244. {
  245. /* // first skip white spaces */
  246. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  247. if (l[0] == 0) return FALSE;
  248. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  249. if (temp_i < 0 || temp_i > 1)
  250. fprintf(stderr,
  251. "WARNING: edge of flight line flag %d is out of range of boolean flag\n",
  252. temp_i);
  253. LASPoint_SetFlightLineEdge(point, temp_i ? 1: 0);
  254. /* point->edge_of_flight_line = (temp_i ? 1 : 0); */
  255. /* // then advance to next white space */
  256. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  257. }
  258. /* // we expect the direction of scan flag */
  259. else if (p[0] == 'd')
  260. {
  261. /* // first skip white spaces */
  262. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  263. if (l[0] == 0) return FALSE;
  264. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  265. if (temp_i < 0 || temp_i > 1)
  266. fprintf(stderr,
  267. "WARNING: direction of scan flag %d is out of range of boolean flag\n",
  268. temp_i);
  269. LASPoint_SetScanDirection(point, temp_i ? 1: 0);
  270. /* point->scan_direction_flag = (temp_i ? 1 : 0); */
  271. /* // then advance to next white space */
  272. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  273. }
  274. /* // we expect the gps time */
  275. else if (p[0] == 't')
  276. {
  277. /* // first skip white spaces */
  278. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  279. if (l[0] == 0) return FALSE;
  280. if (sscanf(l, "%lf", gps_time) != 1) return FALSE;
  281. /* // then advance to next white space */
  282. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  283. }
  284. /* // we expect the red channel of the RGB field */
  285. else if (p[0] == 'R')
  286. {
  287. /* // first skip white spaces */
  288. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  289. if (l[0] == 0) return FALSE;
  290. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  291. LASColor_SetRed(color, temp_i);
  292. /* // then advance to next white space */
  293. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  294. }
  295. /* // we expect the green channel of the RGB field */
  296. else if (p[0] == 'G')
  297. {
  298. /* // first skip white spaces */
  299. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  300. if (l[0] == 0) return FALSE;
  301. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  302. LASColor_SetGreen(color, temp_i);
  303. /* // then advance to next white space */
  304. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  305. }
  306. /* // we expect the blue channel of the RGB field */
  307. else if (p[0] == 'B')
  308. {
  309. /* // first skip white spaces */
  310. while (l[0] && (l[0] == ' ' || l[0] == ',' || l[0] == '\t')) l++;
  311. if (l[0] == 0) return FALSE;
  312. if (sscanf(l, "%d", &temp_i) != 1) return FALSE;
  313. LASColor_SetBlue(color, temp_i);
  314. /* // then advance to next white space */
  315. while (l[0] && l[0] != ' ' && l[0] != ',' && l[0] != '\t') l++;
  316. }
  317. else
  318. {
  319. fprintf(stderr, "ERROR: next symbol '%s' unknown in parse control string\n", p);
  320. }
  321. p++;
  322. }
  323. LASPoint_SetColor(point, color);
  324. LASColor_Destroy(color);
  325. return TRUE;
  326. }
  327. int main(int argc, char *argv[])
  328. {
  329. int i;
  330. int dry = FALSE;
  331. int verbose = FALSE;
  332. char* file_name_in = 0;
  333. char* file_name_out = 0;
  334. double xyz_min[3] = {0.0, 0.0, 0.0};
  335. double xyz_max[3] = {0.0, 0.0, 0.0};
  336. double xyz_scale[3] = {0.01,0.01,0.01};
  337. double xyz_offset[3] = {0.0,0.0,0.0};
  338. unsigned int number_of_point_records = 0;
  339. unsigned int number_of_points_by_return[8] = {0,0,0,0,0,0,0,0};
  340. char* parse_string = "xyz";
  341. int file_creation_day = 0;
  342. int file_creation_year = 0;
  343. char* system_identifier = 0;
  344. char* generating_software = 0;
  345. #define MAX_CHARACTERS_PER_LINE 512
  346. char line[MAX_CHARACTERS_PER_LINE];
  347. double xyz[3];
  348. LASPointH point = NULL;
  349. double gps_time;
  350. FILE* file_in = NULL;
  351. char* parse_less = NULL;
  352. LASHeaderH header = NULL;
  353. LASWriterH writer = NULL;
  354. LASError err;
  355. int format = LAS_FORMAT_12;
  356. int xyz_min_quant[3] = {0, 0, 0};
  357. int xyz_max_quant[3] = {0, 0, 0};
  358. double xyz_min_dequant[3] = {0.0, 0.0, 0.0};
  359. double xyz_max_dequant[3] = {0.0, 0.0, 0.0};
  360. for (i = 1; i < argc; i++)
  361. {
  362. if ( strcmp(argv[i],"-h") == 0 ||
  363. strcmp(argv[i],"--help") == 0
  364. )
  365. {
  366. usage();
  367. exit(0);
  368. }
  369. else if ( strcmp(argv[i],"-v") == 0 ||
  370. strcmp(argv[i],"--verbose") == 0
  371. )
  372. {
  373. verbose = TRUE;
  374. }
  375. else if ( strcmp(argv[i],"-d") == 0 ||
  376. strcmp(argv[i],"-dry") == 0 ||
  377. strcmp(argv[i],"--dry") == 0
  378. )
  379. {
  380. dry = TRUE;
  381. }
  382. else if ( strcmp(argv[i],"--parse") == 0 ||
  383. strcmp(argv[i],"-parse") == 0 ||
  384. strcmp(argv[i],"-p") == 0
  385. )
  386. {
  387. i++;
  388. parse_string = argv[i];
  389. }
  390. else if ( strcmp(argv[i],"--scale") == 0 ||
  391. strcmp(argv[i],"-scale") == 0 ||
  392. strcmp(argv[i],"-s") == 0
  393. )
  394. {
  395. i++;
  396. sscanf(argv[i], "%lf", &(xyz_scale[2]));
  397. xyz_scale[0] = xyz_scale[1] = xyz_scale[2];
  398. }
  399. else if ( strcmp(argv[i],"--xyz_scale") == 0 ||
  400. strcmp(argv[i],"-xyz_scale") == 0
  401. )
  402. {
  403. i++;
  404. sscanf(argv[i], "%lf", &(xyz_scale[0]));
  405. i++;
  406. sscanf(argv[i], "%lf", &(xyz_scale[1]));
  407. i++;
  408. sscanf(argv[i], "%lf", &(xyz_scale[2]));
  409. }
  410. else if ( strcmp(argv[i],"--xyz_offset") == 0 ||
  411. strcmp(argv[i],"-xyz_offset") == 0
  412. )
  413. {
  414. i++;
  415. sscanf(argv[i], "%lf", &(xyz_offset[0]));
  416. i++;
  417. sscanf(argv[i], "%lf", &(xyz_offset[1]));
  418. i++;
  419. sscanf(argv[i], "%lf", &(xyz_offset[2]));
  420. }
  421. else if ( strcmp(argv[i],"--input") == 0 ||
  422. strcmp(argv[i],"-input") == 0 ||
  423. strcmp(argv[i],"-i") == 0 ||
  424. strcmp(argv[i],"-in") == 0
  425. )
  426. {
  427. i++;
  428. file_name_in = argv[i];
  429. }
  430. else if ( strcmp(argv[i],"--output") == 0 ||
  431. strcmp(argv[i],"--out") == 0 ||
  432. strcmp(argv[i],"-out") == 0 ||
  433. strcmp(argv[i],"-o") == 0
  434. )
  435. {
  436. i++;
  437. file_name_out = argv[i];
  438. }
  439. else if ( strcmp(argv[i],"--format") == 0 ||
  440. strcmp(argv[i],"-f") == 0 ||
  441. strcmp(argv[i],"-format") == 0
  442. )
  443. {
  444. i++;
  445. if (strcmp(argv[i], "1.0") == 0) {
  446. format = LAS_FORMAT_10;
  447. }
  448. else if (strcmp(argv[i], "1.1") == 0) {
  449. format = LAS_FORMAT_11;
  450. }
  451. else if (strcmp(argv[i], "1.2") == 0) {
  452. format = LAS_FORMAT_12;
  453. }
  454. else {
  455. LASError_Print("Format must be specified as 1.0, 1.1, or 1.2");
  456. }
  457. }
  458. else if ( strcmp(argv[i],"--system_identifier") == 0 ||
  459. strcmp(argv[i],"-system_identifier") == 0 ||
  460. strcmp(argv[i],"-s") == 0 ||
  461. strcmp(argv[i],"-sys_id") == 0)
  462. {
  463. i++;
  464. system_identifier = (char*) malloc(31 * sizeof(char));
  465. strcpy(system_identifier, argv[i]);
  466. }
  467. else if ( strcmp(argv[i],"--generating_software") == 0 ||
  468. strcmp(argv[i],"-generating_software") == 0 ||
  469. strcmp(argv[i],"-g") == 0 ||
  470. strcmp(argv[i],"-gen_soft") == 0)
  471. {
  472. i++;
  473. generating_software = (char*) malloc(31*sizeof(char));
  474. strcpy(generating_software, argv[i]);
  475. }
  476. else if ( strcmp(argv[i],"--file_creation") == 0 ||
  477. strcmp(argv[i],"-file_creation") == 0)
  478. {
  479. i++;
  480. file_creation_day = (unsigned short)atoi(argv[i]);
  481. i++;
  482. file_creation_year = (unsigned short)atoi(argv[i]);
  483. }
  484. else if ( file_name_in == NULL &&
  485. file_name_out == NULL
  486. )
  487. {
  488. file_name_in = argv[i];
  489. }
  490. else if ( file_name_in &&
  491. file_name_out == NULL
  492. )
  493. {
  494. file_name_out = argv[i];
  495. }
  496. else
  497. {
  498. fprintf(stderr, "ERROR: unknown argument '%s'\n",argv[i]);
  499. usage();
  500. exit(1);
  501. }
  502. }
  503. /* create output file name if none specified and no piped output requested */
  504. if (file_name_out == NULL && file_name_in != NULL)
  505. {
  506. int len = (int)strlen(file_name_in);
  507. file_name_out = LASCopyString(file_name_in);
  508. while (len > 0 && file_name_out[len] != '.')
  509. {
  510. len--;
  511. }
  512. file_name_out[len] = '.';
  513. file_name_out[len+1] = 'l';
  514. file_name_out[len+2] = 'a';
  515. file_name_out[len+3] = 's';
  516. file_name_out[len+4] = '\0';
  517. }
  518. /* make sure that input and output are not *both* piped */
  519. if (file_name_in == NULL && file_name_out == NULL)
  520. {
  521. LASError_Print("both input and output filenames are null!");
  522. usage();
  523. exit(1);
  524. }
  525. file_in = fopen(file_name_in, "r");
  526. if (file_in == NULL)
  527. {
  528. LASError_Print("could not open file to read for first pass");
  529. exit(1);
  530. }
  531. /* create a cheaper parse string that only looks for 'x' 'y' 'z' and 'r' */
  532. parse_less = LASCopyString(parse_string);
  533. for (i = 0; i < (int)strlen(parse_string); i++)
  534. {
  535. if (parse_less[i] != 'x' &&
  536. parse_less[i] != 'y' &&
  537. parse_less[i] != 'z' &&
  538. parse_less[i] != 'r')
  539. {
  540. parse_less[i] = 's';
  541. }
  542. }
  543. do
  544. {
  545. parse_less[i] = '\0';
  546. printf("nuking %d for %c\n", i, parse_less[i]);
  547. i--;
  548. } while (parse_less[i] == 's');
  549. /* first pass to figure out the bounding box and number of returns */
  550. if (verbose) {
  551. fprintf(stderr,
  552. "first pass over file '%s' with parse '%s'\n",
  553. file_name_in,
  554. parse_less);
  555. }
  556. /* read the first line */
  557. while (fgets(line, sizeof(char) * MAX_CHARACTERS_PER_LINE, file_in))
  558. {
  559. point = LASPoint_Create();
  560. if (parse(parse_less, line, xyz, point, &gps_time))
  561. {
  562. /* init the bounding box */
  563. VecCopy3dv(xyz_min, xyz);
  564. VecCopy3dv(xyz_max, xyz);
  565. /* mark that we found the first point */
  566. number_of_point_records = 1;
  567. /* create return histogram */
  568. number_of_points_by_return[LASPoint_GetReturnNumber(point)]++;
  569. /* we can stop this loop */
  570. break;
  571. }
  572. else
  573. {
  574. fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n",
  575. line,
  576. parse_less);
  577. }
  578. LASPoint_Destroy(point);
  579. point = NULL;
  580. }
  581. /* did we manage to parse a line? */
  582. if (number_of_point_records != 1)
  583. {
  584. fprintf(stderr, "ERROR: could not parse any lines with '%s'\n",
  585. parse_less);
  586. exit(1);
  587. }
  588. /* loop over the remaining lines */
  589. while (fgets(line, sizeof(char) * MAX_CHARACTERS_PER_LINE, file_in))
  590. {
  591. point = LASPoint_Create();
  592. if (parse(parse_less, line, xyz, point, &gps_time))
  593. {
  594. /* update bounding box */
  595. VecUpdateMinMax3dv(xyz_min, xyz_max, xyz);
  596. /* count points */
  597. number_of_point_records++;
  598. /* create return histogram */
  599. number_of_points_by_return[LASPoint_GetReturnNumber(point)]++;
  600. }
  601. else
  602. {
  603. fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n",
  604. line,
  605. parse_less);
  606. }
  607. LASPoint_Destroy(point);
  608. point = NULL;
  609. }
  610. /* output some stats */
  611. if (verbose)
  612. {
  613. fprintf(stderr,
  614. "npoints %d min %g %g %g max %g %g %g\n",
  615. number_of_point_records,
  616. xyz_min[0],
  617. xyz_min[1],
  618. xyz_min[2],
  619. xyz_max[0],
  620. xyz_max[1],
  621. xyz_max[2]
  622. );
  623. fprintf(stderr,
  624. "return histogram %d %d %d %d %d %d %d %d\n",
  625. number_of_points_by_return[0],
  626. number_of_points_by_return[1],
  627. number_of_points_by_return[2],
  628. number_of_points_by_return[3],
  629. number_of_points_by_return[4],
  630. number_of_points_by_return[5],
  631. number_of_points_by_return[6],
  632. number_of_points_by_return[7]
  633. );
  634. }
  635. /* close the input file */
  636. fclose(file_in);
  637. /* compute bounding box after quantization */
  638. for (i = 0; i < 3; i++)
  639. {
  640. xyz_min_quant[i] = (int)(0.5 + (xyz_min[i] - xyz_offset[i]) / xyz_scale[i]);
  641. xyz_max_quant[i] = (int)(0.5 + (xyz_max[i] - xyz_offset[i]) / xyz_scale[i]);
  642. }
  643. for (i = 0; i < 3; i++)
  644. {
  645. xyz_min_dequant[i] = xyz_offset[i] + (xyz_min_quant[i] * xyz_scale[i]);
  646. xyz_max_dequant[i] = xyz_offset[i] + (xyz_max_quant[i] * xyz_scale[i]);
  647. }
  648. /* make sure there is not sign flip */
  649. for (i = 0; i < 3; i++)
  650. {
  651. if ((xyz_min[i] > 0) != (xyz_min_dequant[i] > 0))
  652. {
  653. fprintf(stderr,
  654. "WARNING: quantization sign flip for %s min coord %g -> %g. use offset or scale up\n",
  655. (i ? (i == 1 ? "y" : "z") : "x"),
  656. xyz_min[i],
  657. xyz_min_dequant[i]
  658. );
  659. }
  660. if ((xyz_max[i] > 0) != (xyz_max_dequant[i] > 0))
  661. {
  662. fprintf(stderr,
  663. "WARNING: quantization sign flip for %s max coord %g -> %g. use offset or scale up\n",
  664. (i ? (i == 1 ? "y" : "z") : "x"),
  665. xyz_max[i],
  666. xyz_max_dequant[i]
  667. );
  668. }
  669. }
  670. /* populate the header */
  671. header = LASHeader_Create();
  672. if (system_identifier) LASHeader_SetSystemId(header, system_identifier);
  673. if (generating_software) LASHeader_SetSoftwareId(header, generating_software);
  674. LASHeader_SetCreationDOY(header, file_creation_day);
  675. LASHeader_SetCreationYear(header, file_creation_year);
  676. if (format == LAS_FORMAT_10) {
  677. LASHeader_SetVersionMinor(header, 0);
  678. } else if (format == LAS_FORMAT_11){
  679. LASHeader_SetVersionMinor(header, 1);
  680. } else if (format == LAS_FORMAT_12) {
  681. LASHeader_SetVersionMinor(header, 2);
  682. }
  683. if (strstr(parse_string,"t") && (strstr(parse_string, "R") || strstr(parse_string, "G") ||strstr(parse_string, "B") ) )
  684. {
  685. fprintf(stderr, "Setting point format to 3, overriding version to 1.2 -- RGB + time\n");
  686. LASHeader_SetDataFormatId(header, 3);
  687. LASHeader_SetVersionMinor(header, 2);
  688. }
  689. else if ((strstr(parse_string, "R") || strstr(parse_string, "G") ||strstr(parse_string, "B") ) )
  690. {
  691. fprintf(stderr, "Setting point format to 2, overriding version to 1.2 -- RGB\n");
  692. LASHeader_SetDataFormatId(header, 2);
  693. LASHeader_SetVersionMinor(header, 2);
  694. }
  695. else if (strstr(parse_string,"t"))
  696. {
  697. fprintf(stderr, "Setting point format to 1\n");
  698. LASHeader_SetDataFormatId(header, 1);
  699. }
  700. else
  701. {
  702. LASHeader_SetDataFormatId(header, 0);
  703. }
  704. LASHeader_SetPointRecordsCount(header, number_of_point_records);
  705. LASHeader_SetScale(header, xyz_scale[0], xyz_scale[1], xyz_scale[2]);
  706. LASHeader_SetOffset(header, xyz_offset[0], xyz_offset[1], xyz_offset[2]);
  707. LASHeader_SetMin(header, xyz_min_dequant[0], xyz_min_dequant[1], xyz_min_dequant[2]);
  708. LASHeader_SetMax(header, xyz_max_dequant[0], xyz_max_dequant[1], xyz_max_dequant[2]);
  709. LASHeader_SetPointRecordsByReturnCount(header, 0, number_of_points_by_return[1]);
  710. LASHeader_SetPointRecordsByReturnCount(header, 1, number_of_points_by_return[2]);
  711. LASHeader_SetPointRecordsByReturnCount(header, 2, number_of_points_by_return[3]);
  712. LASHeader_SetPointRecordsByReturnCount(header, 3, number_of_points_by_return[4]);
  713. LASHeader_SetPointRecordsByReturnCount(header, 4, number_of_points_by_return[5]);
  714. /* reopen input file for the second pass */
  715. file_in = fopen(file_name_in, "r");
  716. if (file_in == 0)
  717. {
  718. fprintf(stderr, "ERROR: could not open '%s' for second pass\n",file_name_in);
  719. exit(1);
  720. }
  721. /*
  722. because the output goes to a file we can do everything in a
  723. single pass and compute the header information along the way
  724. */
  725. /* open output file */
  726. printf("Creating file...\n");
  727. writer = LASWriter_Create(file_name_out, header, LAS_MODE_WRITE);
  728. if (!writer) {
  729. LASError_Print("Could not open file for write mode ");
  730. exit(1);
  731. }
  732. if (verbose) {
  733. fprintf(stderr,
  734. "scanning %s with parse '%s' writing to %s\n",
  735. file_name_in ,
  736. parse_string,
  737. file_name_out
  738. );
  739. }
  740. /* read the first line */
  741. while (fgets(line, sizeof(char) * MAX_CHARACTERS_PER_LINE, file_in))
  742. {
  743. point = LASPoint_Create();
  744. if (parse(parse_string, line, xyz, point, &gps_time))
  745. {
  746. /* init the bounding box */
  747. VecCopy3dv(xyz_min, xyz);
  748. VecCopy3dv(xyz_max, xyz);
  749. /* mark that we found the first point */
  750. number_of_point_records = 1;
  751. /* create return histogram */
  752. number_of_points_by_return[LASPoint_GetReturnNumber(point)]++;
  753. /* compute the quantized x, y, and z values */
  754. LASPoint_SetX(point, xyz[0]);
  755. LASPoint_SetY(point, xyz[1]);
  756. LASPoint_SetZ(point, xyz[2]);
  757. LASPoint_SetTime(point, gps_time);
  758. /* write the first point */
  759. err = LASWriter_WritePoint(writer, point);
  760. if (err) {
  761. LASError_Print("could not write point");
  762. exit(1);
  763. }
  764. /* we can stop this loop */
  765. break;
  766. }
  767. else
  768. {
  769. fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n",
  770. line,
  771. parse_string);
  772. }
  773. LASPoint_Destroy(point);
  774. point = NULL;
  775. }
  776. /* did we manage to parse a line? */
  777. if (number_of_point_records != 1)
  778. {
  779. fprintf(stderr, "ERROR: could not parse any lines with '%s'\n",
  780. parse_less);
  781. exit(1);
  782. }
  783. /* loop over the remaining lines */
  784. while (fgets(line, sizeof(char) * MAX_CHARACTERS_PER_LINE, file_in))
  785. {
  786. point = LASPoint_Create();
  787. if (parse(parse_string, line, xyz, point, &gps_time))
  788. {
  789. /* update bounding box */
  790. VecUpdateMinMax3dv(xyz_min, xyz_max, xyz);
  791. /* count points */
  792. number_of_point_records++;
  793. /* create return histogram */
  794. number_of_points_by_return[LASPoint_GetReturnNumber(point)]++;
  795. /* compute the quantized x, y, and z values */
  796. LASPoint_SetX(point, xyz[0]);
  797. LASPoint_SetY(point, xyz[1]);
  798. LASPoint_SetZ(point, xyz[2]);
  799. LASPoint_SetTime(point, gps_time);
  800. /* write the first point */
  801. err = LASWriter_WritePoint(writer, point);
  802. if (err) {
  803. LASError_Print("could not write point");
  804. exit(1);
  805. }
  806. }
  807. else
  808. {
  809. fprintf(stderr, "WARNING: cannot parse '%s' with '%s'. skipping ...\n",
  810. line,
  811. parse_string);
  812. }
  813. LASPoint_Destroy(point);
  814. point = NULL;
  815. }
  816. /* close up stuff */
  817. fclose(file_in);
  818. LASWriter_Destroy(writer);
  819. if (verbose)
  820. {
  821. fprintf(stderr, "done.\n");
  822. }
  823. return 0;
  824. }