ale/d2/render/psf/psf_parse.h
2022-07-30 14:46:04 -03:00

198 lines
5.2 KiB
C++

// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
// <dhilvert@ugcs.caltech.edu>
/* This file is part of the Anti-Lamenessing Engine.
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Anti-Lamenessing Engine; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __psf_parse_h__
#define __psf_parse_h__
#include "psf.h"
#include "box.h"
#include "circle.h"
#include "gauss.h"
#include "sum.h"
#include "convolution.h"
#include "scalar_mult.h"
#include "stdin.h"
#include "stdin_vg.h"
/*
* Parse strings describing point-spread functions, and return a psf object
* satisfying the string.
*/
class psf_parse {
private:
static int strpfix(const char *a, const char *b) {
return strncmp(a, b, strlen(a));
}
static void nomem() {
fprintf(stderr, "\n\n*** Error: unable to allocate memory in psf_parse. ***\n\n");
exit(1);
}
static void syntax_error(const char *explanation) {
fprintf(stderr, "\n\n*** Error: PSF syntax: %s ***\n\n", explanation);
exit(1);
}
/*
* Evaluate a type string having no remaining binary operators.
*/
static psf *get_atomic(int is_linear, const char *orig_type) {
double param;
if (!strcmp(orig_type, "stdin")) {
fprintf(stderr, "\nInitializing ");
fprintf(stderr, is_linear ? "linear" : "non-linear");
fprintf(stderr, " PSF.\n");
return new psf_stdin();
} else if (!strcmp(orig_type, "stdin_vg")) {
fprintf(stderr, "\nInitializing ");
fprintf(stderr, is_linear ? "linear" : "non-linear");
fprintf(stderr, " PSF.\n");
return new psf_stdin_vg();
} else if (!strpfix("box=", orig_type)) {
if (sscanf(orig_type + strlen("box="), "%lf", &param) != 1)
syntax_error("Unable to get box diameter.");
return new box(param / 2);
} else if (!strpfix("circle=", orig_type)) {
if (sscanf(orig_type + strlen("circle="), "%lf", &param) != 1)
syntax_error("Unable to get circle diameter.");
return new circle(param / 2);
} else if (!strpfix("gauss=", orig_type)) {
if (sscanf(orig_type + strlen("gauss="), "%lf", &param) != 1)
syntax_error("Unable to parse gauss std deviation.");
return new gauss(param / 2);
} else {
fprintf(stderr, "get_atomic type %s\n", orig_type);
syntax_error("Unable to get filter.");
}
assert(0);
}
/*
* Get a scalar value
*/
static ale_real get_scalar(const char *orig_type) {
double result;
if (sscanf(orig_type, "%lf", &result) != 1)
syntax_error("Unable to get scalar value.");
return result;
}
/*
* Split a type string with the binary operator having
* third-lowest precedence (i.e., scalar multiplication).
*/
static psf *get_scalar_mult(int is_linear, const char *orig_type) {
char *type = strdup(orig_type);
char *operator_index = (char *) type;
assert(type);
if (!type)
nomem();
while (*operator_index != '\0'
&& *operator_index != '*')
operator_index++;
if (*operator_index == '\0') {
free(type);
return get_atomic(is_linear, orig_type);
}
*operator_index = '\0';
psf *result = new scalar_mult(get_scalar(type), get_scalar_mult(is_linear, operator_index + 1));
*operator_index = '*';
free(type);
return result;
}
/*
* Split a type string with the binary operator having
* second-lowest precedence (i.e., convolution).
*/
static psf *get_convolution(int is_linear, const char *orig_type) {
char *type = strdup(orig_type);
char *operator_index = (char *) type;
assert(type);
if (!type)
nomem();
while (*operator_index != '\0'
&& *operator_index != '^')
operator_index++;
if (*operator_index == '\0') {
free(type);
return get_scalar_mult(is_linear, orig_type);
}
*operator_index = '\0';
psf *result = new convolution(get_scalar_mult(is_linear, type), get_convolution(is_linear, operator_index + 1));
*operator_index = '^';
free(type);
return result;
}
/*
* Split the type string using the binary operator with
* lowest precedence (addition).
*/
static psf *get_summation(int is_linear, const char *orig_type) {
char *type = strdup(orig_type);
char *plus_index = (char *) type;
assert(type);
if (!type)
nomem();
while (*plus_index != '\0'
&& *plus_index != '+')
plus_index++;
if (*plus_index == '\0') {
free(type);
return get_convolution(is_linear, orig_type);
}
*plus_index = '\0';
psf *result = new sum(get_convolution(is_linear, type), get_summation(is_linear, plus_index + 1));
*plus_index = '+';
free(type);
return result;
}
public:
static psf *get(int is_linear, const char *orig_type) {
return get_summation(is_linear, orig_type);
}
};
#endif