#ifndef rdo_approx_basis_H #define rdo_approx_basis_H /* Approximation basis for functions defined on sites. */ #define rdo_approx_basis_H_COPYRIGHT "Copyright © 2008 Danillo Pereira and J. Stolfi, UNICAMP" /* Last edited on 2008-08-17 13:53:55 by stolfi */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include /* !!! Refactor {basis_elem_type_t} into: windowing function, weight function, unit sum flag. !!! */ typedef enum { basis_elem_type_Ball, /* Support indicator element --- 1 inside radius, 0 outside. */ basis_elem_type_Radial, /* Gaussian radial-type element. */ basis_elem_type_Shepard, /* Shepard-type element. */ basis_elem_type_RadialShepard, /* As in paper "Meshless Finite...Global Ilumination" !!! */ basis_elem_type_None /* Unspecified or null finite element. */ } basis_elem_type_t; /* A code that specifies the finite element type. */ typedef struct basis_elem_t { basis_elem_type_t tpElem; /* Finite element type. */ dist_type_t tpDist; /* Distance function type. */ point3_t position; /* Nominal center point. */ vector3_t normal; /* Nominal normal direction. */ double radius; /* Nominal support radius. */ } basis_elem_t; /* A record that describes a an element of an approximation basis for functions defined over the sites of a scene. Each element {e} is a real function of sites, usually with a small and compact support. The element is defined by its type {tpElem}, by the site metric {tpDist}, by its nominal geometry {position,normal,radius}. The meaning of these three parameters depends on {tpElem}, but it is assumed that the element's value {e(s)} is zero for any site {s} such that {dist(s,(position,normal)) >= radius} in the metric {tpDist}. */ vec_typedef(approx_basis_t, approx_basis, basis_elem_t); /* Defines the type {approx_basis_t} as a self-bounded vector of {basis_elem_t}s. The elements of an {approx_basis_t} {B} are {B.e[0..B.ne-1]}. Also defines the functions {approx_basis_new()}, {approx_basis_expand()}, {approx_basis_trim()}, and {approx_basis_free()}. */ typedef struct approx_basis_options_t { int numNeighbors; /* Max count of other element centers allowed inside the support. */ } approx_basis_options_t; /* A record that contains the parrameters that determine the choice of an approx basis (besides {tpElem} e {tpDist}). */ approx_basis_t rdo_approx_basis_create ( dist_type_t tpDist, basis_elem_type_t tpElem, site_t sb[], double rb[], int n ); /* Creates an approximation basis with {n} elements of type {tpElem}, centered at sites {sb[0..n-1]}, with nominal radii {rb[0..n-1]} in the metric {tpDist}. */ double rdo_approx_basis_elem_raw_value(basis_elem_t *e, site_t *st); /* Computes the `raw' (unnormalized) value of element {*e} at site {*st}. Note that this value may require normalization, that depends on the other members of the basis; see {rdo_approx_basis_eval_all_elements} below. */ bool_t rdo_basis_approx_element_needs_normalization(basis_elem_type_t tpElem); /* Returns {TRUE} iff the values of basis elements of type {tpElem} need to be normalized to unit sum. This is the case, for example, for the types {basis_elem_type_Shepard} and {basis_elem_type_RadialShepard}. */ void rdo_approx_basis_eval_all_elements(approx_basis_t *bas, site_t *st, double v[]); /* Computes the raw values {v[j]} of element {j} at site {*st}, for every {j} in the range {0 .. bas->ne-1}. If all elements require normalization, applies {rdo_approx_basis_normalize_to_unit_sum} to {v[]}. If none of the elements requires normalization, leaves {v[]} as is. Fails if some elements require normalization and some don't. */ void rdo_approx_basis_normalize_to_unit_sum(double v[], int n); /* Multiplies the values {v[0..n-1]} by a single scale factor {s} such that their sum becomes 1.0. If any of the values {v[i]} is {NAN}, sets all of them to {NAN}. Otherwise, if one of the values {v[i]} is {+INF}, sets that value will to 1.0, and the others to 0.0. Fails if there are two or more values equal to {+INF}, or any value equal to {-INF}. */ double rdo_approx_basis_eval_element_Ball(basis_elem_t *e, site_t *st); double rdo_approx_basis_eval_element_Radial(basis_elem_t *e, site_t *st); double rdo_approx_basis_eval_element_Shepard(basis_elem_t *e, site_t *st); double rdo_approx_basis_eval_element_RadialShepard(basis_elem_t *e, site_t *st); /* Evaluates a basis element {e} of a specific type, on the given site {*st}. */ approx_basis_options_t *rdo_approx_basis_options_parse(argparser_t *pp); /* Parses the command line options that describe the approximation basis, as described in {approx_basis_options_HELP} and {approx_basis_options_INFO}. */ #define approx_basis_options_HELP \ " [ -numNeighbors {N_NEIGH} ]" #define approx_basis_options_INFO \ " -numNeighbors {N_NEIGH}\n" \ " This optional parameter defines the number of sampling" \ " sites allowed inside the nominal support of each basis element" \ " (excluding the centroid of the element itself). If not specified," \ " the program assumes \"-numNeighbors 10\"." void rdo_approx_basis_elem_write(FILE *wr, basis_elem_t *be); /* Writes to {wr} a description of the basis element {*be}. */ basis_elem_t rdo_approx_basis_elem_read(FILE *rd); /* Reads from {rd} a description of a basis element. */ approx_basis_t rdo_approx_basis_read(FILE *arq); /* Reads an approximation basis from file {arq}. */ void rdo_approx_basis_write(FILE *arq, approx_basis_t *bas); /* Writes to file {arq} the approximation basis {bas}. */ dspmat_t rdo_approx_basis_build_matrix(site_vec_t *sts, approx_basis_t *bas, int avgCover); /* Builds the basis value matrix {M} that converts coefficients {L[0..nsb-1]} of the approximation basis {bas} to the radiances {B[0..nsx-1]} of an arbitrary set of sites {sts[0..sts->ne-1]}. The value of {M[i,j]} is the value of element {j} of bas at site {i} of {sts}. The {avgCover} parameter should be an estimate of the average number of non-zero entries in each column of the matrix; that is, the average number of sites {stts->e[i]} where a basis element {bas->e[j]} is nonzero. (This parameter is used only as a hint to estimate the number of non-zero entries in the initial allocation.) */ double rdo_approx_basis_pick_elem_radius(dist_type_t tpDist, site_vec_t *sts, int i, int m); /* Returns the largest value {R} such that there are only {m} sites with distance {R} or less from {sts->e[i]} on the same solid object as {sts->e[i]}, excluding the site {sts->e[i]} itself. In other words, returns the distance from {sts->e[i]} to the {m+1}th other site on the same object in order of increasing distance from {sts->e[i]}. Ignores sites at infinite distance Uses the metric {tpDist}. If there are only {m} os less valid candidates, returns the distance from {sts->e[i]} to the most distant of those candidates, times a suitable correction factor. If there is no valid candidate, returns {NaN}. */ #endif