BRL-CAD
make_pnts.c
Go to the documentation of this file.
1 /* M A K E _ P N T S . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2009-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libged/make_pnts.c
21  *
22  * The "make_pnts" command makes a point-cloud from a points data file.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 
32 #include "bu/sort.h"
33 #include "bu/units.h"
34 #include "rtgeom.h"
35 #include "wdb.h"
36 
37 #include "./ged_private.h"
38 
39 #define INSERT_COORDINATE_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert) \
40  switch (_control_variable) { \
41  case 'x': \
42  ((struct _structure_type *)point)->v[X] = _variable_to_insert; \
43  break; \
44  case 'y': \
45  ((struct _structure_type *)point)->v[Y] = _variable_to_insert; \
46  break; \
47  case 'z': \
48  ((struct _structure_type *)point)->v[Z] = _variable_to_insert; \
49  break; \
50  }
51 
52 #define INSERT_COLOR_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert) \
53  switch (_control_variable) { \
54  case 'r': \
55  ((struct _structure_type *)point)->c.buc_magic = BU_COLOR_MAGIC; \
56  ((struct _structure_type *)point)->c.buc_rgb[0] = _variable_to_insert; \
57  break; \
58  case 'g': \
59  ((struct _structure_type *)point)->c.buc_rgb[1] = _variable_to_insert; \
60  break; \
61  case 'b': \
62  ((struct _structure_type *)point)->c.buc_rgb[2] = _variable_to_insert; \
63  break; \
64  }
65 
66 #define INSERT_SCALE_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert) \
67  switch (_control_variable) { \
68  case 's': \
69  ((struct _structure_type *)point)->s = _variable_to_insert; \
70  break; \
71  }
72 
73 #define INSERT_NORMAL_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert) \
74  switch (_control_variable) { \
75  case 'i': \
76  ((struct _structure_type *)point)->n[X] = _variable_to_insert; \
77  break; \
78  case 'j': \
79  ((struct _structure_type *)point)->n[Y] = _variable_to_insert; \
80  break; \
81  case 'k': \
82  ((struct _structure_type *)point)->n[Z] = _variable_to_insert; \
83  break; \
84  }
85 
86 static char *p_make_pnts[] = {
87  "Enter point-cloud name: ",
88  "Enter point file path and name: ",
89  "Enter file data format (xyzrgbsijk?): ",
90  "Enter file data units (um|mm|cm|m|km|in|ft|yd|mi)\nor conversion factor from file data units to millimeters: ",
91  "Enter default point size: "
92 };
93 
94 
95 /*
96  * Character compare function used by bu_sort function.
97  */
98 int
99 compare_char(const char *a, const char *b, void *UNUSED(arg))
100 {
101  return (int)(*a - *b);
102 }
103 
104 
105 /*
106  * Validate 'point file data format string', determine and output the
107  * point-cloud type. A valid null terminated string is expected as
108  * input. The function returns GED_ERROR if the format string is
109  * invalid or if null pointers were passed to the function.
110  */
111 int
112 str2type(const char *format_string, rt_pnt_type *pnt_type, struct bu_vls *ged_result_str)
113 {
114  struct bu_vls str = BU_VLS_INIT_ZERO;
115  char *temp_string = (char *)NULL;
116  size_t idx = 0;
117  size_t format_string_length = 0;
118  int ret = GED_OK;
119 
120  if ((format_string == (char *)NULL) || (pnt_type == (rt_pnt_type *)NULL)) {
121  bu_vls_printf(ged_result_str, "NULL pointer(s) passed to function 'str2type'.\n");
122  ret = GED_ERROR;
123  } else {
124  format_string_length = strlen(format_string);
125 
126  /* remove any '?' from format string before testing for point-cloud type */
127  for (idx = 0 ; idx < format_string_length ; idx++) {
128  if (format_string[idx] != '?') {
129  bu_vls_putc(&str, format_string[idx]);
130  }
131  }
132 
133  bu_vls_trimspace(&str);
134 
135  temp_string = bu_vls_addr(&str);
136  bu_sort(temp_string, strlen(temp_string), sizeof(char), (int (*)(const void *a, const void *b, void *arg))compare_char, NULL);
137 
138  if (BU_STR_EQUAL(temp_string, "xyz")) {
139  *pnt_type = RT_PNT_TYPE_PNT;
140  } else if (BU_STR_EQUAL(temp_string, "bgrxyz")) {
141  *pnt_type = RT_PNT_TYPE_COL;
142  } else if (BU_STR_EQUAL(temp_string, "sxyz")) {
143  *pnt_type = RT_PNT_TYPE_SCA;
144  } else if (BU_STR_EQUAL(temp_string, "ijkxyz")) {
145  *pnt_type = RT_PNT_TYPE_NRM;
146  } else if (BU_STR_EQUAL(temp_string, "bgrsxyz")) {
147  *pnt_type = RT_PNT_TYPE_COL_SCA;
148  } else if (BU_STR_EQUAL(temp_string, "bgijkrxyz")) {
149  *pnt_type = RT_PNT_TYPE_COL_NRM;
150  } else if (BU_STR_EQUAL(temp_string, "ijksxyz")) {
151  *pnt_type = RT_PNT_TYPE_SCA_NRM;
152  } else if (BU_STR_EQUAL(temp_string, "bgijkrsxyz")) {
153  *pnt_type = RT_PNT_TYPE_COL_SCA_NRM;
154  } else {
155  bu_vls_printf(ged_result_str, "Invalid format string '%s'", format_string);
156  ret = GED_ERROR;
157  }
158  }
159 
160  bu_vls_free(&str);
161 
162  return ret;
163 }
164 
165 
166 /*
167  * Validate points data file unit string and output conversion factor
168  * to millimeters. If string is not a standard units identifier, the
169  * function assumes a custom conversion factor was specified. A valid
170  * null terminated string is expected as input. The function returns
171  * GED_ERROR if the unit string is invalid or if null pointers were
172  * passed to the function.
173  */
174 int
175 str2mm(const char *units_string, double *conv_factor, struct bu_vls *ged_result_str)
176 {
177  struct bu_vls str = BU_VLS_INIT_ZERO;
178  double tmp_value = 0.0;
179  char *endp = (char *)NULL;
180  int ret = GED_OK;
181 
182  if ((units_string == (char *)NULL) || (conv_factor == (double *)NULL)) {
183  bu_vls_printf(ged_result_str, "NULL pointer(s) passed to function 'str2mm'.\n");
184  ret = GED_ERROR;
185  } else {
186  bu_vls_strcat(&str, units_string);
187  bu_vls_trimspace(&str);
188 
189  tmp_value = strtod(bu_vls_addr(&str), &endp);
190  if ((endp != bu_vls_addr(&str)) && (*endp == '\0')) {
191  /* convert to double success */
192  *conv_factor = tmp_value;
193  } else if ((tmp_value = bu_mm_value(bu_vls_addr(&str))) > 0.0) {
194  *conv_factor = tmp_value;
195  } else {
196  bu_vls_printf(ged_result_str, "Invalid units string '%s'\n", units_string);
197  ret = GED_ERROR;
198  }
199  }
200 
201  bu_vls_free(&str);
202 
203  return ret;
204 }
205 
206 
207 void
208 report_import_error_location(unsigned long int num_doubles_read, unsigned int num_doubles_per_point,
209  unsigned long int start_offset_of_current_double, char field, struct bu_vls *ged_result_str)
210 {
211  /* The num_doubles_read is the number of doubles successfully read. This error
212  * report is for the double where the error occurred, i.e. the next double.
213  */
214  unsigned long int point_number = ceil((num_doubles_read + 1) / (double)num_doubles_per_point);
215 
216  bu_vls_printf(ged_result_str, "Failed reading point %lu field '%c' at file byte %lu.\n",
217  point_number, field, start_offset_of_current_double);
218 }
219 
220 
221 /*
222  * 'make_pnts' command for importing point-cloud data into a 'pnts'
223  * primitive.
224  *
225  * Input values:
226  * argv[1] object name
227  * argv[2] filename with path
228  * argv[3] point data file format string
229  * argv[4] point data file units string or conversion factor to millimeters
230  * argv[5] default size of each point
231  *
232  */
233 int
234 ged_make_pnts(struct ged *gedp, int argc, const char *argv[])
235 {
236  struct directory *dp;
237  struct rt_db_internal internal;
238 
239  rt_pnt_type type;
240  double local2base;
241  unsigned long numPoints = 0;
242  struct rt_pnts_internal *pnts;
243 
244  double defaultSize = 0.0;
245  void *headPoint = NULL;
246 
247  FILE *fp;
248 
249  int temp_string_index = 0; /* index into temp_string, set to first character in temp_string, i.e. the start */
250  unsigned long int num_doubles_read = 0; /* counters of double read from file */
251 
252  int current_character_double = 0; /* flag indicating if current character read is part of a double or delimiter */
253  int previous_character_double = 0; /* flag indicating if previously read character was part of a double or delimiter */
254 
255  unsigned long int num_characters_read_from_file = 0; /* counter of number of characters read from file */
256  unsigned long int start_offset_of_current_double = 0; /* character offset from start of file for current double */
257  int found_double = 0; /* flag indicating if double encountered in file and needs to be processed */
258  int found_eof = 0; /* flag indicating if end-of-file encountered when reading file */
259  int done_processing_format_string = 0; /* flag indicating if loop processing format string should be exited */
260 
261  char *temp_char_ptr = (char *)NULL;
262 
263  int buf = 0; /* raw character read from file */
264  double temp_double = 0.0;
265  char temp_string[1024];
266  int temp_string_size = 1024; /* number of characters that can be stored in temp_string including null terminator character */
267  /* it is expected that the character representation of a double will never exceed this size string */
268  char *endp = (char *)NULL;
269 
270  struct bu_vls format_string = BU_VLS_INIT_ZERO;
271  size_t format_string_index = 0;
272 
273  unsigned int num_doubles_per_point = 0;
274 
275  void *point = NULL;
276 
277  char **prompt;
278 
279  static const char *usage = "point_cloud_name filename_with_path file_format file_data_units default_point_size";
280 
281  prompt = &p_make_pnts[0];
282 
285  GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
286 
287  /* initialize result */
288  bu_vls_trunc(gedp->ged_result_str, 0);
289 
290  if (argc > 6) {
291  bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
292  return GED_ERROR;
293  }
294 
295  /* prompt for point-cloud name */
296  if (argc < 2) {
297  bu_vls_printf(gedp->ged_result_str, "%s", prompt[0]);
298  return GED_MORE;
299  }
300 
301  GED_CHECK_EXISTS(gedp, argv[1], LOOKUP_QUIET, GED_ERROR);
302 
303  /* prompt for data file name with path */
304  if (argc < 3) {
305  bu_vls_printf(gedp->ged_result_str, "%s", prompt[1]);
306  return GED_MORE;
307  }
308 
309  /* prompt for data file format */
310  if (argc < 4) {
311  bu_vls_printf(gedp->ged_result_str, "%s", prompt[2]);
312  return GED_MORE;
313  }
314 
315  /* Validate 'point file data format string' and return point-cloud type. */
316  if (str2type(argv[3], &type, gedp->ged_result_str) == GED_ERROR) {
317  return GED_ERROR;
318  }
319 
320  /* prompt for data file units */
321  if (argc < 5) {
322  bu_vls_printf(gedp->ged_result_str, "%s", prompt[3]);
323  return GED_MORE;
324  }
325 
326  /* Validate the unit string and return conversion factor to millimeters. */
327  if (str2mm(argv[4], &local2base, gedp->ged_result_str) == GED_ERROR) {
328  return GED_ERROR;
329  }
330 
331  /* prompt for default point size */
332  if (argc < 6) {
333  bu_vls_printf(gedp->ged_result_str, "%s", prompt[4]);
334  return GED_MORE;
335  }
336 
337  defaultSize = strtod(argv[5], &endp);
338  if ((endp != argv[5]) && (*endp == '\0')) {
339  /* convert to double success */
340  if (defaultSize < 0.0) {
341  bu_vls_printf(gedp->ged_result_str, "Default point size '%lf' must be non-negative.\n", defaultSize);
342  return GED_ERROR;
343  }
344  } else {
345  bu_vls_printf(gedp->ged_result_str, "Invalid default point size '%s'\n", argv[5]);
346  return GED_ERROR;
347  }
348 
349  bu_vls_strcat(&format_string, argv[3]);
350  bu_vls_trimspace(&format_string);
351 
352  /* init database structure */
353  RT_DB_INTERNAL_INIT(&internal);
354  internal.idb_major_type = DB5_MAJORTYPE_BRLCAD;
355  internal.idb_type = ID_PNTS;
356  internal.idb_meth = &OBJ[ID_PNTS];
357  BU_ALLOC(internal.idb_ptr, struct rt_pnts_internal);
358 
359  /* init internal structure */
360  pnts = (struct rt_pnts_internal *) internal.idb_ptr;
361  pnts->magic = RT_PNTS_INTERNAL_MAGIC;
362  pnts->scale = defaultSize;
363  pnts->type = type;
364  pnts->count = numPoints; /* set again later */
365  pnts->point = NULL;
366 
367  /* empty list head */
368  switch (type) {
369  case RT_PNT_TYPE_PNT:
370  BU_ALLOC(headPoint, struct pnt);
371  BU_LIST_INIT(&(((struct pnt *)headPoint)->l));
372  num_doubles_per_point = 3;
373  break;
374  case RT_PNT_TYPE_COL:
375  BU_ALLOC(headPoint, struct pnt_color);
376  BU_LIST_INIT(&(((struct pnt_color *)headPoint)->l));
377  num_doubles_per_point = 6;
378  break;
379  case RT_PNT_TYPE_SCA:
380  BU_ALLOC(headPoint, struct pnt_scale);
381  BU_LIST_INIT(&(((struct pnt_scale *)headPoint)->l));
382  num_doubles_per_point = 4;
383  break;
384  case RT_PNT_TYPE_NRM:
385  BU_ALLOC(headPoint, struct pnt_normal);
386  BU_LIST_INIT(&(((struct pnt_normal *)headPoint)->l));
387  num_doubles_per_point = 6;
388  break;
389  case RT_PNT_TYPE_COL_SCA:
390  BU_ALLOC(headPoint, struct pnt_color_scale);
391  BU_LIST_INIT(&(((struct pnt_color_scale *)headPoint)->l));
392  num_doubles_per_point = 7;
393  break;
394  case RT_PNT_TYPE_COL_NRM:
395  BU_ALLOC(headPoint, struct pnt_color_normal);
396  BU_LIST_INIT(&(((struct pnt_color_normal *)headPoint)->l));
397  num_doubles_per_point = 9;
398  break;
399  case RT_PNT_TYPE_SCA_NRM:
400  BU_ALLOC(headPoint, struct pnt_scale_normal);
401  BU_LIST_INIT(&(((struct pnt_scale_normal *)headPoint)->l));
402  num_doubles_per_point = 7;
403  break;
404  case RT_PNT_TYPE_COL_SCA_NRM:
405  BU_ALLOC(headPoint, struct pnt_color_scale_normal);
406  BU_LIST_INIT(&(((struct pnt_color_scale_normal *)headPoint)->l));
407  num_doubles_per_point = 10;
408  break;
409  }
410  BU_ASSERT_PTR(headPoint, !=, NULL);
411  pnts->point = headPoint;
412 
413  if ((fp=fopen(argv[2], "rb")) == NULL) {
414  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]);
415  bu_vls_printf(gedp->ged_result_str, "Could not open file '%s'.\n", argv[2]);
416  bu_vls_free(&format_string);
417  rt_db_free_internal(&internal);
418  return GED_ERROR;
419  }
420 
421  while (!found_eof) {
422  /* points_loop */
423  /* allocate memory for single point structure for current point-cloud type */
424  switch (type) {
425  case RT_PNT_TYPE_PNT:
426  BU_ALLOC(point, struct pnt);
427  break;
428  case RT_PNT_TYPE_COL:
429  BU_ALLOC(point, struct pnt_color);
430  break;
431  case RT_PNT_TYPE_SCA:
432  BU_ALLOC(point, struct pnt_scale);
433  break;
434  case RT_PNT_TYPE_NRM:
435  BU_ALLOC(point, struct pnt_normal);
436  break;
437  case RT_PNT_TYPE_COL_SCA:
438  BU_ALLOC(point, struct pnt_color_scale);
439  break;
440  case RT_PNT_TYPE_COL_NRM:
441  BU_ALLOC(point, struct pnt_color_normal);
442  break;
443  case RT_PNT_TYPE_SCA_NRM:
444  BU_ALLOC(point, struct pnt_scale_normal);
445  break;
446  case RT_PNT_TYPE_COL_SCA_NRM:
447  BU_ALLOC(point, struct pnt_color_scale_normal);
448  break;
449  }
450 
451  /* make sure we have something */
452  BU_ASSERT_PTR(point, !=, NULL);
453 
454  while (!found_eof && !done_processing_format_string) {
455  /* format_string_loop */
456  char format = '\0';
457 
458  while (!found_eof && !found_double) {
459  /* find_doubles_loop */
460  format = bu_vls_addr(&format_string)[format_string_index];
461 
462  buf = fgetc(fp);
463 
464  num_characters_read_from_file++;
465 
466  if (feof(fp)) {
467  if (ferror(fp)) {
468  perror("ERROR: Problem reading file, system error message");
469  fclose(fp);
470  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]);
471  bu_vls_printf(gedp->ged_result_str, "Unable to read file at byte '%lu'.\n", num_characters_read_from_file);
472  bu_vls_free(&format_string);
473  rt_db_free_internal(&internal);
474  return GED_ERROR;
475  } else {
476  found_eof = 1;
477  }
478  }
479 
480  if (found_eof) {
481  fclose(fp);
482  current_character_double = 0;
483  if (num_doubles_read == 0) {
484  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]);
485  bu_vls_printf(gedp->ged_result_str, "No data in file '%s'.\n", argv[2]);
486  bu_vls_free(&format_string);
487  rt_db_free_internal(&internal);
488  return GED_ERROR;
489  }
490  } else {
491  temp_char_ptr = strchr("0123456789.+-eE", buf);
492  if (temp_char_ptr != NULL) {
493  /* character read is part of a double */
494  current_character_double = 1;
495  } else {
496  current_character_double = 0;
497  }
498  }
499 
500  if (previous_character_double && current_character_double) {
501  if (temp_string_index >= temp_string_size) {
502  fclose(fp);
503  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]);
504  bu_vls_printf(gedp->ged_result_str, "String representing double too large, exceeds '%d' character limit. ", temp_string_size - 1);
505  report_import_error_location(num_doubles_read, num_doubles_per_point, start_offset_of_current_double,
506  format, gedp->ged_result_str);
507  bu_vls_free(&format_string);
508  rt_db_free_internal(&internal);
509  return GED_ERROR;
510  }
511  temp_string[temp_string_index] = (char)buf;
512  temp_string_index++;
513  }
514 
515  if (previous_character_double && !current_character_double) {
516  if (temp_string_index >= temp_string_size) {
517  fclose(fp);
518  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]);
519  bu_vls_printf(gedp->ged_result_str, "String representing double too large, exceeds '%d' character limit. ", temp_string_size - 1);
520  report_import_error_location(num_doubles_read, num_doubles_per_point, start_offset_of_current_double,
521  format, gedp->ged_result_str);
522  bu_vls_free(&format_string);
523  rt_db_free_internal(&internal);
524  return GED_ERROR;
525  }
526  temp_string[temp_string_index] = '\0';
527 
528  /* do not convert string to double for format character '?' */
529  if (format != '?') {
530  temp_double = strtod(temp_string, &endp);
531  if (!((endp != temp_string) && (*endp == '\0'))) {
532  fclose(fp);
533  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. ", argv[1]);
534  bu_vls_printf(gedp->ged_result_str, "Unable to convert string '%s' to double. ", temp_string);
535  report_import_error_location(num_doubles_read, num_doubles_per_point, start_offset_of_current_double,
536  format, gedp->ged_result_str);
537  bu_vls_free(&format_string);
538  rt_db_free_internal(&internal);
539  return GED_ERROR;
540  }
541  num_doubles_read++;
542  } else {
543  temp_double = 0.0;
544  }
545 
546  temp_string_index = 0;
547  found_double = 1;
548  previous_character_double = current_character_double;
549  }
550 
551  if (!previous_character_double && current_character_double) {
552  temp_string[temp_string_index] = (char)buf;
553  temp_string_index++;
554  start_offset_of_current_double = num_characters_read_from_file;
555  previous_character_double = current_character_double;
556  }
557 
558  } /* loop exits when eof encountered (and/or) double found */
559 
560  if (found_double) {
561 
562  /* insert double into point structure for current point-cloud type */
563  /* do not attempt to insert double into point structure for format character '?' */
564  if (format != '?') {
565  switch (type) {
566  case RT_PNT_TYPE_PNT:
567  INSERT_COORDINATE_INTO_STRUCTURE(pnt, format, (temp_double * local2base));
568  break;
569  case RT_PNT_TYPE_COL:
570  INSERT_COORDINATE_INTO_STRUCTURE(pnt_color, format, (temp_double * local2base));
571  INSERT_COLOR_INTO_STRUCTURE(pnt_color, format, temp_double);
572  break;
573  case RT_PNT_TYPE_SCA:
574  INSERT_COORDINATE_INTO_STRUCTURE(pnt_scale, format, (temp_double * local2base));
575  INSERT_SCALE_INTO_STRUCTURE(pnt_scale, format, (temp_double * local2base));
576  break;
577  case RT_PNT_TYPE_NRM:
578  INSERT_COORDINATE_INTO_STRUCTURE(pnt_normal, format, (temp_double * local2base));
579  INSERT_NORMAL_INTO_STRUCTURE(pnt_normal, format, (temp_double * local2base));
580  break;
581  case RT_PNT_TYPE_COL_SCA:
582  INSERT_COORDINATE_INTO_STRUCTURE(pnt_color_scale, format, (temp_double * local2base));
583  INSERT_COLOR_INTO_STRUCTURE(pnt_color_scale, format, temp_double);
584  INSERT_SCALE_INTO_STRUCTURE(pnt_color_scale, format, (temp_double * local2base));
585  break;
586  case RT_PNT_TYPE_COL_NRM:
587  INSERT_COORDINATE_INTO_STRUCTURE(pnt_color_normal, format, (temp_double * local2base));
588  INSERT_COLOR_INTO_STRUCTURE(pnt_color_normal, format, temp_double);
589  INSERT_NORMAL_INTO_STRUCTURE(pnt_color_normal, format, (temp_double * local2base));
590  break;
591  case RT_PNT_TYPE_SCA_NRM:
592  INSERT_COORDINATE_INTO_STRUCTURE(pnt_scale_normal, format, (temp_double * local2base));
593  INSERT_SCALE_INTO_STRUCTURE(pnt_scale_normal, format, (temp_double * local2base));
594  INSERT_NORMAL_INTO_STRUCTURE(pnt_scale_normal, format, (temp_double * local2base));
595  break;
596  case RT_PNT_TYPE_COL_SCA_NRM:
597  INSERT_COORDINATE_INTO_STRUCTURE(pnt_color_scale_normal, format, (temp_double * local2base));
598  INSERT_COLOR_INTO_STRUCTURE(pnt_color_scale_normal, format, temp_double);
599  INSERT_SCALE_INTO_STRUCTURE(pnt_color_scale_normal, format, (temp_double * local2base));
600  INSERT_NORMAL_INTO_STRUCTURE(pnt_color_scale_normal, format, (temp_double * local2base));
601  break;
602  }
603  }
604  found_double = 0; /* allows loop to continue */
605  format_string_index++;
606  if (format_string_index >= bu_vls_strlen(&format_string)) {
607  done_processing_format_string = 1;
608  }
609  }
610 
611  } /* loop exits when eof encountered (and/or) all doubles for
612  * a single point are stored in point structure
613  */
614 
615  if (done_processing_format_string) {
616  /* push single point structure onto linked-list of points
617  * which makeup the point-cloud.
618  */
619  switch (type) {
620  case RT_PNT_TYPE_PNT:
621  BU_LIST_PUSH(&(((struct pnt *)headPoint)->l), &((struct pnt *)point)->l);
622  break;
623  case RT_PNT_TYPE_COL:
624  BU_LIST_PUSH(&(((struct pnt_color *)headPoint)->l), &((struct pnt_color *)point)->l);
625  break;
626  case RT_PNT_TYPE_SCA:
627  BU_LIST_PUSH(&(((struct pnt_scale *)headPoint)->l), &((struct pnt_scale *)point)->l);
628  break;
629  case RT_PNT_TYPE_NRM:
630  BU_LIST_PUSH(&(((struct pnt_normal *)headPoint)->l), &((struct pnt_normal *)point)->l);
631  break;
632  case RT_PNT_TYPE_COL_SCA:
633  BU_LIST_PUSH(&(((struct pnt_color_scale *)headPoint)->l), &((struct pnt_color_scale *)point)->l);
634  break;
635  case RT_PNT_TYPE_COL_NRM:
636  BU_LIST_PUSH(&(((struct pnt_color_normal *)headPoint)->l), &((struct pnt_color_normal *)point)->l);
637  break;
638  case RT_PNT_TYPE_SCA_NRM:
639  BU_LIST_PUSH(&(((struct pnt_scale_normal *)headPoint)->l), &((struct pnt_scale_normal *)point)->l);
640  break;
641  case RT_PNT_TYPE_COL_SCA_NRM:
642  BU_LIST_PUSH(&(((struct pnt_color_scale_normal *)headPoint)->l), &((struct pnt_color_scale_normal *)point)->l);
643  break;
644  }
645  numPoints++;
646  format_string_index = 0;
647  done_processing_format_string = 0;
648  }
649 
650  } /* loop exits when eof encountered */
651 
652  if (num_doubles_read < num_doubles_per_point) {
653  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. Number of values read inconsistent with point-cloud type ", argv[1]);
654  bu_vls_printf(gedp->ged_result_str, "defined by format string '%V'. The number of values read must be an even ", format_string);
655  bu_vls_printf(gedp->ged_result_str, "multiple of %d but read %lu values.\n", num_doubles_per_point, num_doubles_read);
656  bu_vls_free(&format_string);
657  rt_db_free_internal(&internal);
658  return GED_ERROR;
659  }
660 
661  if (num_doubles_read % num_doubles_per_point) {
662  bu_vls_printf(gedp->ged_result_str, "Make '%s' failed. Number of values read inconsistent with point-cloud type ", argv[1]);
663  bu_vls_printf(gedp->ged_result_str, "defined by format string '%V'. The number of values read must be an even ", format_string);
664  bu_vls_printf(gedp->ged_result_str, "multiple of %d but read %lu values.\n", num_doubles_per_point, num_doubles_read);
665  bu_vls_free(&format_string);
666  rt_db_free_internal(&internal);
667  return GED_ERROR;
668  }
669 
670  pnts->count = numPoints;
671 
672  GED_DB_DIRADD(gedp, dp, argv[1], RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&internal.idb_type, GED_ERROR);
673  GED_DB_PUT_INTERNAL(gedp, dp, &internal, &rt_uniresource, GED_ERROR);
674 
675  bu_vls_free(&format_string);
676 
677  bu_vls_printf(gedp->ged_result_str, "Make '%s' success, %lu values read, %lu points imported.\n", argv[1], num_doubles_read, numPoints);
678 
679  return GED_OK;
680 }
681 
682 
683 /*
684  * Local Variables:
685  * mode: C
686  * tab-width: 8
687  * indent-tabs-mode: t
688  * c-file-style: "stroustrup"
689  * End:
690  * ex: shiftwidth=4 tabstop=8
691  */
void usage(struct ged *gedp)
Definition: coil.c:315
#define GED_DB_DIRADD(_gedp, _dp, _name, _laddr, _len, _dirflags, _ptr, _flags)
Definition: ged.h:213
#define GED_OK
Definition: ged.h:55
#define INSERT_COLOR_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert)
Definition: make_pnts.c:52
Definition: ged.h:338
void bu_vls_strcat(struct bu_vls *vp, const char *s)
Definition: vls.c:368
void bu_vls_trunc(struct bu_vls *vp, int len)
Definition: vls.c:198
#define GED_CHECK_ARGC_GT_0(_gedp, _argc, _flags)
Definition: ged.h:202
Header file for the BRL-CAD common definitions.
#define INSERT_NORMAL_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert)
Definition: make_pnts.c:73
double bu_mm_value(const char *s)
Definition: units.c:355
#define GED_ERROR
Definition: ged.h:61
int str2mm(const char *units_string, double *conv_factor, struct bu_vls *ged_result_str)
Definition: make_pnts.c:175
#define GED_DB_PUT_INTERNAL(_gedp, _dp, _intern, _resource, _flags)
Definition: ged.h:243
int compare_char(const char *a, const char *b, void *arg)
Definition: make_pnts.c:99
char * strchr(const char *sp, int c)
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
struct resource rt_uniresource
default. Defined in librt/globals.c
Definition: globals.c:41
#define GED_CHECK_DATABASE_OPEN(_gedp, _flags)
Definition: ged.h:114
#define BU_ALLOC(_ptr, _type)
Definition: malloc.h:223
#define INSERT_COORDINATE_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert)
Definition: make_pnts.c:39
#define RT_DIR_SOLID
this name is a solid
Definition: raytrace.h:883
#define RT_DB_INTERNAL_INIT(_p)
Definition: raytrace.h:199
#define LOOKUP_QUIET
Definition: raytrace.h:893
void bu_sort(void *array, size_t nummemb, size_t sizememb, int(*compare)(const void *, const void *, void *), void *context)
Definition: sort.c:110
#define RT_DIR_PHONY_ADDR
Special marker for d_addr field.
Definition: raytrace.h:879
Coord * point
Definition: chull3d.cpp:52
size_t bu_vls_strlen(const struct bu_vls *vp)
Definition: vls.c:189
#define INSERT_SCALE_INTO_STRUCTURE(_structure_type, _control_variable, _variable_to_insert)
Definition: make_pnts.c:66
#define UNUSED(parameter)
Definition: common.h:239
void report_import_error_location(unsigned long int num_doubles_read, unsigned int num_doubles_per_point, unsigned long int start_offset_of_current_double, char field, struct bu_vls *ged_result_str)
Definition: make_pnts.c:208
#define GED_CHECK_EXISTS(_gedp, _name, _noisy, _flags)
Definition: ged.h:171
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
struct bu_vls * ged_result_str
Definition: ged.h:357
int ged_make_pnts(struct ged *gedp, int argc, const char *argv[])
Definition: make_pnts.c:234
int str2type(const char *format_string, rt_pnt_type *pnt_type, struct bu_vls *ged_result_str)
Definition: make_pnts.c:112
#define BU_LIST_PUSH(hp, p)
Definition: list.h:246
#define BU_LIST_INIT(_hp)
Definition: list.h:148
const struct rt_functab OBJ[]
Definition: table.c:159
#define BU_ASSERT_PTR(_lhs, _relation, _rhs)
Definition: defines.h:227
#define ID_PNTS
Collection of Points.
Definition: raytrace.h:512
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
void bu_vls_trimspace(struct bu_vls *vp)
Definition: vls.c:678
#define idb_type
Definition: raytrace.h:198
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
#define GED_CHECK_READ_ONLY(_gedp, _flags)
Definition: ged.h:181
Definition: vls.h:56
void bu_vls_putc(struct bu_vls *vp, int c)
Definition: vls.c:666
void rt_db_free_internal(struct rt_db_internal *ip)
Definition: dir.c:216
#define RT_PNTS_INTERNAL_MAGIC
Definition: magic.h:114
#define GED_MORE
Definition: ged.h:63
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126