198 lines
5.2 KiB
C++
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", ¶m) != 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", ¶m) != 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", ¶m) != 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
|