/* Draw two versions of the same curve, and their correspondence. */ /* Last edited on 2015-01-20 16:45:34 by stolfilocal */ /* This program draws two sampled curves (or hodographs) and draws them one on top of each other, showing the pairing implied by the associated labels. The program assumes that the samples for the two curves are stored in files "A.X" and "B.X", where "A" and "B" are arbitrary names, and "X" is a given extension (".flc" for curves, ".flv" for hodographs, etc.). The associated labels are read from files "A.lbl" and "B.lbl". */ #include #include #include #include #include #include #include #include #include #include #include TYPE Options = struct ??? { char *curveA; char *curveB; /* Input curve names (without extension). */ char *extension; /* Extension for the curve samples (".flc" usually) */ char *output; /* Output plot file (without ".ps"/".eps") */ char *label; /* Label to show at the curve's center, or "". */ /* Plotting options */ double scaleA; double scaleB; /* Scaling factor for each curve. */ unsigned drawMatchEvery; /* Plot every this many samples of the match. */ unsigned drawSegments; /* If nonzero, plots this many segments. */ /* Options for output file format and scale: */ pz_plot.DrawFmtOptions drawFmt; /* Options that request the `filter scale' icon at corner: */ pz_plot.ScaleIconOptions scaleIconOptions; /* Icon style options. */ double scaleIconLambda; /* Basic length for scale/icon */ } ???; TYPE CurveData = struct ??? { pz_r3_chain_read_data samples; pz_double_chain_read_data labels; } ???; int main(int argc, char **argv ) VAR f: PSPlot.File = NULL; { { /* with */ ??? cdA = ReadSamplesAndLabels(o.curveA, o.extension, o.scaleA); ??? cdB = ReadSamplesAndLabels(o.curveB, o.extension, o.scaleB); /* do */ pz_plot.BeginSingleDrawing(f, o.output, o.drawFmt); DrawCurves(f, cdA, cdB, o); pz_plot.EndSingleDrawing(f, o.drawFmt); }; } /* Main */ Options pz_get_options(int argc, char **argv ) VAR o: Options; { argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { /* with */ /* do */ TRY argparser_get_keyword(pp, "-curves"); o.curveA = argparser_get_next(pp); o.curveB = argparser_get_next(pp); if (( argparser_keyword_present(pp, "-extension") )){ o.extension= argparser_get_next(pp); }else{ o.extension = ".flc";; }; argparser_get_keyword(pp, "-output"); o.output = argparser_get_next(pp); o.drawFmt = pz_plot.ParseDrawFmtOptions( pp, single = TRUE, defaultWidth = 160.0e0, defaultHeight = 160.0e0 ); if (( argparser_keyword_present(pp, "-label") )){ o.label = argparser_get_next(pp) }else{ o.label = ""; }; if (( argparser_keyword_present(pp, "-scale") )){ o.scaleA = argparser_get_next_double(pp, 0.1e0, 10.0e0); o.scaleB = argparser_get_next_double(pp, 0.1e0, 10.0e0) }else{ o.scaleA = 1.0e0; o.scaleB = 1.0e0; }; if (( argparser_keyword_present(pp, "-drawMatchEvery") )){ o.drawMatchEvery = argparser_get_next_int(pp, 1) }else{ o.drawMatchEvery = 1; }; if (( argparser_keyword_present(pp, "-drawSegments") )){ o.drawSegments = argparser_get_next_int(pp, 1) }else{ o.drawSegments = 0; }; o.scaleIconOptions = pz_plot.ParseScaleIconOptions(pp); if (( argparser_keyword_present(pp, "-scaleBarStep") ) || ( argparser_keyword_present(pp, "-scaleIconLambda") )){ o.scaleIconLambda = argparser_get_next_double(pp, 0.0e0); }else{ if (( o.scaleIconOptions.style != pz_plot.ScaleIconStyle.None ) || ( o.scaleIconOptions.barCount > 0 )){ argparser_error(pp, "scale icon/bar requires \"-scaleBarStep\" or \"-scaleIconLambda\""); }; o.scaleIconLambda = 0.0e0; }; argparser_finish(pp); EXCEPT | ParseParams.Error ==> fprintf(stderr, "Usage: pz_draw_cands \\\n"); fprintf(stderr, " -curves NAMEA NAMEB [ -extension EXT ] \\\n"); fprintf(stderr, " -output NAME \\\n"); fprintf(stderr, " [ -scale SCALEA SCALEB ] \\\n"); fprintf(stderr, " [ -drawMatchEvery NSAMPLES ] \\\n"); fprintf(stderr, pz_plot.ScaleIconOptionsHelp & " \\\n"); fprintf(stderr, " [ -label STRING ] \\\n"); fprintf(stderr, " [ -scaleBarStep NUM | -scaleIconLambda NUM ] \\\n"); fprintf(stderr, pz_plot.DrawFmtOptionsHelp & " \n"); Process.Exit(1);; };; }; return o } /* GetOptions */ void DrawCurves( PSPlot.File *f, CurveData *cdA, CurveData *cdB, Options *o ) { pz_plot.Frame(f); DoDrawCurves(f, o, cdA.samples, cdA.labels, PSPlot.Blue, FALSE, cdB.samples, cdB.labels, PSPlot.Red, TRUE ); if (( o.scaleIconLambda > 0.0e0 ) || ( o.scaleIconOptions.barCount > 0 )){ pz_plot.ScaleIcon(f, lambda = o.scaleIconLambda, o = o.scaleIconOptions); }; } /* DrawCurves */ void DoDrawCurves( PSPlot.File f, Options *o, pz_r3_chain_read_data *chA, pz_double_chain_read_data *lbA, PSPlot.Color *colorA, bool_t dotsA /* Plot dots on curve A */ pz_r3_chain_read_data *chB, pz_double_chain_read_data *lbB, PSPlot.Color *colorB, bool_t dotsB, /* Plot dots on curve B */ ) /* Draws the curves proper, assuming that curve "A" has the smallest step size. */ { affirm((chA.c^.ne) == (lbA.c^.ne) ); affirm((chB.c^.ne) == (lbB.c^.ne) ); { /* with */ ??? ca = chA.c^; ??? ma = (ca.ne); ??? cb = chB.c^; ??? sa = pz_segment_t{cvx := 0, tot := ma, ini := 0, ns := ma+1, rev := FALSE}; ??? oa = pz_r3_chain_area_barycenter(ca); ??? ob = pz_r3_chain_area_barycenter(cb); ??? ctr = r3_scale(0.5e0, r3_add(oa, ob)); ??? trn = pz_geo.Translation(r3_neg(ctr)); /* "cc" is "cb" resampled at the same times as "ca": */ ??? cc = pz_r3_chain_new(ma)^; /* do */ affirm(lbB.stride == lbA.stride ); pz_r3_chain_linear_time_sample(lbB.c^, lbB.stride, cb, lbA.c^, cc); { /* with */ ??? caMapped = pz_r3_chain_map(ca, trn)^; ??? cbMapped = pz_r3_chain_map(cb, trn)^; ??? ccMapped = pz_r3_chain_map(cc, trn)^; /* do */ /* Draw the pairing lines: */ f.setLineSolid(); f.setFillColor(PSPlot.Invisible); f.setLineWidth(0.1); f.setLineColor(PSPlot.Color{0.500, 0.500, 0.500}); { /* with */ ??? match = pz_match_most_perfect(sa.ns, sa.ns)^; ??? phase = ma DIV 2; /* do */ pz_plot.Match(f, match, caMapped, ccMapped, sa, sa, drawEvery = o.drawMatchEvery, phaseA = phase, phaseB = phase ); }; /* Draw markers for some pairs of corresp. segments: */ if (( o.drawSegments > 0 )){ for (k = 0; k <= o.drawSegments-1 ; k++){ { /* with */ ??? caIni = (ma * k) DIV o.drawSegments; ??? caLim = (ma * (k+1)) DIV o.drawSegments; za = pz_segment_t{ cvx := 0, tot := ma; ini := caIni; ns := (caLim - caIni) DIV 2; rev := FALSE }; ??? zb = pz_double_chain_map_segment(za, lbA.c^, lbB.c^, lbA.stride); /* do */ f.setLineColor(colorA); pz_plot.SegmentBrackets(f, za, caMapped, width = 20.0, length = 8.0); f.setLineColor(colorB); pz_plot.SegmentBrackets(f, zb, cbMapped, width = 20.0, length = 8.0);; }; }; }; /* Draw the contour label: */ if (( NOT Text.Empty(o.label) )){ f.setTextColor(PSPlot.Black); pz_plot.SegmentLabel(f, sa, caMapped, minRelDist = 1.0e0, label = o.label);; }; /* Draw the two curves, with dots at the original samples: */ f.setLineWidth(0.1); f.setFillColor(PSPlot.Invisible); f.setLineColor(colorA); pz_plot.Curve(f, caMapped, closed = TRUE, drawEvery = 1); if (( dotsA )){ pz_plot.Dots(f, caMapped, size = 2.0, drawEvery = 1);; }; f.setLineColor(colorB); pz_plot.Curve(f, ccMapped, closed = TRUE, drawEvery = 1); if (( dotsB )){ pz_plot.Dots(f, cbMapped, size = 2.0, drawEvery = 1);; };; }; } } /* DoDrawCurves */ CurveData ReadSamplesAndLabels( char *curve, char *extension, double scale ) { { /* with */ samples = pz_r3_chain_read( OpenRead(curve & extension); header_only := FALSE, recenter := pz_ctr_NONE ); ??? labels = pz_double_chain_read(OpenRead(curve & ".lbl"), header_only := FALSE); /* do */ if (( scale != 1.0e0 )){ { /* with */ ??? c = samples.c^; /* do */ for (i = 0; i < (c.ne ) ; i++){ c[i] = r3_scale(scale, c[i]) ;}; }; }; return CurveData{ samples = samples, labels = labels }; } } /* ReadSamplesAndLabels */ FILE *OpenRead( char *name ) { fprintf(stderr, "reading %s\n", name ); return open_read(name, TRUE) } /* OpenRead */ { /* 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. */