/* Draws a set of outlines in specified poses */ /* Last edited on 2015-01-20 16:45:27 by stolfilocal */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include TYPE Options = struct ??? { /* Filename specs */ char *input; /* Name of ".pos" file (minus extension). */ char *chainDir; /* Directory where chains can be found. */ char *chainPrefix; /* Chain file name prefix */ unsigned band; /* Nominal band width for file names */ double step; /* Nominal input sampling step (pixels). */ double blurFactor; /* Corner broadening factor. */ char *extension; /* Extension for geometric chains (".flc" usually) */ char *output; /* Output plot file (without ".ps"/".eps") */ /* Plotting options */ double turn; /* Rotation (degrees) to apply to the cluster. */ double spread; /* Spread pieces by this percentage (0 = no spreading). */ double lineWidth; /* Line width for curves */ bool_t noFrame; /* TRUE omits the frame around each candidate. */ double grid; /* Coordinate grid spacing (0 = no grid). */ char *rect; /* Highlight rectangle file name */ bool_t extraDots; /* TRUE to plot dots at positions given in "dotsFile". */ char *dotsFile; /* Name of extraDots (pz_r3_chain) file, *with* ext. */ unsigned dotsPrec; /* Format prec for 3rd column of "dotsFile" (0=omit). */ double labelSize; /* Curve label size in points (0 = no labels). */ bool_t labelFrames; /* TRUE draws an oval frame around each label. */ double labelDots; /* Diameter in mm of dot at label positions (0 = none). */ double labelDX; /* Label X displacement relative to curve center. */ double labelDY; /* Label Y displacement relative to curve center. */ double plotStep; /* Resampling step for plot (0 = do not resample). */ /* Options for output file format and scale: */ pz_plot.DrawFmtOptions drawFmt; /* Candidate SET specs: */ CandSetSpecList *candSets; /* Candidate sets to draw on top of the pieces. */ /* Options that control the scale bar and/or icon at corner: */ pz_plot.ScaleIconOptions scaleIconOptions; /* Icon style options. */ double scaleIconLambda; /* Basic length for scale/icon */ } ???; CandSetSpecList == ARRAY OF CandSetSpec; CandSetSpec = struct ??? { char *name; /* Candidate file name, minus extensions. */ double minLength; /* Minimum candidate length. */ PSPlot.Color lineColor; /* Line color. */ bool_t segs; /* TRUE to highlight matched segments. */ bool_t adjs; /* TRUE to show adjacency graph edges. */ double lineWidth; /* Line width for adjacency graph edges. */ bool_t dashed; /* Whether adjacency graph edges are dashed. */ } ???; int main(int argc, char **argv ) VAR f: PSPlot.File := NIL; VAR o := pz_get_options(int argc, char **argv); { { /* with */ ??? pos = ReadPoses(o.input).pos^; ??? used = pz_pose.ChainsPlaced(pos)^; chAllData = pz_r3_chain_read_all( o.chainPrefix, o.band, o.extension, sel := used; dir := o.chainDir, header_only := FALSE, recenter := pz_ctr_AREA ); ??? chData = chAllData.chData^; ??? center = NEW(ARRAY *OF r3_t, (chData.ne))^; /* do */ pz_pose.MakeAbsolute(pos); MapAllChains(chData, pos, center, turn = o.turn, spreadFactor = o.spread); if (( o.step == 0.0e0 )){ o.step = ComputeMeanStep(chData); fprintf(stderr, "warning: \"-step\" adjusted to " & Fmt.LongReal(o.step) & "\n"); }; AdjustPlotScales(chData, o.drawFmt); pz_plot.BeginSingleDrawing(f, o.output, o.drawFmt); DrawGrid(f, o); DrawFragments(f, chData, o); DrawMarkers(f, o); DrawCandidateSets(f, chData, center, o); DrawCurveLabels(f, chData, center, o); DrawScaleIcon(f, o); pz_plot.EndSingleDrawing(f, o.drawFmt); } } /* Main */ double ComputeMeanStep( ARRAY *OF pz_r3_chain_read_data chData ) VAR sum: double = 0.0e0; n: unsigned = 0; { for (i = 0; i < (chData.ne ) ; i++){ if (( chData[i].c != NULL )){ { /* with */ ??? c = chData[i].c^, m = (c.ne); /* do */ for (k = 0; k < (c.ne ) ; k++){ sum = sum + r3_dist(c[k], c[(k+1) MOD m]); }; n = n + m; }; }; }; return sum/FLOAT(max(n, 1), double) } /* ComputeMeanStep */ void MapAllChains( VAR /*IO*/ chData: ARRAY OF pz_r3_chain_read_data; pz_pose.List *pos, ARRAY *OF r3_t center, /* (OUT) */ double turn, double spreadFactor ) CONST Degree == 0.0174532925199432e0; { for (f = 0; f < (center.ne ) ; f++){ center[f] = r3_t{0.0e0, ..} ;}; { /* with */ ??? theta = turn * Degree; ??? u = r3_t{1.0e0, 0.0e0, 0.0e0}; ??? w = r3_t{cos(theta), sin(theta), 0.0e0}; ??? r = pz_geo.Rotation(u, w); /* do */ for ( iPos = 0 TO (pos.ne - 1) ){ { /* with */ ??? chainNum = pos[iPos].cvx[0]; ??? c = chData[chainNum].c^; ??? m = LR4x4.Mul(pos[iPos].m, r); ??? bar = r3_t{m[0][1],m[0][2],0.0e0}; ??? disp = r3_scale(spreadFactor, bar); /* do */ pz_r3_chain_do_map(c, m); pz_r3_chain_do_translate(c, disp); center[chainNum] = r3_add(bar, disp);; }; };; }; } /* MapAllChains */ CONST X == PSPlot.Axis.X; Y == PSPlot.Axis.Y; void AdjustPlotScales( ARRAY *OF pz_r3_chain_read_data ch, /* Already centered, sampled, mapped. */ pz_plot.DrawFmtOptions *o ) VAR w: pz_window_t; { fprintf(stderr, "computing bounding box of cluster...\n"); /* Compute bounding box OF all mapped chains: */ w[X].end[0] = (double.ne - 1); w[X].end[1] = (-INFINITY); w[Y].end[0] = (double.ne - 1); w[Y].end[1] = (-INFINITY); for (i = 0; i < (ch.ne ) ; i++){ if (( ch[i].c != NULL )){ { /* with */ ??? b = pz_r3_chain_get_window(ch[i].c^); /* do */ w[X].end[0] = min(w[X].end[0], b[X].end[0]); w[X].end[1] = max(w[X].end[1], b[X].end[1]); w[Y].end[0] = min(w[Y].end[0], b[Y].end[0]); w[Y].end[1] = max(w[Y].end[1], b[Y].end[1]);; }; }; }; /* Ensure minimum width: */ { /* with */ ??? hX = ((o.window[X].end[1] - o.window[X].end[0]) - (w[X].end[1] - w[X].end[0]))/2.0e0; ??? hY = ((o.window[Y].end[1] - o.window[Y].end[0]) - (w[Y].end[1] - w[Y].end[0]))/2.0e0; /* do */ if (( hX > 0.0e0 )){ w[X].end[0] = w[X].end[0] - hX; w[X].end[1] = w[X].end[1] + hX ;}; if (( hY > 0.0e0 )){ w[Y].end[0] = w[Y].end[0] - hY; w[Y].end[1] = w[Y].end[1] + hY ;};; }; o.window[X] = (interval_t){w[X].end[0], w[X].end[1]}; o.window[Y] = (interval_t){w[Y].end[0], w[Y].end[1]} } /* AdjustPlotScales */ void DrawGrid( PSPlot.File f, Options *o ) { if (( o.grid > 0.0e0 )){ pz_plot.Grid(f, o.grid) ;}; } /* DrawGrid */ void DrawFragments( PSPlot.File f, ARRAY *OF pz_r3_chain_read_data chData, Options *o ) { if (( o.lineWidth > 0.0 )){ { /* with */ ??? drawEvery = pz_plot.ComputeDrawEvery(f, o.plotStep, o.step, all := FALSE); /* do */ for (i = 0; i < (chData.ne ) ; i++){ if (( chData[i].c != NULL )){ { /* with */ ??? c = chData[i].c^; /* do */ f.setLineSolid(); f.setLineWidth(o.lineWidth); f.setLineColor(PSPlot.Black); f.setFillColor(PSPlot.Invisible); pz_plot.Curve(f, c, drawEvery = drawEvery, closed = TRUE);; }; }; }; }; }; } /* DrawFragments */ void DrawMarkers( PSPlot.File f, Options *o ) { if (( o.extraDots )){ { /* with */ er = pz_r3_chain_read( open_read(o.dotsFile, TRUE); header_only := FALSE; recenter := pz_ctr_NONE ); ??? e = er.c^; /* do */ PlotDotsMarks(f, e, o.dotsPrec);; }; ; }; if (( NOT Text.Empty(o.rect) )){ { /* with */ ??? rec = ReadWindow(o.rect, 1.0e0); /* do */ f.setLineWidth(0.1); f.setLineSolid(); f.setLineColor(PSPlot.Black); f.setFillColor(PSPlot.Invisible); f.rectangle(rec[X].end[0], rec[X].end[1], rec[Y].end[0], rec[Y].end[1]); };; }; } /* DrawMarkers */ void DrawCandidateSets( PSPlot.File f, ARRAY *OF pz_r3_chain_read_data chData, ARRAY *OF r3_t center, Options *o ) { { /* with */ ??? candSet = o.candSets^; ??? candData = NEW(ARRAY *OF pz_candidate_read_data, (candSet.ne)); ??? drawEvery = pz_plot.ComputeDrawEvery(f, o.plotStep, o.step, all := FALSE); /* do */ for (i = 0; i < (candSet.ne ) ; i++){ { /* with */ ??? cs = candSet[i]; /* do */ candData[i] = ReadCandidates(cs.name, minLength = cs.end[0]Length, blurFactor = o.blurFactor, step = o.step ); }; }; for (i = 0; i < (candSet.ne ) ; i++){ DrawCandSetSegments(f, chData, candData[i].c^, candSet[i], lineWidth = 2.0 * o.lineWidth, drawEvery = drawEvery ); }; for (i = 0; i < (candSet.ne ) ; i++){ DrawCandSetAdjacencies(f, chData, center, candData[i].c^, candSet[i]); }; } } /* DrawCandidateSets */ void DrawCurveLabels( PSPlot.File f, ARRAY *OF pz_r3_chain_read_data chData, ARRAY *OF r3_t center, Options *o ) { for (i = 0; i < (center.ne ) ; i++){ if (( chData[i].c != NULL )){ { /* with */ ??? loc = center[i]; ??? label = Fmt.Int(i); /* do */ DrawCurveLabel(f, loc, label, o); }; }; }; } /* DrawCurveLabels */ void DrawScaleIcon( PSPlot.File f, Options *o ) { if (( o.scaleIconLambda > 0.0e0 ) || ( o.scaleIconOptions.barCount > 0 )){ pz_plot.ScaleIcon(f, lambda = o.scaleIconLambda, o = o.scaleIconOptions); }; } /* DrawScaleIcon */ pz_window_t ReadWindow( char *name, double expand ) VAR w: pz_window_t; { { /* with */ ??? fileName = txtcat(name , ".wnd"); /* do */ fprintf(stderr, "reading %s\n", fileName ); { /* with */ ??? rd = open_read(fileName, TRUE); /* do */ w = pz_window_read(rd); w[X].end[0] = w[X].end[0] * expand; w[X].end[1] = w[X].end[1] * expand; w[Y].end[0] = w[Y].end[0] * expand; w[Y].end[1] = w[Y].end[1] * expand; return w; }; } } /* ReadWindow */ void PlotDotsMarks( PSPlot.File f, pz_r3_chain_t *e, unsigned prec ) { { /* with */ ??? n = (e.ne); /* do */ f.setTextColor(PSPlot.Color{0.0, 0.5, 0.0}); if (( prec > 0 )){ for (i = 0; i <= n-1 ; i++){ f.label( Fmt.Pad(Fmt.LongReal(e[i][2]), prec), e[i][0],e[i][1] );; };; }; f.setLineColor(PSPlot.Black); for (i = 0; i <= n-1 ; i++){ f.dot(e[i][0],e[i][1], 3.0) ;};; }; } /* PlotDotsMarks */ void DrawCandSetSegments( PSPlot.File f, ARRAY *OF pz_r3_chain_read_data chData, pz_candidate.List *cand, CandSetSpec *cs, double lineWidth, unsigned drawEvery ) { if (( cs.segs )){ f.setLineColor(cs.lineColor); f.setFillColor(PSPlot.Invisible); f.setLineWidth(lineWidth); for ( iCand = 0 TO (cand.ne - 1) ){ { /* with */ ??? ci = cand[iCand]; ??? aseg = ci.seg[0], a = aseg.cvx; ??? bseg = ci.seg[1], b = bseg.cvx; /* do */ if (( chData[a].c != NULL )){ { /* with */ ??? ac = chData[a].c^; /* do */ affirm((ac.ne) == aseg.tot ); pz_plot.Segment(f, aseg, ac, closed = FALSE, drawEvery = drawEvery); }; }; if (( chData[b].c != NULL )){ { /* with */ ??? bc = chData[b].c^; /* do */ affirm((bc.ne) == bseg.tot ); pz_plot.Segment(f, bseg, bc, closed = FALSE, drawEvery = drawEvery); }; }; }; }; }; } /* DrawCandSetSegments */ void DrawCandSetAdjacencies( PSPlot.File f, ARRAY *OF pz_r3_chain_read_data chData, ARRAY *OF r3_t center, pz_candidate.List *cand, CandSetSpec *cs ) CONST Alpha == 1.0e0/3.0e0; { if (( cs.adjs )){ f.setLineColor(cs.lineColor); f.setFillColor(PSPlot.Invisible); f.setLineWidth(cs.lineWidth); if (( cs.dashed )){ f.setLineDashed(ARRAY OF double{1.5, 0.5}) }else{ f.setLineSolid(); }; for ( iCand = 0 TO (cand.ne - 1) ){ { /* with */ ??? ci = cand[iCand]; ??? aseg = ci.seg[0], a = aseg.cvx; ??? bseg = ci.seg[1], b = bseg.cvx; /* do */ if (( chData[a].c != NULL ) ANDAND ( chData[b].c != NULL )){ { /* with */ ??? ac = chData[a].c^, av = center[a]; ??? bc = chData[b].c^, bv = center[b]; ??? mid = CandCenter(ac, aseg, bc, bseg); ??? at = r3_mix(Alpha, av, 1.0e0 - Alpha, mid); ??? bt = r3_mix(Alpha, bv, 1.0e0 - Alpha, mid); /* do */ f.bezier(av[0], av[1], at[0], at[1], bt[0], bt[1], bv[0], bv[1]); }; }; }; }; } } /* DrawCandSetAdjacencies */ r3_t CandCenter( pz_r3_chain_t *ac, pz_segment_t *aseg, pz_r3_chain_t *bc, pz_segment_t *bseg ) { { /* with */ ??? ai = (aseg.ini + aseg.ns DIV 2) MOD aseg.tot; ??? bi = (bseg.ini + bseg.ns DIV 2) MOD bseg.tot; /* do */ return r3_mix(0.5e0, ac[ai], 0.5e0, bc[bi]); } } /* CandCenter */ pz_candidate_read_data ReadCandidates( char *name, double minLength, double blurFactor, double step ) /* Reads a candidate list, and removes entries shorter than "minLength" (minus corner blurring) on either segment. */ VAR cData: pz_candidate_read_data; { /* Hack to avoid overflow when "step" is zero. */ if (( step == 0.0e0 )){ minLength = 0.0e0; step = 1.0e0 ;}; { /* with */ ??? fileName = txtcat(name , ".can"); /* do */ fprintf(stderr, "reading %s ...\n", fileName ); cData = pz_candidate_read(open_read(fileName, TRUE)); { /* with */ ??? lambda = cData.lambda; ??? c = cData.c^; ??? minCorrLength = MAX(0.0e0, minLength - 2.0e0*blurFactor*lambda); ??? minSteps = FLOOR(minCorrLength/step); /* do */ nCands = (c.ne); pz_candidate_remove_short(c, nCands, minSteps); { int diff = nCands - c.ne; txt = " Read " & Fmt.Int((c.ne)) & " candidates.\n" & " Removed " & Fmt.Int(diff) & " candidates with less than " & Fmt.Int(minSteps) & " steps.\n" & " Left " & Fmt.Int(nCands) & " candidates."; fprintf(stderr, txt & "\n"); cData.cmt = txtcat(cData.cmt & "\n" & "pz_draw_cluster:\n" , txt); }; return cData; }; } } /* ReadCandidates */ void DrawCurveLabel( PSPlot.File f, r3_t *loc, char *label, Options *o ) { if (( NOT Text.Empty(label) )){ if (( o.labelFrames )){ DrawLabelFrame(f, loc, max(3, Text.Length(label)), o.labelSize) }else if (( o.labelDots > 0.0 )){ DrawLabelDot(f, loc, o.labelDots); }; f.setTextColor(PSPlot.Black); f.label( label, loc[0] + o.labelDX, loc[1] + o.labelDY, 0.5, 0.5, font = "Courier", size = o.labelSize ); } } /* DrawCurveLabel */ void DrawLabelFrame( PSPlot.File f, r3_t *p, unsigned nChars, double fontSize ) { /* Charbox dimensions (grid units). */ f.setLineSolid(); f.setLineColor(PSPlot.Black); f.setLineWidth(0.1); f.setFillColor(PSPlot.White); { /* with */ ??? sX = f.getScaleFactor(PSPlot.Axis.X); ??? sY = f.getScaleFactor(PSPlot.Axis.Y); ??? charX = ((double)0.070 * fontSize) / sX; /* Charbox width. */ ??? charY = ((double)0.139 * fontSize) / sY; /* Charbox height. */ ??? HX = 1.9e0 * ((double)charX) * ((double)nChars); ??? HY = 1.9e0 * ((double)charY); /* do */ /* f.rectangle(p[0] - HX, p[0] + HX, p[1] - HY, p[1] + HY) */ f.ellipse(p[0], p[1], HX, 0.0e0, 0.0e0, HY); } } /* DrawLabelFrame */ void DrawLabelDot( PSPlot.File f, r3_t *p, double dotSize ) { /* Charbox dimensions (grid units). */ f.setLineSolid(); f.setLineColor(PSPlot.Black); f.setLineWidth(dotSize); f.dot(p[0], p[1], 1.0) } /* DrawLabelDot */ pz_pose.ReadData ReadPoses( char *name ) { { /* with */ ??? fileName = txtcat(name , ".pos"); /* do */ fprintf(stderr, "reading %s\n", fileName ); { /* with */ ??? rd = open_read(fileName, TRUE); /* do */ return pz_pose.Read(rd); }; } } /* ReadPoses */ 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, "-input"); o.input = argparser_get_next(pp); if (( argparser_keyword_present(pp, "-chainDir") )){ o.chainDir = argparser_get_next(pp) }else{ o.chainDir = "."; }; argparser_get_keyword(pp, "-chainPrefix"); o.chainPrefix = argparser_get_next(pp); argparser_get_keyword(pp, "-band"); o.band = argparser_get_next_int(pp); argparser_get_keyword(pp, "-step"); o.step = argparser_get_next_double(pp, 0.0e0, 1024.0e0); argparser_get_keyword(pp, "-blurFactor"); o.blurFactor = argparser_get_next_double(pp, 0.01e0, 100.0e0); 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); if (( argparser_keyword_present(pp, "-turn") )){ o.turn = argparser_get_next_double(pp, 0.0e0) }else{ o.turn = 0.0e0; }; if (( argparser_keyword_present(pp, "-spread") )){ o.spread = argparser_get_next_double(pp); }else{ o.spread = 0.0e0; }; if (( argparser_keyword_present(pp, "-lineWidth") )){ o.lineWidth = pp.getNextReal(0.0) }else{ o.lineWidth = 0.15; }; o.noFrame = argparser_keyword_present(pp, "-noFrame"); if (( argparser_keyword_present(pp, "-grid") )){ o.grid = argparser_get_next_double(pp, 1.0e-10, 1.0e+10) }else{ o.grid = 0.0e0; }; if (( argparser_keyword_present(pp, "-rect") )){ o.rect = argparser_get_next(pp) }else{ o.rect = ""; }; o.extraDots = argparser_keyword_present(pp, "-extraDots"); if (( o.extraDots )){ o.dotsFile = argparser_get_next(pp); if (( argparser_keyword_present(pp, "-prec") )){ o.dotsPrec = argparser_get_next_int(pp, 0,16); }else{ o.dotsPrec= 0;; };; }; if (( argparser_keyword_present(pp, "-labelSize") )){ o.labelSize = pp.getNextReal(0.0, 100.0) }else{ o.labelSize = 12.0; }; if (( argparser_keyword_present(pp, "-labelFrames") )){ o.labelFrames = TRUE; o.labelDots = 0.0 }else if (( argparser_keyword_present(pp, "-labelDots") )){ o.labelFrames = FALSE; o.labelDots = pp.getNextReal(0.0) }else{ o.labelFrames = FALSE; o.labelDots = 0.0; }; if (( argparser_keyword_present(pp, "-labelShift") )){ o.labelDX = argparser_get_next_double(pp); o.labelDY = argparser_get_next_double(pp); }else{ o.labelDX = 0.0e0; o.labelDY = 0.0e0;; }; o.drawFmt = pz_plot.ParseDrawFmtOptions( pp, single = FALSE, defaultWidth = 80.0e0, defaultHeight = 80.0e0 ); if (( argparser_keyword_present(pp, "-plotStep") )){ o.plotStep = pp.getNextReal(0.0); }else{ o.plotStep = 0.0;; }; o.candSets = ParseCandSetOptions(pp); 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_cluster \\\n"); fprintf(stderr, " -input NAME \\\n"); fprintf(stderr, " [ -chainDir DIR ] -chainPrefix NAME \\\n"); fprintf(stderr, " -band NUMBER [ -extension EXT ] -step NUM \\\n"); fprintf(stderr, " -blurFactor NUM \\\n"); fprintf(stderr, " -output NAME \\\n"); fprintf(stderr, " [ -turn DEGREES ] [ -spread FRACTION ] \\\n"); fprintf(stderr, " [ -noFrame ] [ -grid SPACING ] \\\n"); fprintf(stderr, " [ -rect WINNAME ] \\\n"); fprintf(stderr, " [ -extraDots FILE [ -dotsPrec NUM ] ] \\\n"); fprintf(stderr, " [ -labelSize POINTS ] [ -labelShift DX DY ] \\\n"); fprintf(stderr, " [ -labelFrames | -labelDots ] \\\n"); fprintf(stderr, " [ -plotStep NUMBER ] \\\n"); fprintf(stderr, " [ -candSet NAME \\\n"); fprintf(stderr, " [ minLength PIXELS ] \\\n"); fprintf(stderr, " [ segs | adjs | both ] \\\n"); fprintf(stderr, " [ lineWidth LINEWD ] [ color R G B ] [ dashed ] \\\n"); fprintf(stderr, " ]... \\\n"); fprintf(stderr, pz_plot.ScaleIconOptionsHelp & " \\\n"); fprintf(stderr, " [ -scaleBarStep NUM | -scaleIconLambda NUM ] \\\n"); fprintf(stderr, pz_plot.DrawFmtOptionsHelp & " \n"); Process.Exit(1);; };; }; return o } /* GetOptions */ CandSetSpecList *ParseCandSetOptions( arparser_t pp ) RAISES {ParseParams.Error} = VAR candSets = NEW(REF CandSetSpecList, 2); nCandSets: unsigned = 0; { while ( argparser_keyword_present(pp, "-candSet") ){ VAR spec: CandSetSpec; { spec.name = argparser_get_next(pp); if (( argparser_keyword_present_next(pp, "minLength") )){ spec.end[0]Length = argparser_get_next_double(pp, 0.0e0) }else{ spec.end[0]Length = 0.0e0; }; if (( argparser_keyword_present_next(pp, "adjs") )){ spec.adjs = TRUE; spec.segs = FALSE }else if (( argparser_keyword_present_next(pp, "segs") )){ spec.adjs = FALSE; spec.segs = TRUE }else if (( argparser_keyword_present_next(pp, "both") )){ spec.adjs = TRUE; spec.segs = TRUE; }; if (( argparser_keyword_present_next(pp, "lineWidth") )){ spec.lineWidth = pp.getNextReal(0.0) }else{ spec.lineWidth = 0.20; }; if (( argparser_keyword_present_next(pp, "color") )){ spec.lineColor = PSPlot.Color{ pp.getNextReal(0.0, 1.0), pp.getNextReal(0.0, 1.0), pp.getNextReal(0.0, 1.0) } }else{ spec.lineColor = PSPlot.Black;; }; spec.dashed = argparser_keyword_present_next(pp, "dashed"); if (( nCandSets >= (candSets^.ne) )){ { /* with */ ??? newCandSets = NEW(REF CandSetSpecList, 2*nCandSets + 2); /* do */ SUBARRAY(newCandSets^, 0, nCandSets) = candSets^; candSets = newCandSets; }; }; candSets[nCandSets] = spec; nCandSets++; }; }; if (( nCandSets < (candSets^.ne) )){ { /* with */ ??? trimCandSets = NEW(REF CandSetSpecList, nCandSets); /* do */ trimCandSets^ = SUBARRAY(candSets^, 0, nCandSets); candSets = trimCandSets; }; }; return candSets } /* ParseCandSetOptions */ { /* 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. */