/* Refines a list of candidate pairings, using DP on geometric chains. */ /* Last edited on 2015-01-20 16:47:36 by stolfilocal */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include TYPE MismatchOptions == pz_mismatch.Options; Options = struct ??? { char *input; /* Input candidate file name. */ char *chainDir; /* Directory where to find chain files. */ char *chainPrefix; /* Invariant chain file name prefix. */ char *extension; /* Extension of chain files, usually ".flc" */ unsigned band; /* Nominal band width (lambda) for file names. */ double step; /* Sampling step. */ unsigned maxInputCands; /* For debugging: truncate input at this count. */ /* Pairing parameters: */ MismatchOptions mp; /* Mismatch formula parameters. */ double minLength; /* Minimum length of pairing segments. */ double blurFactor; /* Corner broadening factor. */ double extraLength; /* Extra length to add at each candidate end. */ double maxRefineShift; /* Max align. shift during refinement. */ bool_t simpleMatch; /* TRUE uses "FindBest" match instead of "Refine". */ /* Sort/prune parameters: */ unsigned maxChainCands; /* Max candidates per chain. */ unsigned maxPairCands; /* Max candidates per chain pair. */ /* Placement/optimization parameters: */ bool_t perturbMatrix; /* TRUE to perturb placement matrix */ unsigned maxEvals; /* Max trials in evaluation (0 = dont' optimize). */ bool_t plotFunction; /* TRUE to plot the goal function. */ /* Plot parameters: */ bool_t draw; /* TRUE to draw the the initial and final placements */ unsigned drawEvery; /* Plot one every this many samples. */ double grid; /* Coordinate grid spacing (0 = no grid). */ bool_t noColors; /* TRUE uses only black, FALSE uses red/blue for segs. */ double displace; /* Separate curves by this amount when plotting */ bool_t epsFormat; /* TRUE: eps format, FALSE: plain ps format */ double plotWidth; /* Plot area width in mm. */ double plotHeight; /* Plot area height in mm. */ /* Parameters that control the output: */ char *output; /* Output file name (without extensions) */ } ???; TYPE ChainData == pz_r3_chain_read_data; int main(int argc, char **argv ) { { /* with */ ??? o = pz_get_options(int argc, char **argv); ??? candData = pz_candidate_read(open_read(o.input & ".can", TRUE)); ??? oldCand = SUBARRAY(candData.c^, 0, MIN(o.maxInputCands, (candData.c^.ne))); ??? lambda = candData.lambda; ??? chainUsed = pz_candidate_chains_used(oldCand)^; chAllData = pz_r3_chain_read_all( o.chainPrefix, o.band, o.extension, sel := chainUsed; dir := o.chainDir, header_only := FALSE, recenter := pz_ctr_NONE ); ??? newCand = RefineCandidates(oldCand, chAllData.chData^, o, lambda)^; ??? runCmt = RunComments(o); /* do */ { /* with */ ??? wr = open_write(o.output & ".can", TRUE); /* do */ pz_candidate_write(wr, candData.cmt & "\n" & runCmt, newCand, lambda);; };; }; } /* 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, "-input"); o.input = argparser_get_next(pp); if (( argparser_keyword_present(pp, "-maxInputCands") )){ o.maxInputCands = argparser_get_next_int(pp, 1) }else{ o.maxInputCands = (unsigned.ne - 1); }; 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); 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.plotFunction = argparser_keyword_present(pp, "-plotFunction"); o.simpleMatch = argparser_keyword_present(pp, "-simpleMatch"); argparser_get_keyword(pp, "-minLength"); o.minLength = argparser_get_next_double(pp); argparser_get_keyword(pp, "-blurFactor"); o.blurFactor = argparser_get_next_double(pp, 0.0e0, 5.0e0); argparser_get_keyword(pp, "-extraLength"); o.extraLength = argparser_get_next_double(pp, 0.0e0); argparser_get_keyword(pp, "-maxRefineShift"); o.maxRefineShift = argparser_get_next_double(pp); o.mp = pz_mismatch.ParseOptions(pp); if (( argparser_keyword_present(pp, "-maxChainCands") )){ o.maxChainCands = argparser_get_next_int(pp, 1) }else{ o.maxChainCands = (unsigned.ne - 1); }; if (( argparser_keyword_present(pp, "-maxPairCands") )){ o.maxPairCands = argparser_get_next_int(pp, 1, o.maxChainCands) }else{ o.maxPairCands = (unsigned.ne - 1); }; o.perturbMatrix = argparser_keyword_present(pp, "-perturbMatrix"); if (( argparser_keyword_present(pp, "-dontOptimize") )){ o.maxEvals = 0 }else{ argparser_get_keyword(pp, "-maxEvals"); o.maxEvals = argparser_get_next_int(pp);; }; o.draw = argparser_keyword_present(pp, "-draw"); if (( argparser_keyword_present(pp, "-displace") )){ o.displace = argparser_get_next_double(pp); }else{ o.displace = 0.0e0;; }; 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, "-drawEvery") )){ o.drawEvery = argparser_get_next_int(pp, 1, (unsigned.ne - 1)) }else{ o.drawEvery = 1; }; o.noColors = argparser_keyword_present(pp, "-noColors"); o.epsFormat = argparser_keyword_present(pp, "-epsFormat"); if (( o.epsFormat )){ if (( argparser_keyword_present(pp, "-plotSize") )){ o.plotWidth = argparser_get_next_double(pp, 10.0e0, 1000.0e0); o.plotHeight = argparser_get_next_double(pp, 10.0e0, 1000.0e0); }else{ o.plotWidth = 150.0e0; o.plotHeight = 50.0e0;; }; }else{ o.plotWidth = 150.0e0; o.plotHeight = 150.0e0;; }; argparser_finish(pp); EXCEPT | ParseParams.Error ==> fprintf(stderr, "Usage: PZPZRefineCandsGeoII \\\n"); fprintf(stderr, " -input NAME [ -maxInputCands NUMBER ] \\\n"); fprintf(stderr, " [ -chainDir DIR ] -chainPrefix NAME \\\n"); fprintf(stderr, " -band BAND -step NUMBER \\\n"); fprintf(stderr, " [ -extension EXT ] \\\n"); fprintf(stderr, " -output NAME \\\n"); fprintf(stderr, " [ -plotFunction ] \\\n"); fprintf(stderr, " [ -simpleMatch ] \\\n"); fprintf(stderr, " -maxRefineShift NUM \\\n"); fprintf(stderr, " %s \\\n", pz_mismatch.OptionsHelp ); fprintf(stderr, " -minLength NUM \\\n"); fprintf(stderr, " -blurFactor NUM -extraLength NUM \\\n"); fprintf(stderr, " [ -maxChainCands NUMBER ] \\\n"); fprintf(stderr, " [ -maxPairCands NUMBER ] \\\n"); fprintf(stderr, " [ -perturbMatrix ] \\\n"); fprintf(stderr, " { -dontOptimize | -maxEvals NUM } \\\n"); fprintf(stderr, " [ -draw \\\n"); fprintf(stderr, " [ -epsFormat [ -plotSize WIDTH HEIGHT ] ] \\\n"); fprintf(stderr, " [ -drawEvery NUM ] [ -grid SPACING ] \\\n"); fprintf(stderr, " [ -displace NUM ] [ -noColors ] \\\n"); fprintf(stderr, " ] \n"); Process.Exit(1);; };; }; return o; } GetOptions; pz_candidate.List *RefineCandidates( pz_candidate.List *cand, ARRAY *OF ChainData ch, Options *o, double lambda ) VAR c: REF pz_candidate.List; /* Refined candidates. */ n: unsigned = 0; /* Refined candidate count. */ minAvgDist: REF double_vec_t = NULL; rCost: REF pz_match_cost_matrix_t = NULL; plotName: char *; { { /* with */ ??? nCands = (cand.ne); ??? nChains = (ch.ne); ??? length = double_vec_new(nChains)^; /* do */ for (k = 0; k <= nChains-1 ; k++){ if (( ch[k].c != NULL )){ length[k] = ChainLength(ch[k].c^) ;}; }; fprintf(stderr, "candidates before refine loop == %s\n", Fmt.Int(nCands) ); c = NEW(REF pz_candidate.List, nCands); for (i = 0; i <= nCands-1 ; i++){ { /* with */ ??? candTag = Fmt.Pad(Fmt.Int(i), 6, '0'); /* do */ fprintf(stderr, "===== candidate %s ====================================\n", candTag ); if (( i == 0 ) ANDAND ( o.plotFunction )){ plotName = o.output & "-" & candTag & "-fn" }else{ plotName = ""; }; c[n] = RefineOneCandidate( cand[i], ch, o, lambda, plotName = plotName, drawName = o.output & "-" & candTag & "-dr", candCmt = CandComments(i, cand[i], o.step), /*WORK*/ minAvgDist = minAvgDist, rCost = rCost ); if (( (i MOD 80 == 0) )){ fprintf(stderr, "\n") ;}; if (( c[n].mismatch <= 0.0e0 )){ fprintf(stderr, "+"); n++ }else{ fprintf(stderr, "-");; };; };; }; fprintf(stderr, "\n"); fprintf(stderr, "candidates before pruning == %s\n", Fmt.Int(n) ); pz_candidate_sort(SUBARRAY(c^, 0, n), pz_candidate_pair_mismatch_better); pz_candidate_prune_cands_per_pair(c^, n, o.maxPairCands); fprintf(stderr, "candidates after pair pruning == %s\n", Fmt.Int(n) ); pz_candidate_sort(SUBARRAY(c^, 0, n), pz_candidate_mismatch_better); pz_candidate_prune_cands_per_chain(c^, n, o.maxChainCands); fprintf(stderr, "candidates after chain pruning == %s\n", Fmt.Int(n) ); { /* with */ ??? ct = NEW(REF pz_candidate.List, n); /* do */ ct^ = SUBARRAY(c^,0,n); return ct; };; } } /* RefineCandidates */ double ChainLength( pz_r3_chain_t *c ) VAR s: double := 0.0e0; VAR j := (c.ne - 1); { for (i = 0; i < (c.ne ) ; i++){ s = s + r3_dist(c[i], c[j]); j = i; }; return s } /* ChainLength */ pz_candidate_t RefineOneCandidate( pz_candidate_t *cOld, ARRAY *OF ChainData ch, Options *o, double lambda, char *plotName, char *drawName, char *candCmt, /* (WORK) */ REF *double_vec_t minAvgDist, REF *pz_match_cost_matrix_t rCost ) VAR cNew pz_candidate_t; ok: bool_t = FALSE; mt: REF pz_match_t; mismatch: double; candLength: double; matchedLength: double; mat: r4x4_t; aMap: REF pz_r3_chain_t; { { /* with */ ??? cvxa = cOld.seg[0].cvx; ??? ca = ch[cvxa].c^; ??? cvxb = cOld.seg[1].cvx; ??? cb = ch[cvxb].c^; /* do */ affirm((ca.ne) == cOld.seg[0].tot ); affirm((cb.ne) == cOld.seg[1].tot ); /* Apply initial expansion to candidate: */ VAR extra: i2_t; { { /* with */ /* Compute the expansion needed, in samples: */ FOR j := 0 TO 1; /* do */ extra[j] = CEILING(o.extraLength / o.step); }; cNew = pz_candidate_expand(cOld, extra, extra);; }; /* Repeatedly compute the best rotation matrix and trim ends: */ while ( NOT ok ) ANDAND ( nEvals < o.maxEvals ){ { /* with */ ??? caNew = pz_r3_chain_extract-segment(ca, cNew.seg[0])^; ??? cbNew = pz_r3_chain_extract-segment(cb, cExp.seg[1])^; /* do */ ok = TRUE; pz_candidate_print(stderr, cNew); ComputeMatrix( /*IO*/ a = caNew, b = cbNew, /*IN*/ o = o, step = o.step, plotName = plotName, drawName = drawName, candCmt = candCmt, /*OUT*/ mt = mt, mismatch = mismatch, length = candLength, matchedLength = matchedLength, /*WORK*/ minAvgDist = minAvgDist, rCost = rCost ); nEvals++; cNew = TrimCandidateEnds(cNew, mt^, candChanged); if (( candChanged )){ ok = FALSE ;};; }; fprintf(stderr, "\n"); }; { /* with */ cOut = pz_candidate_cutAndPack( cNew, mt^; mismatch := mismatch; length := candLength; matchedLength := matchedLength ); /* do */ pz_candidate_print(stderr, cNew); return cNew; }; } } /* RefineOneCandidate */ void ComputeMatrix( /*IO*/ pz_r3_chain_t *a, pz_r3_chain_t *b, /* Curve segments to match. */ /* (IN) */ Options *o, double step, /* Mean sampling step. */ char *drawName, /* File name prefix for drawings. */ char *plotName, /* File name prefix for goal function plots. */ char *candCmt, /* Candidate description for plot caption. */ /* (OUT) */ REF *pz_match_t mt, double *mismatch, double *length, double *matchedLength, /* (WORK) */ REF *double_vec_t minAvgDist, pz_match_cost_matrix_t *rCost ) VAR f, f1: Value; nEvals: unsigned; mat: r4x4_t; { { /* with */ ??? ma = (a.ne); ??? mb = (b.ne); /* do */ void DrawCand( char *tag ) { if (( o.draw )){ DrawPlacement(drawName & "-" & tag, o, candCmt, aMap^, b, mt^, nEvals, mismatch = mismatch, length = length, matchedLength = matchedLength ); }; } /* DrawCand */ { /* Compute an initial guess for the placement matrix: */ mat = ComputeInitialMatrix(a, b, o); ComputeOptimumPairing(mat); DrawCand(); /* Plot initial placement and pairing: */ while ( NOT ok ) ANDAND ( nEvals < o.maxEvals ){ ok = TRUE; ComputeForceAndTorque(...); if (( force ) ANDAND ( torque small enough )){ TrimEnds(cand, ..., which, changed); if (( changed )){ ok = FALSE }else{ { /* with */ ??? t = ComputeAdjustmentMatrix(...); /* do */ mat = LR4x4.Mul(mat, t); }; ok = FALSE; }; ComputePairing(...);; }; /* Plot optimum placement and pairing: */ if (( o.draw )){ DrawPlacement(drawName & "-f", o, candCmt, aMap^, b, mt^, nEvals, mismatch = mismatch, length = length, matchedLength = matchedLength ); };; }; } } /* ComputeMatrix */ double AdjustChains( pz_match_t *mt ) /* Applies a rigid motion to chain "a" so as to minimize the strain energy of the "(a[i],b[j])" sample pairs, as specified in the current pairing. Returns the maximum amount that a sample moved. */ VAR dt: double = 0.0e0; /* Disp. momentum around Z axis. */ ctra, ctrb: r3_t = r3_t{0.0e0, ..}; /* Chain barycenters. */ C, S: double = 0.0e0; nPairs: unsigned = (mt.ne); { if (( (mt.ne) == 0 )){ return 0.0e0 ;}; /* Reduce the pairing to a one-to-one correspondence: */ ReducePairing(mt, nPairs); /* Compute barycenters of "a" and "b": */ for (k = 0; k <= nPairs-1 ; k++){ { /* with */ ??? pa = a[mt[k][0]], pb = b[mt[k][1]]; /* do */ ctra = r3_add(ctra, pa); ctrb = r3_add(ctrb, pb); }; }; { /* with */ ??? s = 1.0e0/((double)2*nPairs); /* do */ ctra = r3_scale(s, ctra); ctrb = r3_scale(s, ctrb); }; /* Displace "a" and "b" so that their centers are at the origin: */ for (ia = 1; ia < (a.ne ) ; ia++){ a[ia] = r3_sub(a[ia], ctra) ;}; for (ib = 1; ib < (b.ne ) ; ib++){ b[ib] = r3_sub(b[ib], ctrb) ;}; /* Now compute the rotation of "a" that minimizes the squared discrepancy: */ for (k = 0; k <= nPairs-1 ; k++){ { /* with */ ??? pa = a[mt[k][0]], pb = b[mt[k][1]]; /* do */ C = C + (pa[0]*pb[0] + pa[1]*pb[1]); S = S + (pa[0]*pb[1] - pa[1]*pb[0]); }; }; { /* with */ ??? R = MAX(sqrt(C*C + S*S), 1.0e-20); ??? c = C/R, s = S/R; /* do */ for (ia = 1; ia < (a.ne ) ; ia++){ { /* with */ ??? xa = a[ia][0], ya = a[ia][1]; ??? xr = xa*c - ya*s, yr = xa*s + ya*c; /* do */ xa = xr; ya = yr; };; }; ia = mt[0][0]; ib = mt[0][1]; for (k = 1; k < (mt.ne ) ; k++){ { /* with */ ??? a = mt[k][0]; ??? jb = mt[k][1]; ??? w = FLOAT((ja - ia) + (jb - ib), double); ??? stepLength = FLOAT((ja - ia) + (jb - ib), double)/totLength; ??? pa = r3_mix(0.5e0, a[ia], 0.5e0, a[ja]); ??? pb = r3_mix(0.5e0, b[ib], 0.5e0, b[jb]); /* do */ ctra = r3_add(ctra, r3_scale(stepLength, pa)); ctrb = r3_add(ctrb, r3_scale(stepLength, pb)); }; }; { /* with */ ??? s = 1.0e0/FLOAT(((a.ne)-1) + ((b.ne)-1), double); /* do */ ctra = r3_scale(s, ctra); ctrb = r3_scale(s, ctrb); }; } /* AdjustChains */ ; } ComputeForceAndTorque r4x4_t ComputeInitialMatrix( pz_r3_chain_t *a, pz_r3_chain_t *b, Options *o ) VAR mat: r4x4_t; { mat = pz_r3_chain_alignment_matrix(a, b, pz_ctr_SMPS, 0.20); if (( o.perturbMatrix )){ mat = PerturbMatrix (mat, dTheta = 0.1e0, dX = 1.0e0, dY = 1.0e0); }; return mat } /* ComputeInitialMatrix */ r4x4_t PerturbMatrix( r4x4_t *mat, double dTheta, double dX, double dY ) VAR n: r4x4_t := LR4x4.Identity(); { { /* with */ ??? cos = Math.cos(dTheta); ??? sin = Math.sin(dTheta); /* do */ affirm(cos != 0.0e0 ) || ( sin != 0.0e0 ); n[1,1] = cos; n[1,2] = sin; n[2,1] = -sin; n[2,2] = cos; n[0,1] = dX; n[0,2] = dY;; }; return LR4x4.Mul(mat, n) } /* PerturbMatrix */ void ComputeMatch( pz_r3_chain_t *a, pz_r3_chain_t *b, Options *o, unsigned minChainEdges, double step, /* (OUT) */ REF *pz_match_t mt, double *mismatch, double *length, double *matchedLength, /* (WORK) */ REF *double_vec_t minAvgDist, pz_match_cost_matrix_t *rCost ) VAR avgDist: double; { { /* with */ ??? NA = (a.ne); ??? NB = (b.ne); ??? ctr = PickCenter(a, b); ??? mtOld = pz_match_t{ctr}; /* do */ if (( minChainEdges < (NA)+(NB-1) )){ if (( o.simpleMatch )){ pz_r3_chain_match_find_best( a, b, maxDistSqr = o.mp.maxDistSqr, removeUnmatchedEnds = TRUE, /*OUT*/ mt = mt, avgDist = avgDist, length = length, matchedLength = matchedLength, /*WORK*/ rCost = rCost ); mismatch = (avgDist*avgDist - o.mp.critDistSqr)*length }else{ if (( minAvgDist == NULL ) || ( (minAvgDist^.ne) < NA + NB - 1 )){ minAvgDist = NEW(REF double_vec_t, NA + NB - 1); }; pz_r3_chain_match_refine( a, b, step = step, mtOld = mtOld, maxAdjust = CEILING(o.maxRefineShift / o.step), critDistSqr = o.mp.critDistSqr, maxDistSqr = o.mp.maxDistSqr, /*OUT*/ mt = mt, mismatch = mismatch, length = length, matchedLength = matchedLength, /*WORK*/ minAvgDist = SUBARRAY(minAvgDist^, 0, NA+NB-1), rCost = rCost );; }; /* If the pairing has zero length, provide a useful "mismatch": */ if (( mt == NULL ) || ( (mt^.ne) < 2 ) || ( length <= 0.0e0 )){ affirm(mismatch == 0.0e0 ); { /* with */ ??? ac = (NA-1) DIV 2; ??? bc = IndexNearestPoint(b, a[ac]); /* do */ mismatch = r3_dist_sqr(a[ac], b[bc]);; }; } }else{ mismatch = (double.ne - 1); length = 0.0e0; matchedLength = 0.0e0; mt = pz_match_new(1); mt[0] = ctr; }; }; } /* ComputeMatch */ pz_match_pair PickCenter( pz_r3_chain_t *a, pz_r3_chain_t *b ) { { /* with */ ??? ai = IndexNearestPoint(a, b[0]); ??? af = IndexNearestPoint(a, b[(b.ne - 1)]); ??? bi = IndexNearestPoint(b, a[0]); ??? bf = IndexNearestPoint(b, a[(a.ne - 1)]); /* do */ return pz_match_pair{(ai + af) DIV 2, (bi + bf) DIV 2}; } } /* PickCenter */ unsigned IndexNearestPoint( pz_r3_chain_t *b, r3_t p ) VAR index: unsigned; mindist: double; { { /* with */ ??? m = (b.ne); ??? mHalf = (m-1) DIV 2; /* do */ index = 0; mindist = Dist(b[0],p); for (i = mHalf; i <= 1 BY -1 ; i++){ { /* with */ ??? d = Dist(b[i],p); /* do */ if (( d < mindist )){ index = i; mindist = d ;};; }; }; for (i = mHalf+1; i <= m-1 ; i++){ { /* with */ ??? d = Dist(b[i],p); /* do */ if (( d < mindist )){ index = i; mindist = d ;};; }; };; }; return index } /* IndexNearestPoint */ void DrawPlacement( char *fileName /* File name without extension. */ Options *o, char *candCmt, /* Candidate description for caption. */ pz_r3_chain_t *a, pz_r3_chain_t *b, /* Partial contours, reversed and mapped. */ pz_match_t *mt, /* The match, relative to "a" and "b". */ unsigned nEvals, /* Goal function evaluations done. */ double mismatch, /* Mismatch of "mt". */ double length, /* Total length of "a" and "b" */ double matchedLength, /* Length actually matched. */ ) { { /* with */ ??? ma = (a.ne); ??? mb = (b.ne); ??? w = r3_t{-1.0e0, 0.0e0, 0.0e0}; ??? p = a[0]; ??? q = a[(a.ne - 1)]; ??? u = pz_geo.SegDir(p, q); ??? mat = pz_geo.Rotation(u, w); cand = pz_candidate_t{ seg := pz_segment_pair{ pz_segment_t{cvx := 0, tot := ma, ini := 0, ns := ma, rev := FALSE}; pz_segment_t{cvx := 0, tot := mb, ini := 0, ns := mb, rev := FALSE} }; mismatch := mismatch; length := length; matchedLength := matchedLength; pm := pz_match_pack(mt) }; ??? fd = o.displace/2.0e0; ??? am = DisplaceChain(pz_r3_chain_map(a, mat)^, r3_t{0.0e0, +fd, 0.0e0})^; ??? bm = DisplaceChain(pz_r3_chain_map(b, mat)^, r3_t{0.0e0, -fd, 0.0e0})^; caption = candCmt & MatchComments( nEvals, mat, mt, mismatch, length, matchedLength ); /* do */ pz_full_plot.Candidate( fileName, cand, c0 = am, c1 = bm, whole = FALSE, closed = FALSE, colors = NOT o.noColors, thicker = TRUE, dots = (o.drawEvery <= 1), pointers = FALSE, labelSize = 0.0, axes = FALSE, grid = o.grid, epsFormat = o.epsFormat, caption = caption, drawEvery = o.drawEvery, drawMatchEvery = 1, XSize = o.plotWidth, YSize = o.plotHeight );; }; fprintf( stderr, "."); } /* DrawPlacement */ pz_r3_chain_t *DisplaceChain( pz_r3_chain_t *a, r3_t *d ) { { /* with */ ??? r = NEW(REF pz_r3_chain_t, (a.ne)), ad = r^; /* do */ for (i = 0; i < (a.ne ) ; i++){ ad[i] = r3_add(a[i], d) ;}; return r; } } /* DisplaceChain */ char *CandComments( unsigned iCand, pz_candidate_t *cand, double step ) { return "Candidate " & Fmt.Pad(Fmt.Int(iCand), 6, '0') & " step == " & Fmt.LongReal(step, prec = 6) & "\n" & SegmentComments(cand.seg[0]) & SegmentComments(cand.seg[1]) } /* CandComments */ <* UNUSED ); char *FI( int x, unsigned w ) { return Fmt.Pad(Fmt.Int(x), w, '0') } /* FI */ char *SegmentComments( pz_segment_t *s ) { { /* with */ ??? wr = NEW(TextFILE *).init(); /* do */ fprintf( wr, " chain " & Fmt.Pad(Fmt.Int(s.cvx), 4, '0')); fprintf(wr, " (total %s samples)", Fmt.Pad(Fmt.Int(s.tot), 5) ); fprintf(wr, " %s samples", Fmt.Pad(Fmt.Int(s.ns), 5) ); fprintf( wr, " from sample " & Fmt.Pad(Fmt.Int(s.ini), 5)); if (( s.rev )){ fprintf( wr, " (reversed)") ;}; fprintf( wr, "\n"); return TextFILE *oText(wr); } } /* SegmentComments */ char *MatchComments( unsigned nEvals, r4x4_t *mat, pz_match_t *mt, double mismatch, double length, double matchedLength ) { { /* with */ ??? wr = NEW(TextFILE *).init(); ??? nm = (mt.ne); /* do */ fprintf(wr, " matched "); fprintf(wr, FmtMatchedRange(mt[0][0], mt[nm-1][0])); fprintf(wr, " to "); fprintf(wr, FmtMatchedRange(mt[0][1], mt[nm-1][1])); fprintf(wr, " nEvals == %s\n", Fmt.Int(nEvals) ); fprintf(wr, " (cos,sin) == %s\n", PairToText(mat[1,1], mat[1,2]) ); fprintf(wr, " (dX,dY) == %s\n", PairToText(mat[0,1], mat[0,2]) ); fprintf(wr, " mismatch == " & Fmt.LongReal(mismatch, prec = 6)); fprintf(wr, " length == " & Fmt.LongReal(length, prec = 6)); fprintf(wr, " matchedLength == %s\n", Fmt.LongReal(matchedLength, prec = 6) ); return TextFILE *oText(wr); } } /* MatchComments */ char *RunComments( Options *o ) { { /* with */ ??? wr = NEW(TextFILE *).init(); /* do */ fprintf(wr, " input == %s\n", o.input ); fprintf(wr, " maxInputCands == %s\n", Fmt.Int(o.maxInputCands) ); fprintf(wr, " chainDir == " & o.chainDir); fprintf(wr, " chainPrefix == " & o.chainPrefix); fprintf(wr, " band == %s\n", Fmt.Int(o.band) ); fprintf(wr, " output == %s\n", o.output ); fprintf(wr, " maxRefineShift == %s\n", Fmt.LongReal(o.maxRefineShift, prec = 6) ); fprintf(wr, " maxDist == %s\n", Fmt.LongReal(sqrt(o.mp.maxDistSqr), prec = 6) ); fprintf(wr, " critDist == " & Fmt.LongReal(sqrt(o.mp.critDistSqr), prec = 6)); fprintf(wr, " minLength == %s\n", Fmt.LongReal(o.minLength, prec = 6) ); fprintf(wr, " blurFactor == " & Fmt.LongReal(o.blurFactor, prec = 6)); fprintf(wr, " extraLength == %s\n", Fmt.LongReal(o.extraLength, prec = 6) ); return TextFILE *oText(wr); } } /* RunComments */ char *FmtMatchedRange( unsigned iniMatch, unsigned finMatch ) { { /* with */ ??? wr = NEW(TextFILE *).init(); /* do */ fprintf(wr, " [" & Fmt.Int(iniMatch)); fprintf(wr, "..%s]", Fmt.Int(finMatch) ); return TextFILE *oText(wr); } } /* FmtMatchedRange */ char *PairToText( double x, double y ) { return "(" & Fmt.LongReal(x, prec = 6) & ", " & Fmt.LongReal(y, prec = 6) & ")" } /* PairToText */ { /* 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. */