htrdr_args.c (21000B)
1 /* Copyright (C) 2018-2019, 2022-2025 Centre National de la Recherche Scientifique 2 * Copyright (C) 2020-2022 Institut Mines Télécom Albi-Carmaux 3 * Copyright (C) 2022-2025 Institut Pierre-Simon Laplace 4 * Copyright (C) 2022-2025 Institut de Physique du Globe de Paris 5 * Copyright (C) 2018-2025 |Méso|Star> (contact@meso-star.com) 6 * Copyright (C) 2022-2025 Observatoire de Paris 7 * Copyright (C) 2022-2025 Université de Reims Champagne-Ardenne 8 * Copyright (C) 2022-2025 Université de Versaille Saint-Quentin 9 * Copyright (C) 2018-2019, 2022-2025 Université Paul Sabatier 10 * 11 * This program is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation, either version 3 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 23 24 #define _POSIX_C_SOURCE 2 /* strtok_r support */ 25 26 #include "core/htrdr.h" 27 #include "core/htrdr_args.h" 28 #include "core/htrdr_version.h" 29 30 #include <star/scam.h> 31 32 #include <rsys/cstr.h> 33 #include <rsys/double3.h> 34 #include <rsys/str.h> 35 36 #include <string.h> 37 38 /******************************************************************************* 39 * Helper functions 40 ******************************************************************************/ 41 static INLINE res_T 42 parse_doubleX(const char* str, double* val, const size_t sz) 43 { 44 size_t len; 45 res_T res = RES_OK; 46 ASSERT(str && val); 47 res = cstr_to_list_double(str, ',', val, &len, sz); 48 if(res == RES_OK && len != sz) res = RES_BAD_ARG; 49 return res; 50 } 51 52 static INLINE res_T 53 parse_definition(const char* str, unsigned val[2]) 54 { 55 size_t len; 56 res_T res = RES_OK; 57 ASSERT(str && val); 58 res = cstr_to_list_uint(str, 'x', val, &len, 2); 59 if(res != RES_OK) return res; 60 if(len != 2) return RES_BAD_ARG; 61 if(val[0] > 16384 || val[1] > 16384) return RES_BAD_ARG; 62 return RES_OK; 63 } 64 65 static res_T 66 parse_fov(const char* str, double* out_fov) 67 { 68 double fov; 69 res_T res = RES_OK; 70 ASSERT(str && out_fov); 71 72 res = cstr_to_double(str, &fov); 73 if(res != RES_OK) { 74 fprintf(stderr, "Invalid field of view `%s'.\n", str); 75 return RES_BAD_ARG; 76 } 77 if(fov <= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN 78 || fov >= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX) { 79 fprintf(stderr, "The field of view %g is not in ]%g, %g[.\n", fov, 80 HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN, 81 HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX); 82 return RES_BAD_ARG; 83 } 84 *out_fov = fov; 85 return RES_OK; 86 } 87 88 static res_T 89 parse_focal_length(const char* str, double* out_length) 90 { 91 double length; 92 res_T res = RES_OK; 93 ASSERT(str && out_length); 94 95 res = cstr_to_double(str, &length); 96 if(res != RES_OK) { 97 fprintf(stderr, "Invalid focal length `%s'.\n", str); 98 return RES_BAD_ARG; 99 } 100 if(length <= 0) { 101 fprintf(stderr, "Invalid negative or null focal length %g.\n", length); 102 return RES_BAD_ARG; 103 } 104 *out_length = length; 105 return RES_OK; 106 } 107 108 static res_T 109 parse_lens_radius(const char* str, double* out_radius) 110 { 111 double radius; 112 res_T res = RES_OK; 113 ASSERT(str && out_radius); 114 115 res = cstr_to_double(str, &radius); 116 if(res != RES_OK) { 117 fprintf(stderr, "Invalid lens radius `%s'.\n", str); 118 return RES_BAD_ARG; 119 } 120 if(radius < 0) { 121 fprintf(stderr, "Invalid negative lens radius %g.\n", radius); 122 return RES_BAD_ARG; 123 } 124 *out_radius = radius; 125 return RES_OK; 126 } 127 128 static res_T 129 parse_focal_dst(const char* str, double* out_dst) 130 { 131 double dst; 132 res_T res = RES_OK; 133 ASSERT(str && out_dst); 134 135 res = cstr_to_double(str, &dst); 136 if(res != RES_OK) { 137 fprintf(stderr, "Invalid focal distance `%s'.\n", str); 138 return RES_BAD_ARG; 139 } 140 if(dst <= 0) { 141 fprintf(stderr, "Invalid negative or null focal disrtance %g.\n", dst); 142 return RES_BAD_ARG; 143 } 144 *out_dst = dst; 145 return RES_OK; 146 } 147 148 static res_T 149 parse_image_plane_height(const char* str, double* out_height) 150 { 151 double height; 152 res_T res = RES_OK; 153 ASSERT(str && out_height); 154 155 res = cstr_to_double(str, &height); 156 if(res != RES_OK) { 157 fprintf(stderr, 158 "Invalid height `%s' of the image plane of the orthographic camera.\n", 159 str); 160 return RES_BAD_ARG; 161 } 162 if(height <= 0) { 163 fprintf(stderr, 164 "Invalid negative or null height of the image plane " 165 "of the orthographic camera.\n"); 166 return RES_BAD_ARG; 167 } 168 *out_height = height; 169 return RES_OK; 170 } 171 172 static res_T 173 parse_image_parameter(const char* str, void* args) 174 { 175 char buf[128]; 176 struct htrdr_args_image* img = args; 177 char* key; 178 char* val; 179 char* ctx; 180 res_T res = RES_OK; 181 ASSERT(str && img); 182 183 if(strlen(str) >= sizeof(buf) -1/*NULL char*/) { 184 fprintf(stderr, 185 "Could not duplicate the image option string `%s'.\n", str); 186 res = RES_MEM_ERR; 187 goto error; 188 } 189 strncpy(buf, str, sizeof(buf)); 190 191 key = strtok_r(buf, "=", &ctx); 192 val = strtok_r(NULL, "", &ctx); 193 194 if(!val) { 195 fprintf(stderr, "Missing a value to the image option `%s'.\n", key); 196 res = RES_BAD_ARG; 197 goto error; 198 } 199 200 #define PARSE(Name, Func) \ 201 res = Func; \ 202 if(res != RES_OK) { \ 203 fprintf(stderr, "Invalid image "Name" `%s'.\n", val); \ 204 goto error; \ 205 } (void)0 206 if(!strcmp(key, "def")) { 207 PARSE("definition", parse_definition(val, img->definition)); 208 } else if(!strcmp(key, "spp")) { 209 PARSE("#samples per pixel", cstr_to_uint(val, &img->spp)); 210 } else { 211 fprintf(stderr, "Invalid image parameter `%s'.\n", key); 212 res = RES_BAD_ARG; 213 goto error; 214 } 215 #undef PARSE 216 217 if(!img->definition[0] || !img->definition[1]) { 218 fprintf(stderr, "The image definition cannot be null.\n"); 219 res = RES_BAD_ARG; 220 goto error; 221 } 222 if(!img->spp) { 223 fprintf(stderr, "The number of samples per pixel cannot be null.\n"); 224 res = RES_BAD_ARG; 225 goto error; 226 } 227 228 exit: 229 return res; 230 error: 231 goto exit; 232 } 233 234 static res_T 235 parse_camera_perspective_parameter(const char* str, void* args) 236 { 237 char buf[128]; 238 struct htrdr_args_camera_perspective* cam = args; 239 char* key; 240 char* val; 241 char* ctx; 242 res_T res = RES_OK; 243 ASSERT(cam && str); 244 245 if(strlen(str) >= sizeof(buf) -1/*NULL char*/) { 246 fprintf(stderr, 247 "Could not duplicate the perspective camera option string `%s'.\n", str); 248 res = RES_MEM_ERR; 249 goto error; 250 } 251 strncpy(buf, str, sizeof(buf)); 252 253 key = strtok_r(buf, "=", &ctx); 254 val = strtok_r(NULL, "", &ctx); 255 256 if(!val) { 257 fprintf(stderr, 258 "Missing value to the perspective camera parameter `%s'.\n", key); 259 res = RES_BAD_ARG; 260 goto error; 261 } 262 263 #define PARSE(Name, Func) { \ 264 if(RES_OK != (res = Func)) { \ 265 fprintf(stderr, "Invalid perspective camera "Name" `%s'.\n", val); \ 266 goto error; \ 267 } \ 268 } (void)0 269 if(!strcmp(key, "pos")) { 270 PARSE("position", parse_doubleX(val, cam->position, 3)); 271 } else if(!strcmp(key, "tgt")) { 272 PARSE("target", parse_doubleX(val, cam->target, 3)); 273 } else if(!strcmp(key, "up")) { 274 PARSE("up vector", parse_doubleX(val, cam->up, 3)); 275 } else if(!strcmp(key, "fov")) { 276 PARSE("field-of-view", parse_fov(val, &cam->fov_y)); 277 cam->focal_length = -1; /* Overwrite the focal_length */ 278 } else if(!strcmp(key, "focal-length")) { 279 PARSE("focal-length", parse_focal_length(val, &cam->focal_length)); 280 cam->fov_y = -1; /* Overwrite the fov */ 281 } else if(!strcmp(key, "lens-radius")) { 282 PARSE("lens radius", parse_lens_radius(val, &cam->lens_radius)); 283 } else if(!strcmp(key, "focal-dst")) { 284 PARSE("focal distance", parse_focal_dst(val, &cam->focal_dst)); 285 } else { 286 fprintf(stderr, "Invalid perspective camera parameter `%s'.\n", key); 287 res = RES_BAD_ARG; 288 goto error; 289 } 290 #undef PARSE 291 exit: 292 return res; 293 error: 294 goto exit; 295 } 296 297 static res_T 298 parse_camera_orthographic_parameter(const char* str, void* args) 299 { 300 char buf[128]; 301 struct htrdr_args_camera_orthographic* cam = args; 302 char* key; 303 char* val; 304 char* ctx; 305 res_T res = RES_OK; 306 ASSERT(cam && str); 307 308 if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) { 309 fprintf(stderr, 310 "Could not duplicate the orthographic camera option string `%s'.\n", str); 311 res = RES_MEM_ERR; 312 goto error; 313 } 314 strncpy(buf, str, sizeof(buf)); 315 316 key = strtok_r(buf, "=", &ctx); 317 val = strtok_r(NULL, "", &ctx); 318 319 if(!val) { 320 fprintf(stderr, 321 "Missing value to the orthographic camera parameter `%s'.\n", key); 322 res = RES_BAD_ARG; 323 goto error; 324 } 325 #define PARSE(Name, Func) { \ 326 if(RES_OK != (res = Func)) { \ 327 fprintf(stderr, "Invalid orthographic camera "Name" `%s'.\n", val); \ 328 goto error; \ 329 } \ 330 } (void)0 331 if(!strcmp(key, "pos")) { 332 PARSE("position", parse_doubleX(val, cam->position, 3)); 333 } else if(!strcmp(key, "tgt")) { 334 PARSE("target", parse_doubleX(val, cam->target, 3)); 335 } else if(!strcmp(key, "up")) { 336 PARSE("up vector", parse_doubleX(val, cam->up, 3)); 337 } else if(!strcmp(key, "height")) { 338 PARSE("image plane height", parse_image_plane_height(val, &cam->height)); 339 } else { 340 fprintf(stderr, "Invalid orthographic camera parameter `%s'.\n", key); 341 res = RES_BAD_ARG; 342 goto error; 343 } 344 #undef PARSE 345 exit: 346 return res; 347 error: 348 goto exit; 349 } 350 351 static res_T 352 parse_rectangle_parameter(const char* str, void* args) 353 { 354 char buf[128]; 355 struct htrdr_args_rectangle* rect = args; 356 char* key; 357 char* val; 358 char* ctx; 359 res_T res = RES_OK; 360 ASSERT(rect && str); 361 362 if(strlen(str) >= sizeof(buf) -1/*NULL char*/) { 363 fprintf(stderr, 364 "Could not duplicate the rectangle option string `%s'.\n", str); 365 res = RES_MEM_ERR; 366 goto error; 367 } 368 strncpy(buf, str, sizeof(buf)); 369 370 key = strtok_r(buf, "=", &ctx); 371 val = strtok_r(NULL, "", &ctx); 372 373 if(!val) { 374 fprintf(stderr, "Missing value to the rectangle option `%s'.\n", key); 375 res = RES_BAD_ARG; 376 goto error; 377 } 378 379 #define PARSE(Name, Func) { \ 380 if(RES_OK != (res = Func)) { \ 381 fprintf(stderr, "Invalid rectangle "Name" `%s'.\n", val); \ 382 goto error; \ 383 } \ 384 } (void)0 385 if(!strcmp(key, "pos")) { 386 PARSE("position", parse_doubleX(val, rect->position, 3)); 387 } else if(!strcmp(key, "tgt")) { 388 PARSE("target", parse_doubleX(val, rect->target, 3)); 389 } else if(!strcmp(key, "up")) { 390 PARSE("up vector", parse_doubleX(val, rect->up, 3)); 391 } else if(!strcmp(key, "sz")) { 392 PARSE("size", parse_doubleX(val, rect->size, 2)); 393 } else { 394 fprintf(stderr, "Invalid rectangle parameter `%s'.\n", key); 395 res = RES_BAD_ARG; 396 goto error; 397 } 398 #undef PARSE 399 exit: 400 return res; 401 error: 402 goto exit; 403 } 404 405 static res_T 406 parse_spectral_range(const char* str, double wlen_range[2]) 407 { 408 double range[2]; 409 size_t len; 410 res_T res = RES_OK; 411 ASSERT(wlen_range && str); 412 413 res = cstr_to_list_double(str, ',', range, &len, 2); 414 if(res == RES_OK && len != 2) res = RES_BAD_ARG; 415 if(res == RES_OK && range[0] > range[1]) res = RES_BAD_ARG; 416 if(res != RES_OK) { 417 fprintf(stderr, "Invalid spectral range `%s'.\n", str); 418 goto error; 419 } 420 wlen_range[0] = range[0]; 421 wlen_range[1] = range[1]; 422 423 exit: 424 return res; 425 error: 426 goto exit; 427 } 428 429 static res_T 430 parse_spectral_parameter(const char* str, void* ptr) 431 { 432 char buf[128]; 433 struct htrdr_args_spectral* args = ptr; 434 char* key; 435 char* val; 436 char* ctx; 437 res_T res = RES_OK; 438 ASSERT(args && str); 439 440 if(strlen(str) >= sizeof(buf) -1/*NULL char*/) { 441 fprintf(stderr, 442 "Could not duplicate the spectral option string `%s'.\n", str); 443 res = RES_MEM_ERR; 444 goto error; 445 } 446 strncpy(buf, str, sizeof(buf)); 447 448 key = strtok_r(buf, "=", &ctx); 449 val = strtok_r(NULL, "", &ctx); 450 451 if(!strcmp(key, "cie_xyz")) { 452 args->spectral_type = HTRDR_SPECTRAL_SW_CIE_XYZ; 453 args->wlen_range[0] = HTRDR_RAN_WLEN_CIE_XYZ_RANGE_DEFAULT[0]; 454 args->wlen_range[1] = HTRDR_RAN_WLEN_CIE_XYZ_RANGE_DEFAULT[1]; 455 } else { 456 if(!val) { 457 fprintf(stderr, "Missing value to the spectral option `%s'.\n", key); 458 res = RES_BAD_ARG; 459 goto error; 460 } 461 if(!strcmp(key, "sw")) { 462 args->spectral_type = HTRDR_SPECTRAL_SW; 463 res = parse_spectral_range(val, args->wlen_range); 464 if(res != RES_OK) goto error; 465 } else if(!strcmp(key, "lw")) { 466 args->spectral_type = HTRDR_SPECTRAL_LW; 467 res = parse_spectral_range(val, args->wlen_range); 468 if(res != RES_OK) goto error; 469 } else if(!strcmp(key, "Tref")) { 470 res = cstr_to_double(val, &args->ref_temperature); 471 if(res == RES_OK && args->ref_temperature < 0) res = RES_BAD_ARG; 472 if(res != RES_OK) { 473 fprintf(stderr, "Invalid reference temperature Tref=%s.\n", val); 474 goto error; 475 } 476 } else { 477 fprintf(stderr, "Invalid spectral parameter `%s'.\n", key); 478 res = RES_BAD_ARG; 479 goto error; 480 } 481 } 482 483 exit: 484 return res; 485 error: 486 goto exit; 487 } 488 489 static res_T 490 parse_geometry_parameter(const char* str, void* ptr) 491 { 492 struct str buf; 493 struct htrdr_args_geometry* geom = ptr; 494 char* key; 495 char* val; 496 char* ctx; 497 res_T res = RES_OK; 498 ASSERT(geom && str); 499 500 str_init(NULL, &buf); 501 res = str_set(&buf, str); 502 if(res != RES_OK) { 503 fprintf(stderr, 504 "Could not duplicate the geometry option string `%s' -- %s.\n", 505 str, res_to_cstr(res)); 506 goto error; 507 } 508 509 key = strtok_r(str_get(&buf), "=", &ctx); 510 val = strtok_r(NULL, "", &ctx); 511 512 if(!val) { 513 fprintf(stderr, "Missing value to the geometry parameter `%s'.\n", key); 514 res = RES_BAD_ARG; 515 goto error; 516 } 517 518 #define SET_VALUE(Key, Val, Str) { \ 519 const size_t len = strlen(Val) + 1; \ 520 Str = mem_alloc(len); \ 521 if(!Str) { \ 522 fprintf(stderr, \ 523 "Could not duplicate the value `%s' of the geometry parameter `%s'.\n",\ 524 (Val), (Key)); \ 525 res = RES_MEM_ERR; \ 526 goto error; \ 527 } \ 528 strncpy(Str, Val, len); \ 529 } (void)0 530 if(!strcmp(key, "obj")) { 531 SET_VALUE(key, val, geom->path_obj); 532 } else if(!strcmp(key, "mats")) { 533 SET_VALUE(key, val, geom->path_mats); 534 } else { 535 fprintf(stderr, "Invalid geometry parameter `%s'.\n", key); 536 res = RES_BAD_ARG; 537 goto error; 538 } 539 #undef SET_VALUE 540 541 exit: 542 str_release(&buf); 543 return res; 544 error: 545 htrdr_args_geometry_free(geom); 546 goto exit; 547 } 548 549 /******************************************************************************* 550 * Exported functions 551 ******************************************************************************/ 552 res_T 553 htrdr_args_camera_perspective_parse 554 (struct htrdr_args_camera_perspective* cam, 555 const char* str) 556 { 557 res_T res = RES_OK; 558 559 if(!cam || !str) { 560 res = RES_BAD_ARG; 561 goto error; 562 } 563 564 *cam = HTRDR_ARGS_CAMERA_PERSPECTIVE_DEFAULT; 565 566 res = cstr_parse_list(str, ':', parse_camera_perspective_parameter, cam); 567 if(res != RES_OK) goto error; 568 569 if(cam->focal_length < 0) { 570 ASSERT(cam->fov_y > 0); 571 res = scam_field_of_view_to_focal_length 572 (cam->lens_radius, MDEG2RAD(cam->fov_y), &cam->focal_length); 573 if(res != RES_OK) { 574 fprintf(stderr, 575 "Cannot compute the focal length from the lens radius %g " 576 "and the field of view %g -- %s.\n", 577 cam->lens_radius, 578 cam->fov_y, 579 res_to_cstr(res)); 580 goto error; 581 } 582 583 } else if(cam->fov_y < 0) { 584 ASSERT(cam->focal_length > 0); 585 res = scam_focal_length_to_field_of_view 586 (cam->lens_radius, cam->focal_length, &cam->fov_y); 587 if(res != RES_OK) { 588 fprintf(stderr, 589 "Cannot compute the field of view from the lens radius %g " 590 "and the focal length %g -- %s.\n", 591 cam->lens_radius, 592 cam->focal_length, 593 res_to_cstr(res)); 594 goto error; 595 } 596 cam->fov_y = MRAD2DEG(cam->fov_y); 597 if(cam->fov_y <= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN 598 || cam->fov_y >= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX) { 599 fprintf(stderr, 600 "Invalid focal length %g regarding the lens radius %g. " 601 "The corresponding field of view %g is not in ]%g, %g[ degrees.\n", 602 cam->focal_length, 603 cam->lens_radius, 604 cam->fov_y, 605 HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN, 606 HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX); 607 res = RES_BAD_ARG; 608 goto error; 609 } 610 } 611 612 exit: 613 return res; 614 error: 615 goto exit; 616 } 617 618 res_T 619 htrdr_args_camera_perspective_check 620 (const struct htrdr_args_camera_perspective* cam) 621 { 622 if(!cam) return RES_BAD_ARG; 623 624 /* Invalid Fov */ 625 if(cam->fov_y <= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MIN 626 || cam->fov_y >= HTRDR_ARGS_CAMERA_PERSPECTIVE_FOV_EXCLUSIVE_MAX) { 627 /* Is the fov defined by the focal length? */ 628 if(cam->focal_length < 0) return RES_BAD_ARG; 629 } 630 631 /* Invalid focal length */ 632 if(cam->focal_length <= 0) { 633 /* Is the focal length defined by the fov? */ 634 if(cam->fov_y < 0) return RES_BAD_ARG; 635 } 636 637 /* Invalid lens radius */ 638 if(cam->lens_radius < 0) 639 return RES_BAD_ARG; 640 641 /* Invalid focal distance */ 642 if(cam->lens_radius > 0/*!pinhole*/ && cam->focal_dst < 0) 643 return RES_BAD_ARG; 644 645 return RES_OK; 646 } 647 648 res_T 649 htrdr_args_camera_orthographic_parse 650 (struct htrdr_args_camera_orthographic* cam, 651 const char* str) 652 { 653 if(!cam || !str) return RES_BAD_ARG; 654 return cstr_parse_list(str, ':', parse_camera_orthographic_parameter, cam); 655 } 656 657 res_T 658 htrdr_args_camera_orthographic_check 659 (const struct htrdr_args_camera_orthographic* cam) 660 { 661 if(!cam) return RES_BAD_ARG; 662 663 /* Invalid image plane height */ 664 if(cam->height <= 0) return RES_BAD_ARG; 665 666 return RES_OK; 667 } 668 669 res_T 670 htrdr_args_rectangle_parse(struct htrdr_args_rectangle* rect, const char* str) 671 { 672 if(!rect || !str) return RES_BAD_ARG; 673 return cstr_parse_list(str, ':', parse_rectangle_parameter, rect); 674 } 675 676 res_T 677 htrdr_args_image_parse(struct htrdr_args_image* img, const char* str) 678 { 679 if(!img || !str) return RES_BAD_ARG; 680 return cstr_parse_list(str, ':', parse_image_parameter, img); 681 } 682 683 res_T 684 htrdr_args_image_check(const struct htrdr_args_image* img) 685 { 686 if(!img) return RES_BAD_ARG; 687 688 /* Invalid definition */ 689 if(!img->definition[0] || !img->definition[1]) 690 return RES_BAD_ARG; 691 692 /* Invalid number of samples per pixel */ 693 if(!img->spp) 694 return RES_BAD_ARG; 695 696 return RES_OK; 697 } 698 699 res_T 700 htrdr_args_spectral_parse(struct htrdr_args_spectral* spectral, const char* str) 701 { 702 if(!spectral || !str) return RES_BAD_ARG; 703 return cstr_parse_list(str, ':', parse_spectral_parameter, spectral); 704 } 705 706 void 707 htrdr_args_geometry_free(struct htrdr_args_geometry* geom) 708 { 709 ASSERT(geom); 710 if(geom->path_obj) mem_rm(geom->path_obj); 711 if(geom->path_mats) mem_rm(geom->path_mats); 712 *geom = HTRDR_ARGS_GEOMETRY_NULL; 713 } 714 715 res_T 716 htrdr_args_geometry_parse(struct htrdr_args_geometry* geom, const char* str) 717 { 718 res_T res = RES_OK; 719 720 if(!geom || !str) { 721 res = RES_BAD_ARG; 722 goto error; 723 } 724 725 htrdr_args_geometry_free(geom); 726 727 res = cstr_parse_list(str, ':', parse_geometry_parameter, geom); 728 if(res != RES_OK) goto error; 729 730 if(!geom->path_obj) { 731 fprintf(stderr, "Missing the `obj' geometry parameter.\n"); 732 res = RES_BAD_ARG; 733 goto error; 734 } 735 736 if(!geom->path_mats) { 737 fprintf(stderr, "Missing the `mats' geometry parameter.\n"); 738 res = RES_BAD_ARG; 739 goto error; 740 } 741 742 exit: 743 return res; 744 error: 745 if(geom) htrdr_args_geometry_free(geom); 746 goto exit; 747 } 748