#ifndef dg_plot_H #define dg_plot_H /* dg_plot.h -- enumeration of faces in a dyadic grid. */ /* Last edited on 2009-08-21 15:34:56 by stolfilocal */ /* The procedures in this module recursivly enumerate selected cell faces of a subtree of the infinite dyadic cell tree, keeping track of the shape of each face or cell (a tensor-style Bezier patch) and the corresponding node(s) in some finite cell tree. */ #include "mdg_grid.h" #include "dg_locus.h" #include "dg_tree.h" #include "bz_patch.h" #include "pswr.h" #include "bool.h" #include /* TREE STARS Let {T} be a finite binary tree resperesenting a finite multigrid {G}. We define the /tree star/ of any {m}-dimensional dyadic locus {E} of rank {r} as a tree pack corresponding to the star of {E} (all the cells of rank {r} incident to {E}). */ typedef void dg_locus_proc_t ( mdg_dim_t d, dg_locus_t E, mdg_rank_t r, bz_patch_t *b, dg_tree_vec_t *NE ); /* A client procedure that consumes some locus {E} of rank {r} in some {d}-dimensional finite dyadic grid. Argument {b} is either NULL or a Bézier patch associated with {E}. Domain coordinate {j} of the patch is coordinate {Spn(E)[j]} of {R^d}. Argument {NE} is the tree star of {E}. */ /* ENUMERATION OF PLOTTABLE ELEMENTS */ void dg_enum_locus_leaves ( mdg_dim_t d, dg_locus_t E, /* Root locus. */ mdg_rank_t r, /* Rank of {E}. */ bz_patch_t *b, /* Shape of {E}, or NULL. */ mdg_grid_size_t psz[], /* Size vector of the tree pack {NE}. */ dg_tree_vec_t *NE, /* Nodes of adjacent cells. */ mdg_rank_t rMax, /* Truncate the recursion just below this rank. */ dg_locus_proc_t visit /* Client face-processing procedure. */ ); /* Recursively enumerate every leaf locus {E'} descendent from {E}, of rank {r}, calling {visit} on each. Argument {NE} should be a node star for {E}, and {psz[i]} should be its size along each axis {i}. A locus is considered to be a leaf if it has rank {rMax}, or if none of nodes {NE[j]} has any children. Argument {b} describes the geometry of {E}, as in a {dg_locus_proc_t}. The leaf locus that lies in the common boundary of two loci {E'0,E'1} contained in {E} is visited only after visiting {E'0} and {E'1}. */ void dg_enum_cell_leaves ( mdg_dim_t d, mdg_cell_index_t k, bz_patch_t *b, dg_tree_vec_t *nf, /* Nodes of adjacent cells. */ mdg_rank_t rMax, /* Never split below this rank. */ dg_locus_proc_t visit /* Client face-processing procedure. */ ); /* Recursively enumerate every leaf locus contained in the closure of cell {k}, calling {visit} on each one (see {dg_enum_leaf_loci}). Argument {b} describes the geometry of {E}, as in a {dg_locus_proc_t}. Nodes {nf[0..3^d-1]} should be the enclosing nodes of the cells that are neighbors of cell {k}; specifically, {nf[fi]} should be the neighbor opposite to face {fi}. */ /* POSTSCRIPT PLOTTING OF 2D GRID ITEMS These procedures plot items of a 2D dyadic grid: vrtices, edges, or faces. Each {k}-dimensional item is drawn as a bilinear patch, and is specified by {2^k} data vectors, one for each corner. The first two components {c[0]} and {c[1]} of a corner's data vector {c} are interpreted as the corner's {X} and {Y} coordinates for plotting. The remaining components {c[2..n-1]} are interpreted as the function value at that corner. */ void dg_plot_2D_vertex(PSStream *ps, double *c, bz_patch_rdim_t n); /* Plots a vertex of a 2D finite multigrid {G}, as a small dot. The vertex has coordinates {c[0],c[1]}. The function values (components {c[2..n-1]}) are ignored. */ void dg_plot_2D_edge(PSStream *ps, double c0[], double c1[], bz_patch_rdim_t n); /* Draws an edge of a 2D finite multigrid {G}. The edge is the straight line segment connecting the points {(c0[0],c0[1])} to {(c1[0],c1[1])}. The function values (components {c0[2..n-1]} and {c1[2..n-1]}) are ignored. */ void dg_plot_2D_face_shade ( PSStream *ps, double c00[], /* Coords and values at domain corner {(0,0)}. */ double c01[], /* Coords and values at domain corner {(0,1)}. */ double c10[], /* Coords and values at domain corner {(1,0)}. */ double c11[], /* Coords and values at domain corner {(1,1)}. */ bz_patch_rdim_t n, /* Dim of point vectors (incl. function values). */ int plotDepth, /* Subdivision depth for plotting. */ double fMin, /* Minimum nominal function value. */ double fMax /* Maximum nominal function value. */ ); /* Paints a face of a 2D finite multigrid {G}. Assumes that the face is a bilinear patch whose corner positions and function values are {c00,c01,c10,c11}. It is plotted by breaking it into {4^plotDepth} sub-patches, then breaking each sub-patch into 4 triangles. Each corner may have from 0 to 3 function values (i.e. {n} may vary from 2 to 5). The function values are clipped to the range {[fMn _ fMax]} and converted to colors by some internal scale. See {dg_shade_triangle} for details. */ void dg_plot_2D_face_bands ( PSStream *ps, double c00[], /* Coords and values at domain corner {(0,0)}. */ double c01[], /* Coords and values at domain corner {(0,1)}. */ double c10[], /* Coords and values at domain corner {(1,0)}. */ double c11[], /* Coords and values at domain corner {(1,1)}. */ bz_patch_rdim_t n, /* Dim of point vectors (incl. function values). */ int plotDepth, /* Subdivision depth for plotting. */ double fStart, /* Synchronize isolines with this level. */ double fStep, /* Isoline spacing. */ int kMin, /* Minimum isoline index. */ int kMax, /* Maximum isoline index. */ double *R, double *G, double *B ); /* Paints a face of a 2D finite multigrid {G}. The face is the bilinear patch with the given corners. It is plotted by breaking it into {4^plotDepth} sub-patches, then breaking each sub-patch into 4 triangles. */ void dg_plot_2D_face_isolines ( PSStream *ps, double c00[], /* Coords and values at domain corner {(0,0)}. */ double c01[], /* Coords and values at domain corner {(0,1)}. */ double c10[], /* Coords and values at domain corner {(1,0)}. */ double c11[], /* Coords and values at domain corner {(1,1)}. */ bz_patch_rdim_t n, /* Dim of point vectors (incl. function values). */ int plotDepth, /* Subdivision depth for plotting. */ double fStart, /* Synchronize isolines with this level. */ double fStep, /* Isoline spacing. */ int kMin, /* Minimum isoline index. */ int kMax /* Maximum isoline index. */ ); /* Paints a face of a 2D finite multigrid {G}. The face is the bilinear patch with the given corners. It is plotted by breaking it into {4^plotDepth} sub-patches, then breaking each sub-patch into 4 triangles. */ /* LOW-LEVEL PLOTTING In the quadrilateral-painting procedures below, the geometry and function values of the quadrilateral {Q} are specified by its corner data vectors {p00,p01,p10,p11}. The corner coordinates are {{p00,p01,p10,p11}[0..1]}. The corresponding function values are {{p00,p01,p10,p11}[2..n-1]}. These corners should be given in row-by-row order (NOT ccw order). The quadrilateral is plotted by breaking it into 4 triangles with common vertex at the quadrilateral's barycenter {b}. The function value at {b} is assumed to be the average of the corner values. Function values are extended into the quadrilateral by affine interpolation inside each triangle. */ void dg_shade_quadrilateral ( PSStream *ps, double p00[], /* Coords and values at corner [0,0]. */ double p01[], /* Coords and values at corner [0,1]. */ double p10[], /* Coords and values at corner [1,0]. */ double p11[], /* Coords and values at corner [1,1]. */ bz_patch_rdim_t n, /* Dimension of range space. */ double fMin, /* Minimum function value. */ double fMax /* Maximum function value. */ ); /* Paints the quadrilateral with color gradient that depends on the function values. The number of function values must be at most 3 (that is, {n} must be in {2..5}). Function values are assumed to range in {[fMin _ fMax]}, and are mapped to colors according to an internal color scale. See {dg_shade_triangle} for details. */ void dg_bands_in_quadrilateral ( PSStream *ps, double p00[], /* Coords and values at domain corner {(0,0)}. */ double p01[], /* Coords and values at domain corner {(0,1)}. */ double p10[], /* Coords and values at domain corner {(1,0)}. */ double p11[], /* Coords and values at domain corner {(1,1)}. */ bz_patch_rdim_t n, /* Dim of point vectors (incl. function values). */ double fStart, /* Synchronize isolines with this level. */ double fStep, /* Isoline spacing. */ int kMin, /* Minimum isoline index. */ int kMax, /* Maximum isoline index. */ double *R, double *G, double *B ); /* Paints the quadrilateral with color bands, as approproate for an isoline plot. The function values must be scalars (i.e. {n} must be exactly 3). The band colors are defined by the tables {R,G,B}. See {pswr_bands_in_quadrilateral} for details. */ void dg_isolines_in_quadrilateral ( PSStream *ps, double p00[], /* Coords and values at corner [0,0]. */ double p01[], /* Coords and values at corner [0,1]. */ double p10[], /* Coords and values at corner [1,0]. */ double p11[], /* Coords and values at corner [1,1]. */ bz_patch_rdim_t n, /* Dimension of range space. */ double fStart, /* Synchronize isolines with this level. */ double fStep, /* Isoline spacing. */ int kMin, /* Minimum isoline index. */ int kMax /* Maximum isoline index. */ ); /* Draws isolines of function values inside the quadrilateral. The function values must be scalars (i.e. {n} must be exactly 3). See {pswr_isolines_in_quadrilateral} for details. */ /* REALLY LOW-LEVEL PLOTTING */ void dg_shade_triangle ( PSStream *ps, double a[], /* First vertex. */ double b[], /* Second vertex. */ double c[], /* Third vertex. */ bz_patch_rdim_t n, /* Dimension of range space. */ double fMin, /* Minimum function value. */ double fMax /* Maximum function value. */ ); /* Paints values of a function as color shades in a triangle {T} with given corners. The function values at corners are {{a,b,c}[2..n-1]}. The procedure computes a single function value vector {f[0..n-3]}, where {f[i]} is the average of the corner values {a[2+i],b[2+i],c[2+i]}. The result is clipped to range {[fMin _ fMax]}, and determines the color of the triangle. If {n == 2}, there are no function values; the triangle is just painted with a fixed color. If {n == 3}, there is only one function value {f[0]}; the triangle is painted with a shade between two complementary colors, depending on the position of {f[0]} in {[fMin _ fMax]}. If {n == 4}, there are two function values {f[0..1]}; the triangle is painted with a shade defined by two orthogonal pairs of complementary colors, depending on the position of {f[0]} and {f[1]} in {[fMin _ fMax]}. If {n == 5}, there are three function values {f[0..2]}; the triangle is painted with a shade that depends on the position of {f[0]}, {f[1]}, and {f[2]} in {[fMin _ fMax]}. When {n > 0}, a zero value vector is mapped to a neutral color (white or light gray). */ /* CONVENIENCE FUNCTIONS */ PSStream *dg_plot_init ( char *name, bool_t epsformat, char *paperSize, char *caption, interval_t bbox[] ); /* Opens a Postsript plotfile with given name, plus the appropriate extension (".eps" or ".ps"), and initializes it for plotting. The scales are set so that the rectangle {bbox[0] � bbox[1]} fits snugly in the available plotting area, with equal scales. The {caption}, if not NULL, is written beneath the figure. */ void dg_plot_finish(PSStream *ps); /* Finalizes and closes the Postscript plotfile {f}. */ #endif