00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
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
00091 #define TWODMESHPLOTC_MAXOBJ 797
00092
00093
00094
00095 typedef struct tagMeshMacroParamStruc {
00096 UINT4 nMacro;
00097 UINT4 nObj;
00098 UINT4 level;
00099 TwoDMeshPlotStruc *plotParams;
00100 } MeshMacroParamStruc;
00101
00102
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
00114 void
00115 LALPlotTwoDMesh( LALStatus *stat,
00116 FILE *stream,
00117 TwoDMeshNode *mesh,
00118 TwoDMeshPlotStruc *params )
00119 {
00120 UINT4 i;
00121 UINT4 nObj = 0;
00122 UINT4 nMacro = 0;
00123 UINT4 nPage = 0;
00124 REAL4 bBox[4];
00125 REAL4 xOff, yOff;
00126 MeshMacroParamStruc macroParams;
00127
00128
00129 INITSTATUS( stat, "LALPlotTwoDMesh", TWODEMESHPLOTC );
00130 ATTATCHSTATUSPTR( stat );
00131
00132
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
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
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
00169
00170
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
00190
00191
00192
00193
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
00199
00200
00201
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
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
00219 if ( params->nBoundary >= 2 ) {
00220 REAL4 x, x0, dx;
00221 REAL4 *yBound;
00222 yBound = (REAL4 *)LALMalloc( 2*params->nBoundary*sizeof(REAL4) );
00223 if ( yBound == NULL ) {
00224 ABORT( stat, TWODMESHPLOTH_EMEM, TWODMESHPLOTH_MSGEMEM );
00225 }
00226
00227
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
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
00290 macroParams.nMacro = 0;
00291 macroParams.nObj = 0;
00292 macroParams.level = 0;
00293 macroParams.plotParams = params;
00294
00295
00296
00297
00298
00299 fprintf( stream, "\n/mesh%u {\n", macroParams.nMacro );
00300 TRY( LALMakeMeshMacro( stat->statusPtr, stream, mesh,
00301 ¯oParams ), stat );
00302 fprintf( stream, "} def\n" );
00303
00304
00305
00306 if ( macroParams.nObj > 0 )
00307 macroParams.nMacro++;
00308
00309
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
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
00346 fprintf( stream, "\n0 setlinewidth 0 setgray\n" );
00347
00348
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
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
00383
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
00398
00399
00400
00401
00402
00403 {
00404 UINT4 rLevel;
00405 BOOLEAN plotPoints;
00406 BOOLEAN plotEllipses;
00407 BOOLEAN plotTiles;
00408 BOOLEAN plotAny;
00409
00410
00411
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
00424 if ( ( rLevel = params->level ) >= params->plotParams->nLevels ) {
00425 DETATCHSTATUSPTR( stat );
00426 RETURN( stat );
00427 }
00428
00429
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
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];
00465 REAL4 metric[3];
00466 REAL4 axes[2];
00467 REAL4 theta;
00468 REAL4 cost, sint;
00469 REAL4 lambda;
00470 REAL4 term1, term2;
00471
00472
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
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
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
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
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
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
00551 mesh = mesh->next;
00552 }
00553
00554 DETATCHSTATUSPTR( stat );
00555 RETURN( stat );
00556 }
00557
00558
00559 static void
00560 AdjustBBox( REAL4 x, REAL4 y, TwoDMeshPlotStruc *params )
00561
00562
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 }