#ifndef pz_r3_chain_H #define pz_r3_chain_H /* Sequences of points of {R^3}, closed or open. */ /* Last edited on 2015-01-20 16:49:43 by stolfilocal */ #include #include #include #include #include #include #include #include typedef r3_vec_t pz_r3_chain_t; /* A sequence of points of {R^3}, often used to represent points on the plane (with the third component set to zero). The elements may be also velocities or accelerations. The chain may be interpreted as a polygonal or a spline, closed or open, depending on the context. */ /* BASIC MANIPULATION */ /* The {DoXXX} procedures below are analogous to the {XXX} procedures, except that the result is returned in an array provided by the client (which must have the correct size). */ pz_r3_chain_t pz_r3_chain_from_int_chain ( pz_i2_chain_t *c ); /* Converts {c} to floating point, adding the third coordinate {Z==0}. */ pz_i2_chain_t pz_r3_chain_to_int_chain( pz_r3_chain_t *c ); /* Converts {c} to integer format, ignoring the {Z} coordinate and rounding {X} and {Y} to the nearest int. */ pz_r3_chain_t pz_r3_chain_from_line_segment(r3_t *p, r3_t *q, unsigned n); /* Creates a chain with {n} points equally spaced along the segment {p--q}. */ pz_r3_chain_t pz_r3_chain_cut( pz_r3_chain_t *c, unsigned start, unsigned length); void pz_r3_chain_do_cut ( pz_r3_chain_t *c, unsigned start, unsigned length, pz_r3_chain_t *x ); /* Returns a new chain that is a copy of elements from {c[start]} to {c[start+length-1]}. Assumes the chain is periodic, i.e. {c[i+n]==c[i]} for all {i}, where {n==(c.ne)}. */ void pz_r3_chain_reverse ( pz_r3_chain_t *c ); /* pz_r3_chain_reverses the direction of traversal of the Chain {c}. */ pz_r3_chain_t pz_r3_chain_extract_segment ( pz_r3_chain_t *c, pz_segment_t s ); void pz_r3_chain_do_extract_segment ( pz_r3_chain_t *c, pz_segment_t s, pz_r3_chain_t *t ); /* Extracts from {c} the part described by {s}, reversing it if {s.rev} is TRUE. */ pz_window_t pz_r3_chain_get_window ( pz_r3_chain_t *c ); /* The bounding box of chain {c}, viewed as a polygonal chain. */ r3_t pz_r3_chain_sample_barycenter ( pz_r3_chain_t *c ); /* The barycenter of all points of the chain. */ r3_t pz_r3_chain_area_barycenter ( pz_r3_chain_t *c ); /* Returns the barycenter {b} of the projection of {c} on the XY plane, seen as a polygonal *area*, with {b[2] == 0}. */ pz_r3_chain_t pz_r3_chain_translate ( pz_r3_chain_t *c, r3_t t ); void pz_r3_chain_do_translate ( pz_r3_chain_t *c, r3_t t ); /* Translates {c} by the vector {t}. {pz_r3_chain_translate} makes a new copy and translates it, leaving {c} unchanged; {pz_r3_chain_do_translate} modifies {c} itself. */ pz_r3_chain_t pz_r3_chain_map ( pz_r3_chain_t *c, hr3_pmap_t *M ); void pz_r3_chain_do_map ( pz_r3_chain_t *c, hr3_pmap_t *M ); /* Maps {c} by the given projective transformation. {pz_r3_chain_map} makes a new copy and transforms it, leaving {c} unchanged; {pz_r3_chain_do_map} modifies {c} itself. */ r3_t pz_r3_chain_center ( pz_r3_chain_t *c, pz_ctr_t ctrType ); /* Computes the curve's center as specified by {ctrType}. If {ctrType = pz_ctr_NONE}, returns {(0,0,0)}. */ void pz_r3_chain_recenter ( pz_r3_chain_t *c, pz_ctr_t ctrType ); /* Translates {c} so that its center (as specified by {ctrType}) ends up at the origin. It is a no-op if {ctrType=pz_ctr_NONE}. */ r3_t pz_r3_chain_general_dir( pz_r3_chain_t *c, double pos ); /* Returns the ``general direction'' of {c[0..n-1]}, defined as that the unit vector that points from sample {c[i]} to sample {c[n-1-i]}, where {i} is {pos*n} rounded to an integer. Thus {pos=0} uses the endpoints, {pos=0.25} uses the 1/4 and 3/4 points, etc. */ hr3_pmap_t pz_r3_chain_alignment_matrix ( pz_r3_chain_t *a, pz_r3_chain_t *b, pz_ctr_t ctrType, double pos ); /* Given two open chains {a} and {b}, returns a {4×4} matrix that moves the center of {a} (as specified by {ctrType}) to the center of {b}, and rotates {a} around the {Z} axis so that its general direction is parallel to the general direction of {b}, when both are projected on the {XY} plane. */ void pz_r3_chain_untilt ( pz_r3_chain_t *c, pz_ctr_t ctrType, double pos ); /* Performs {pz_r3_chain_recenter(c,ctrType)}, then rotates {c} around the {Z} axis so that the vector {pz_r3_chain_general_dir(c,pos)} lies on the {Y=0} plane. */ /* CHAINS AS CLOSED POLYGONS */ /* The procedures in this section interpret the chain {p} as the vertices of a closed polygonal chain with {m == (p.ne)} sides. It is assumed that each edge is traversed at constant speed, in such a way that the chain reaches vertex {p[i]} at time {t[i]}, for {i IN [0..m-1]}; and the chain goes back to vertex {p[0]} at time {t[0] + tPeriod}. */ double pz_r3_chain_linear_lengths ( pz_r3_chain_t *p, pz_double_chain_t *s ); /* Assumes that {p[j]} is the chain position at time {t[j]}. Computes the Euclidean length {s[j]} on the polygonal from vertex {p[0]} to vertex {p[j]}, for {j} in {[0..(p.ne - 1)]}. Returns the total length of the polygonal as the result of the call. */ void pz_r3_chain_linear_uniform_sample ( pz_double_chain_t *t, /* Times of input samples. */ double tPeriod, /* Time period */ pz_r3_chain_t *p, /* {p[i]} is chain position at time {t[i]}. */ double tStart, /* Time of first output sample */ pz_r3_chain_t *q /* {q[j]} will be position sample number {j}. */ ); /* Computes {n} samples along the chain, equally spaced in time, starting with time {tStart}. The samples are returned in {q[j]}, {j IN [0..n-1]}. */ void pz_r3_chain_linear_equidistant_sample ( pz_r3_chain_t *p, /* {p[i]} is chain position at time {t[i]}. */ double tStart, /* Time of first output sample */ pz_r3_chain_t *q /* {q[j]} will be position sample number {j}. */ ); /* Same as {pz_r3_chain_linear_uniform_sample}, assuming that the chain is traversed with constant velocity in unit time. */ void pz_r3_chain_linear_time_sample ( pz_double_chain_t *t, /* Times of input samples. */ double tPeriod, /* Time period */ pz_r3_chain_t *p, /* Input chain positions at times {t[i]}. */ pz_double_chain_t *r, /* Times of output samples. */ pz_r3_chain_t *q /* Output chain positions at times {r[j]}. */ ); /* Computes the positions {q[j]} at the specified times {tq[j]}, {j IN [0..n-1]}. */ /* CHAINS AS CLOSED C_1 CUBIC SPLINES */ /* The procedures in this section interpret the chains {p} and {dp} as the positions and velocities of a closed spline chain with {m == (p.ne)} cubic arcs, at the nodal times {t[0..m-1]}. It is assumed the chain goes back to vertex {p[0]} and velocity {dp[0]} at time {t[0] + tPeriod}. */ void pz_r3_chain_hermite_uniform_sample ( pz_double_chain_t *t, /* Times of input samples. */ double tPeriod, /* Time period */ pz_r3_chain_t *p, /* {p[i]} is chain position at time {t[i]}. */ pz_r3_chain_t *dp, /* {dp[i]} is velocity at time {t[i]}. */ double tStart, /* Time of first output sample */ pz_r3_chain_t *q, /* {q[j]} will be position sample number {j}. */ pz_r3_chain_t *dq /* {dq[j]} will be velocity at point {q[j]}. */ ); /* Computes {n} samples {q[0..n-1]} along the chain, and their velocities {dq[0..n-1]}, equally spaced in time, starting with time {tStart}. */ void pz_r3_chain_hermite_equidistant_sample ( pz_r3_chain_t *p, /* {p[i]} is chain position at time {t[i]}. */ double tStart, /* Time of first output sample */ pz_r3_chain_t *q, /* {q[j]} will be position sample number {j}. */ pz_r3_chain_t *dq /* {dq[j]} will be velocity at point {q[j]}. */ ); /* Same as {pz_r3_chain_hermite_uniform_sample}, assuming that the chain is traversed with constant velocity in the total time {tPeriod}. */ void pz_r3_chain_hermite_time_sample ( pz_double_chain_t *t, /* Times of input samples. */ double tPeriod, /* Time period */ pz_r3_chain_t *p, /* {p[i]} is chain position at time {t[i]}. */ pz_r3_chain_t *dp, /* {dp[i]} is velocity at time {t[i]}. */ pz_double_chain_t *r, /* Times of output samples. */ pz_r3_chain_t *q, /* {q[j]} will be chain position at time {r[j]}. */ pz_r3_chain_t *dq /* {dq[j]} will be velocity at time {r[j]}. */ ); /* Computes the positions {q[j]} and velocities {dq[j]} at the specified times {r[j]}, {j IN [0..n-1]}. */ typedef r3_t pz_r3_chain_vel_estimator_t ( double a, r3_t *pa, double b, r3_t *pb, double c, r3_t *pc ); void pz_r3_chain_estimate_velocities ( pz_double_chain_t *t, double tPeriod, pz_r3_chain_t *p, pz_r3_chain_t *dp, pz_r3_chain_vel_estimator_t est ); /* Estimates the velocity {dp[i]} at each point {p[i]}, by applying the estimator {est} to three consecutive times. */ /* INPUT/OUTPUT */ double pz_r3_chain_adjust_unit ( double givenUnit, pz_r3_chain_t *c ); /* Adjusts the {givenUnit} if needed to avoid overflow or excessive error when quantizing the values in {c}. May print warnings to {stderr}. */ typedef struct pz_r3_chain_read_data_t { char *cmt; /* Comment text */ unsigned samples; /* Number of samples in chain. */ pz_r3_chain_t c; /* The samples */ double unit; /* Unit that was used when writing the data */ } pz_r3_chain_read_data_t; pz_r3_chain_read_data_t pz_r3_chain_read ( FILE *rd, bool_t header_only, pz_ctr_t recenter ); /* Reads a chain (and its comments) from {rd}. If {header_only==TRUE}, reads only the parameters, and leaves the {c} field as NULL. If {recenter} is not {pz_ctr_NONE}, displaces the chain so that the point {pz_r3_chain_center(c,recenter)} ends up at the origin. */ void pz_r3_chain_write ( FILE *wr, char *cmt, pz_r3_chain_t *c, double unit ); /* Writes chain {c} to {wr}, prefixed with comments {cmt}. The coordinates will be written as integer multiples of the given {unit}. */ typedef struct pz_r3_chain_read_all_data_t { pz_r3_chain_read_data_t *chData; double unitMin; /* Minimum quantization unit. */ double unitMax; /* Maximum quantization unit. */ char *cmt; /* Comment of first chain, if any. */ } pz_r3_chain_read_all_data_t; pz_r3_chain_read_all_data_t pz_r3_chain_read_all ( char *prefix, unsigned band, char *extension, bool_vec_t *sel, bool_t header_only, pz_ctr_t recenter, char *dir /* default was "." */ ); /* Reads a set of numbered chains, returns a {pz_r3_chain_read_all_data_t} record {r}. Chain number {i} is read if and only if {sel[i] == TRUE}, and its {pz_r3_chain_read_data_t} is stored in {r.chain[i]}; otherwise {r.chain[i] } is set to a record with null {c} field. The data is read from file "{DDD}/{KKKK}/{PPP}{BBB}{EEE}", where {DDD} is the directory {dir}, {KKKK} is the chain number {k} (4 digits, zero padded), {PPP} is the given {prefix}, {BBB} is the {band} number (3 digits, zero padded), and {EEE} is the given {extension}. If {header_only=TRUE}, only the header of each file is read; the {c} fields are all set to NULL. If {recenter} is not {pz_ctr_NONE}, displaces the chain so that the point {pz_r3_chain_center(c,recenter)} ends up at the origin. The range of quantization {unit}s of the chains that were read is returned in {r.unitMin}, {r.unitMax}. The comment of the first chain read, plus the call arguments, are stored in {r.cmt}. */ /* FOURIER ANALYSIS AND SYNTHESIS */ void pz_r3_chain_fourier_transform ( pz_r3_chain_t *c, pz_r3_chain_t *f ); /* Computes the Fourier spectrum {f} of chain {c}. The sizes {c.ne} and {f.ne} must be the same power of two. */ void pz_r3_chain_inv_fourier_transform ( pz_r3_chain_t *f, pz_r3_chain_t *c ); /* Computes a chain {c} given its Fourier spectrum {f}. Their sizes must be equal and a power of two. WARNING: destroys {f} in the process. */ /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP). Authors: Helena C. G. Leitão and Jorge Stolfi. This file can be freely distributed, used, and modified, provided that this copyright and authorship notice is preserved, and that any modified versions are clearly marked as such. This software has NO WARRANTY of correctness or applicability for any purpose. Neither the authors nor their employers chall be held responsible for any losses or damages that may result from its use. */ #endif