TwoDMeshPlot.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton, Teviet Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /********************************* <lalVerbatim file="TwoDMeshPlotCV">
00021 Author: Creighton, T. D.
00022 $Id: TwoDMeshPlot.c,v 1.6 2007/06/08 14:41:52 bema Exp $
00023 **************************************************** </lalVerbatim> */
00024 
00025 /********************************************************** <lalLaTeX>
00026 
00027 \subsection{Module \texttt{TwoDMeshPlot.c}}
00028 \label{ss:TwoDMeshPlot.c}
00029 
00030 Plots a hierarchical mesh of templates on an 2-dimensional parameter
00031 space.
00032 
00033 \subsubsection*{Prototypes}
00034 \vspace{0.1in}
00035 \input{TwoDMeshPlotCP}
00036 \idx{LALPlotTwoDMesh()}
00037 
00038 \subsubsection*{Description}
00039 
00040 This routine creates a PostScript plot of the parameter mesh list
00041 pointed to by \verb@mesh@, using the plotting parameters given in
00042 \verb@*params@.  The PostScript output is printed to the writable
00043 output stream \verb@*stream@ using \verb@fprintf()@.
00044 
00045 \subsubsection*{Algorithm}
00046 
00047 The algorithm is set up so that it requires only one pass through the
00048 list.  After defining PostScript macros to plot mesh points, mesh
00049 tiles, and mismatch ellipses, the routine then defines a macro to plot
00050 the boundary.  Since some PostScript interpreters will fail if a macro
00051 contains too many objects, the boundary-plotting macro may be split
00052 into several macros.
00053 
00054 \verb@LALPlotTwoDMesh()@ then calls a static (but LAL-compliant)
00055 subroutine \verb@LALMakeMeshMacro()@ to create one or more macros to
00056 plot the mesh points, tiles, or ellipses, as required by
00057 \verb@*params@.  This subroutine takes a pointer to the head of a list
00058 of mesh points as input, and traverses down the list, calling itself
00059 recursively on any submeshes it encounters (if
00060 \verb@params->maxLevels@ permits).
00061 
00062 While plotting the boundary and other mesh objects,
00063 \verb@LALPlotTwoDMesh()@ and \verb@LALMakeMeshMacro()@ keep track of
00064 the bounding box surrounding all plotted objects.  This is used either
00065 to set a bounding box for the overall plot, or to adjust the scale of
00066 the plot, depending on \verb@params->autoscale@.  If the resulting
00067 bounding box is larger than a single $8.5''\times11''$ page,
00068 \verb@LALPlotTwoDMesh()@ will divide the plot area up into pages of
00069 this side, calling the plotting macros on each page.
00070 
00071 \subsubsection*{Uses}
00072 \begin{verbatim}
00073 LALMalloc()             LALFree()
00074 \end{verbatim}
00075 
00076 \subsubsection*{Notes}
00077 
00078 \vfill{\footnotesize\input{TwoDMeshPlotCV}}
00079 
00080 ******************************************************* </lalLaTeX> */
00081 
00082 #include <math.h>
00083 #include <lal/LALStdlib.h>
00084 #include <lal/LALConstants.h>
00085 #include <lal/TwoDMesh.h>
00086 #include "TwoDMeshPlot.h"
00087 
00088 NRCSID( TWODEMESHPLOTC, "$Id: TwoDMeshPlot.c,v 1.6 2007/06/08 14:41:52 bema Exp $" );
00089 
00090 /* Local constants. */
00091 #define TWODMESHPLOTC_MAXOBJ 797 /* Maximum number of objects in a
00092                                     PostScript macro */
00093 
00094 /* Local datatypes. */
00095 typedef struct tagMeshMacroParamStruc {
00096   UINT4 nMacro;                  /* running count of macro number */
00097   UINT4 nObj;                    /* running count number of objects */
00098   UINT4 level;                   /* current recursion level */
00099   TwoDMeshPlotStruc *plotParams; /* top-level plotting parameters */
00100 } MeshMacroParamStruc;
00101 
00102 /* Local prototypes. */
00103 static void
00104 LALMakeMeshMacro( LALStatus           *stat,
00105                   FILE                *stream,
00106                   TwoDMeshNode        *mesh,
00107                   MeshMacroParamStruc *params );
00108 
00109 static void
00110 AdjustBBox( REAL4 x, REAL4 y, TwoDMeshPlotStruc *params );
00111 
00112 
00113 /* <lalVerbatim file="TwoDMeshPlotCP"> */
00114 void
00115 LALPlotTwoDMesh( LALStatus         *stat,
00116                  FILE              *stream,
00117                  TwoDMeshNode      *mesh,
00118                  TwoDMeshPlotStruc *params )
00119 { /* </lalVerbatim> */
00120   UINT4 i;          /* an index */
00121   UINT4 nObj = 0;   /* counter of number of objects boundary macro */
00122   UINT4 nMacro = 0; /* counter of number of boundary macros */
00123   UINT4 nPage = 0;  /* number of pages plotted */
00124   REAL4 bBox[4];    /* bounding box in plot coordinates */
00125   REAL4 xOff, yOff; /* horizontal and vertical offsets */
00126   MeshMacroParamStruc macroParams; /* parameters for
00127                                       LALMakeMeshMacro() */
00128 
00129   INITSTATUS( stat, "LALPlotTwoDMesh", TWODEMESHPLOTC );
00130   ATTATCHSTATUSPTR( stat );
00131 
00132   /* Check that arguments and their fields exist. */
00133   ASSERT( stream, stat, TWODMESHPLOTH_ENUL, TWODMESHPLOTH_MSGENUL );
00134   ASSERT( mesh, stat, TWODMESHPLOTH_ENUL, TWODMESHPLOTH_MSGENUL );
00135   ASSERT( params, stat, TWODMESHPLOTH_ENUL, TWODMESHPLOTH_MSGENUL );
00136   if ( params->nLevels ) {
00137     ASSERT( params->plotPoints, stat, TWODMESHPLOTH_ENUL,
00138             TWODMESHPLOTH_MSGENUL );
00139     ASSERT( params->plotTiles, stat, TWODMESHPLOTH_ENUL,
00140             TWODMESHPLOTH_MSGENUL );
00141     ASSERT( params->plotEllipses, stat, TWODMESHPLOTH_ENUL,
00142             TWODMESHPLOTH_MSGENUL );
00143     ASSERT( params->params, stat, TWODMESHPLOTH_ENUL,
00144             TWODMESHPLOTH_MSGENUL );
00145   }
00146 
00147   /* Perform some setup. */
00148   if ( params->autoscale )
00149     memcpy( bBox, params->bBox, 4*sizeof(REAL4) );
00150   params->bBox[0] = params->bBox[1] = LAL_REAL4_MAX;
00151   params->bBox[2] = params->bBox[3] = -LAL_REAL4_MAX;
00152   params->cosTheta = cos( LAL_PI_180*params->theta );
00153   params->sinTheta = sin( LAL_PI_180*params->theta );
00154   params->clip = ( ( params->clipBox[2] > params->clipBox[0] ) &&
00155                    ( params->clipBox[3] > params->clipBox[1] ) );
00156 
00157   /* Write the PostScript header. */
00158   fprintf( stream,
00159            "%%!PS-Adobe-1.0\n"
00160            "%%%%Creator: LALPlotTwoDMesh()\n"
00161            "%%%%Title: mesh.ps\n"
00162            "%%%%BoundingBox: %i %i %i %i\n"
00163            "%%%%EndComments\n\n",
00164            TWODMESHPLOTH_XMARG, TWODMESHPLOTH_YMARG,
00165            TWODMESHPLOTH_XMARG + TWODMESHPLOTH_XSIZE,
00166            TWODMESHPLOTH_YMARG + TWODMESHPLOTH_YSIZE );
00167 
00168   /* Write PostScript macros for plotting mesh points.  The macros are
00169      called simply as "point[N]", where [N] is the recursive submesh
00170      level. */
00171   for ( i = 0; i < params->nLevels; i++ )
00172     if ( params->plotPoints[i] > 0 )
00173       fprintf( stream,
00174                "/point%u { gsave currentpoint translate %f %f scale\n"
00175                "  auto auto scale %f rotate\n"
00176                "  newpath 0 0 %u 0 360 arc closepath fill grestore }"
00177                " def\n",
00178                i, 1.0/params->xScale, 1.0/params->yScale,
00179                -params->theta, params->plotPoints[i] );
00180     else if ( params->plotPoints[i] < 0 )
00181       fprintf( stream,
00182                "/point%u { gsave currentpoint translate %f %f scale\n"
00183                "  auto auto scale %f rotate\n"
00184                "  newpath 0 0 r%u 0 360 arc closepath stroke grestore }"
00185                " def\n",
00186                i, 1.0/params->xScale, 1.0/params->yScale,
00187                -params->theta, i );
00188 
00189   /* Write PostScript macro for plotting ellipses.  The macro is
00190      called as "[axis1] [axis2] [angle] ellipse", where [axis1] and
00191      [axis2] are the two principal axis lengths, and [angle] is the
00192      angle in degrees counterclockwise from the x-axis to the first
00193      principal axis. */
00194   fprintf( stream,
00195            "/ellipse { gsave currentpoint translate rotate scale\n"
00196            "  newpath 0 0 1 0 360 arc closepath stroke grestore } def\n" );
00197 
00198   /* Write PostScript macro for plotting tiles.  The macro is called
00199      as "[dx] [dy1] [dy2] tile", where [dx] is the half-width of the
00200      tile, and [dy1], [dy2] are the heights of the corners of the tile
00201      relative to the centre. */
00202   fprintf( stream,
00203            "/tile { gsave currentpoint translate 3 copy\n"
00204            "  dup 4 1 roll exch 4 1 roll moveto sub 0 exch rlineto\n"
00205            "  2 copy add neg 4 3 roll -2 mul exch rlineto\n"
00206            "  sub neg 0 exch rlineto closepath stroke grestore } def\n" );
00207 
00208   /* Write PostScript macro to clip the x-y area, if necessary. */
00209   if ( params->clip )
00210     fprintf( stream,
00211              "/xyclip { %f %f moveto %f %f lineto %f %f lineto\n"
00212              "  %f %f lineto closepath clip } def\n",
00213              params->clipBox[0], params->clipBox[1],
00214              params->clipBox[0], params->clipBox[3],
00215              params->clipBox[2], params->clipBox[3],
00216              params->clipBox[2], params->clipBox[1] );
00217 
00218   /* Write PostScript macros for plotting boundary, if necessary. */
00219   if ( params->nBoundary >= 2 ) {
00220     REAL4 x, x0, dx;   /* x coordinate, initial value, and increment */
00221     REAL4 *yBound;     /* array of y-values of boundary points */
00222     yBound = (REAL4 *)LALMalloc( 2*params->nBoundary*sizeof(REAL4) );
00223     if ( yBound == NULL ) {
00224       ABORT( stat, TWODMESHPLOTH_EMEM, TWODMESHPLOTH_MSGEMEM );
00225     }
00226 
00227     /* Fill array of boundary points. */
00228     x0 = params->params->domain[0];
00229     dx = ( params->params->domain[1] - x0 )/( params->nBoundary - 1 );
00230     for ( i = 0; i < params->nBoundary - 1; i++ ) {
00231       x = x0 + i*dx;
00232       (params->params->getRange)( stat->statusPtr, yBound + 2*i, x,
00233                                   params->params->rangeParams );
00234       BEGINFAIL( stat )
00235         LALFree( yBound );
00236       ENDFAIL( stat );
00237     }
00238     x = params->params->domain[1];
00239     (params->params->getRange)( stat->statusPtr, yBound + 2*i, x,
00240                                 params->params->rangeParams );
00241     BEGINFAIL( stat )
00242       LALFree( yBound );
00243     ENDFAIL( stat );
00244 
00245     /* Write macro. */
00246     fprintf( stream,
00247              "/boundary%u {\n"
00248              "%f %f moveto\n", nMacro, x0, yBound[1] );
00249     nObj = 3;
00250     for ( i = 1; i < params->nBoundary - 1; i++ ) {
00251       x = x0 + i*dx;
00252       fprintf( stream, "%f %f lineto\n", x, yBound[2*i+1] );
00253       AdjustBBox( x, yBound[2*i+1], params );
00254       nObj += 3;
00255       if ( nObj > TWODMESHPLOTC_MAXOBJ ) {
00256         fprintf( stream,
00257                  "stroke } def\n"
00258                  "/boundary%u {\n"
00259                  "%f %f moveto\n", ++nMacro, x, yBound[2*i+1] );
00260         nObj = 3;
00261       }
00262     }
00263     x = params->params->domain[1];
00264     fprintf( stream, "%f %f lineto\n", x, yBound[2*i+1] );
00265     fprintf( stream, "%f %f lineto\n", x, yBound[2*i] );
00266     AdjustBBox( x, yBound[2*i+1], params );
00267     AdjustBBox( x, yBound[2*i], params );
00268     nObj += 6;
00269     for ( i = params->nBoundary - 2; i < (UINT4)( -1 ); i-- ) {
00270       x = x0 + i*dx;
00271       fprintf( stream, "%f %f lineto\n", x, yBound[2*i] );
00272       AdjustBBox( x, yBound[2*i], params );
00273       nObj += 3;
00274       if ( nObj > TWODMESHPLOTC_MAXOBJ ) {
00275         fprintf( stream,
00276                  "stroke } def\n"
00277                  "/boundary%u {\n"
00278                  "%f %f moveto\n", ++nMacro, x, yBound[2*i] );
00279         nObj = 3;
00280       }
00281     }
00282     fprintf( stream,
00283              "%f %f lineto\n"
00284              "stroke } def\n", x0, yBound[1] );
00285     nMacro++;
00286     LALFree( yBound );
00287   }
00288 
00289   /* Set up parameters for LALMakeMeshMacro(). */
00290   macroParams.nMacro = 0;
00291   macroParams.nObj = 0;
00292   macroParams.level = 0;
00293   macroParams.plotParams = params;
00294 
00295   /* Write PostScript macro for plotting the mesh.  The routine
00296      MakeMeshMacro() traverses the linked list, adding a line to the
00297      macro for each node, and calling itself recursively on any
00298      submeshes. */
00299   fprintf( stream, "\n/mesh%u {\n", macroParams.nMacro );
00300   TRY( LALMakeMeshMacro( stat->statusPtr, stream, mesh,
00301                          &macroParams ), stat );
00302   fprintf( stream, "} def\n" );
00303 
00304   /* Increment macro counter only if the last macro list is not
00305      empty. */
00306   if ( macroParams.nObj > 0 )
00307     macroParams.nMacro++;
00308 
00309   /* Autoscale the axes, if necessary. */
00310   if ( params->autoscale ) {
00311     REAL4 xScaleFac = params->bBox[2] - params->bBox[0];
00312     REAL4 yScaleFac = params->bBox[3] - params->bBox[1];
00313     if ( ( xScaleFac == 0.0 ) && ( yScaleFac == 0.0 ) ) {
00314       ABORT( stat, TWODMESHPLOTH_ENOPLOT, TWODMESHPLOTH_MSGENOPLOT );
00315     }
00316     xScaleFac = ( bBox[2] - bBox[0] )/xScaleFac;
00317     yScaleFac = ( bBox[3] - bBox[1] )/yScaleFac;
00318     if ( yScaleFac < xScaleFac )
00319       xScaleFac = yScaleFac;
00320     params->xScale *= xScaleFac;
00321     params->yScale *= xScaleFac;
00322     for ( i = 0; i < 4; i++ )
00323       params->bBox[i] *= xScaleFac;
00324     fprintf( stream, "/auto %f def\n", 1.0/xScaleFac );
00325   } else
00326     fprintf( stream, "/auto 1 def\n" );
00327 
00328   /* Set up coordinate system. */
00329   if ( params->bBox[2] > params->bBox[0] ) {
00330     bBox[0] = params->bBox[0];
00331     bBox[2] = params->bBox[2];
00332   } else {
00333     bBox[0] = params->bBox[2];
00334     bBox[2] = params->bBox[0];
00335   }
00336   if ( params->bBox[3] > params->bBox[1] ) {
00337     bBox[3] = params->bBox[3];
00338     bBox[1] = params->bBox[1];
00339   } else {
00340     bBox[3] = params->bBox[1];
00341     bBox[1] = params->bBox[3];
00342   }
00343   nPage = 0;
00344 
00345   /* Set the global graphics state. */
00346   fprintf( stream, "\n0 setlinewidth 0 setgray\n" );
00347 
00348   /* Define an overall clipping region for all pages. */
00349   fprintf( stream, "%i %i moveto %i %i lineto %i %i lineto\n"
00350            "%i %i lineto closepath clip newpath\n",
00351            TWODMESHPLOTH_XMARG, TWODMESHPLOTH_YMARG,
00352            TWODMESHPLOTH_XMARG,
00353            TWODMESHPLOTH_YMARG + TWODMESHPLOTH_YSIZE,
00354            TWODMESHPLOTH_XMARG + TWODMESHPLOTH_XSIZE,
00355            TWODMESHPLOTH_YMARG + TWODMESHPLOTH_YSIZE,
00356            TWODMESHPLOTH_XMARG + TWODMESHPLOTH_XSIZE,
00357            TWODMESHPLOTH_YMARG );
00358 
00359   /* Plot macros on each page. */
00360   for ( yOff = params->bBox[1] - TWODMESHPLOTH_YMARG;
00361         yOff < params->bBox[3] - TWODMESHPLOTH_YMARG - 1;
00362         yOff += TWODMESHPLOTH_YSIZE )
00363     for ( xOff = params->bBox[0] - TWODMESHPLOTH_XMARG;
00364           xOff < params->bBox[2] - TWODMESHPLOTH_XMARG - 1;
00365           xOff += TWODMESHPLOTH_XSIZE ) {
00366       fprintf( stream, "\n"
00367                "%%%%Page: %u\n"
00368                "gsave %f %f translate %f rotate %f %f scale",
00369                ++nPage, -xOff, -yOff, params->theta, params->xScale,
00370                params->yScale );
00371       if ( params->clip )
00372         fprintf( stream, " xyclip\n" );
00373       else
00374         fprintf( stream, "\n" );
00375       for ( i = 0; i < nMacro; i++ )
00376         fprintf( stream, "boundary%u\n", i );
00377       for ( i = 0; i < macroParams.nMacro; i++ )
00378         fprintf( stream, "mesh%u\n", i );
00379       fprintf( stream, "showpage grestore\n" );
00380     }
00381 
00382   /* Finished plotting.  Restore params->bBox to its original setting,
00383      if necessary. */
00384   fprintf( stream, "\n%%%%EOF\n" );
00385   if ( params->autoscale )
00386     memcpy( params->bBox, bBox, 4*sizeof(REAL4) );
00387   DETATCHSTATUSPTR( stat );
00388   RETURN( stat );
00389 }
00390 
00391 
00392 static void
00393 LALMakeMeshMacro( LALStatus           *stat,
00394                   FILE                *stream,
00395                   TwoDMeshNode        *mesh,
00396                   MeshMacroParamStruc *params )
00397      /* This routine writes lines to the macro to draw the mesh
00398         points, tiles, and ellipses (as required), for the list
00399         pointed to by mesh.  It calls itself recursively on any
00400         submeshes, if the current recursion level is less than the
00401         maximum requested recursion level.  Along the way it adjusts
00402         the bounding box for the figure. */
00403 {
00404   UINT4 rLevel;         /* current recursion depth */
00405   BOOLEAN plotPoints;   /* whether to plot mesh points at this level */
00406   BOOLEAN plotEllipses; /* whether to plot ellipses at this level */
00407   BOOLEAN plotTiles;    /* whether to plot tiles at this level */
00408   BOOLEAN plotAny;      /* whether to plot anything at this level */
00409 
00410   /* Pointer to the metric function, its optional arguments, and the
00411      mismatch value, for the current recursion level. */
00412   void (*getMetric)( LALStatus *, REAL4 [3], REAL4 [2], void *) = NULL;
00413   void *metricParams = NULL;
00414   REAL4 mThresh = 0.0;
00415 
00416   INITSTATUS( stat, "LALMakeMeshMacro", TWODEMESHPLOTC );
00417   ATTATCHSTATUSPTR( stat );
00418 
00419   ASSERT( params, stat, TWODMESHPLOTH_ENUL, TWODMESHPLOTH_MSGENUL );
00420   ASSERT( params->plotParams, stat, TWODMESHPLOTH_ENUL,
00421           TWODMESHPLOTH_MSGENUL );
00422 
00423   /* Do nothing if we're beyond the maximum recursion level. */
00424   if ( ( rLevel = params->level ) >= params->plotParams->nLevels ) { 
00425     DETATCHSTATUSPTR( stat );
00426     RETURN( stat );
00427   }
00428 
00429   /* Otherwise, determine what needs to be plotted at this level. */
00430   plotPoints = ( params->plotParams->plotPoints[rLevel] != 0 );
00431   plotTiles = params->plotParams->plotTiles[rLevel];
00432   plotEllipses = params->plotParams->plotEllipses[rLevel];
00433   plotAny = ( plotPoints || plotTiles || plotEllipses );
00434   if ( plotEllipses ) {
00435     getMetric = params->plotParams->params[rLevel].getMetric;
00436     metricParams = params->plotParams->params[rLevel].metricParams;
00437     mThresh = params->plotParams->params[rLevel].mThresh;
00438   }
00439 
00440   /* Move down the list, plotting what needs to be plotted. */
00441   while ( mesh != NULL ) {
00442 
00443     if ( plotAny ) {
00444       fprintf( stream, "%f %f moveto", mesh->x, mesh->y );
00445       if ( plotPoints ) {
00446         fprintf( stream, " point%u", rLevel );
00447         AdjustBBox( mesh->x, mesh->y, params->plotParams );
00448         params->nObj += 1;
00449       }
00450       if ( plotTiles ) {
00451         fprintf( stream, " %f %f %f tile", mesh->dx, mesh->dy[0],
00452                  mesh->dy[1] );
00453         AdjustBBox( mesh->x - mesh->dx, mesh->y - mesh->dy[0],
00454                     params->plotParams );
00455         AdjustBBox( mesh->x - mesh->dx, mesh->y - mesh->dy[1],
00456                     params->plotParams );
00457         AdjustBBox( mesh->x + mesh->dx, mesh->y + mesh->dy[0],
00458                     params->plotParams );
00459         AdjustBBox( mesh->x + mesh->dx, mesh->y + mesh->dy[1],
00460                     params->plotParams );
00461         params->nObj += 4;
00462       }
00463       if ( plotEllipses ) {
00464         REAL4 position[2];  /* location of current mesh point */
00465         REAL4 metric[3];    /* value of the metric at position */
00466         REAL4 axes[2];      /* lengths of principal axes of ellipse */
00467         REAL4 theta;        /* angle from x-axis to axis[0] */
00468         REAL4 cost, sint;   /* cosine and sine of theta */
00469         REAL4 lambda;       /* eigenvalue of metric */
00470         REAL4 term1, term2; /* temporary variables */
00471 
00472         /* Get metric and angle. */
00473         position[0] = mesh->x;
00474         position[1] = mesh->y;
00475         TRY( (getMetric)( stat->statusPtr, metric, position,
00476                           metricParams ), stat );
00477         theta = 0.5*atan2( -2.0*metric[2], metric[1] - metric[0] );
00478         cost = cos( theta );
00479         sint = sin( theta );
00480 
00481         /* Get first principal axis. */
00482         term1 = fabs( metric[0]*cost + metric[2]*sint );
00483         term2 = fabs( metric[2]*cost + metric[1]*sint );
00484         if ( term1 > term2 ) {
00485           term2 /= term1;
00486           lambda = term1*sqrt( 1.0 + term2*term2 );
00487         } else {
00488           term1 /= term2;
00489           lambda = term2*sqrt( 1.0 + term1*term1 );
00490         }
00491         if ( lambda <= 0.0 ) {
00492           ABORT( stat, TWODMESHPLOTH_EMETRIC,
00493                  TWODMESHPLOTH_MSGEMETRIC );
00494         }
00495         axes[0] = sqrt( mThresh / lambda );
00496 
00497         /* Get second principal axis. */
00498         term1 = fabs( metric[0]*sint - metric[2]*cost );
00499         term2 = fabs( metric[2]*sint - metric[1]*cost );
00500         if ( term1 > term2 ) {
00501           term2 /= term1;
00502           lambda = term1*sqrt( 1.0 + term2*term2 );
00503         } else {
00504           term1 /= term2;
00505           lambda = term2*sqrt( 1.0 + term1*term1 );
00506         }
00507         if ( lambda <= 0.0 ) {
00508           ABORT( stat, TWODMESHPLOTH_EMETRIC,
00509                  TWODMESHPLOTH_MSGEMETRIC );
00510         }
00511         axes[1] = sqrt( mThresh / lambda );
00512 
00513         /* Plot ellipse. */
00514         fprintf( stream, " %f %f %f ellipse", axes[0], axes[1],
00515                  theta*(REAL4)( LAL_180_PI ) );
00516         AdjustBBox( mesh->x + axes[0]*cost - axes[1]*sint,
00517                     mesh->y + axes[0]*sint + axes[1]*cost,
00518                     params->plotParams );
00519         AdjustBBox( mesh->x - axes[0]*cost - axes[1]*sint,
00520                     mesh->y - axes[0]*sint + axes[1]*cost,
00521                     params->plotParams );
00522         AdjustBBox( mesh->x - axes[0]*cost + axes[1]*sint,
00523                     mesh->y - axes[0]*sint - axes[1]*cost,
00524                     params->plotParams );
00525         AdjustBBox( mesh->x + axes[0]*cost + axes[1]*sint,
00526                     mesh->y + axes[0]*sint - axes[1]*cost,
00527                     params->plotParams );
00528         params->nObj += 4;
00529       }
00530       fprintf( stream, "\n" );
00531 
00532       /* Start a new macro if necessary. */
00533       if ( params->nObj > TWODMESHPLOTC_MAXOBJ ) {
00534         fprintf( stream,
00535                  "} def\n"
00536                  "\n/mesh%u {\n", ++( params->nMacro ) );
00537         params->nObj = 0;
00538       }
00539     }
00540 
00541     /* Plot any submeshes, if necessary. */
00542     if ( ( mesh->subMesh != NULL ) &&
00543          ( rLevel < params->plotParams->nLevels - 1 ) ) {
00544       params->level += 1;
00545       TRY( LALMakeMeshMacro( stat->statusPtr, stream, mesh->subMesh,
00546                              params ), stat );
00547       params->level -= 1;
00548     }
00549 
00550     /* Move on to next node. */
00551     mesh = mesh->next;
00552   }
00553   /* End of loop over list. */
00554   DETATCHSTATUSPTR( stat );
00555   RETURN( stat );
00556 }
00557 
00558 
00559 static void
00560 AdjustBBox( REAL4 x, REAL4 y, TwoDMeshPlotStruc *params )
00561      /* This routine expands the params->bBox field to include the
00562         point with x-y coordinates given by position. */
00563 {
00564   if ( !params->clip ||
00565        ( ( x > params->clipBox[0] ) && ( x < params->clipBox[2] ) &&
00566          ( y > params->clipBox[1] ) && ( y < params->clipBox[3] ) ) ) {
00567     REAL4 xp = x*params->xScale*params->cosTheta - 
00568       y*params->yScale*params->sinTheta;
00569     REAL4 yp = x*params->xScale*params->sinTheta +
00570       y*params->yScale*params->cosTheta;
00571     if ( params->bBox[0] > xp )
00572       params->bBox[0] = xp;
00573     if ( params->bBox[2] < xp )
00574       params->bBox[2] = xp;
00575     if ( params->bBox[1] > yp )
00576       params->bBox[1] = yp;
00577     if ( params->bBox[3] < yp )
00578       params->bBox[3] = yp;
00579   }
00580   return;
00581 }

Generated on Mon Sep 8 03:07:32 2008 for LAL by  doxygen 1.5.2