@@ -104,12 +104,13 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int
104104 return (status) ? vmid[0 ] + crossResult.Value () * vdir[0 ] : 0 ;
105105 };
106106
107- // function to find teh contour points at the border of p1 after the minimization in p2
107+ // function to find the contour points at the border of p1 after the minimization in p2
108108 auto findContourPointsAtBorder = [&](unsigned int p1, unsigned int p2, double p1Limit, FunctionMinimum & minp2, bool order) {
109109 // we are at the limit in p1
110110 ustate.SetValue (p1, p1Limit);
111111 ustate.Fix (p1);
112- bool ret1, ret2 = false ;
112+ bool ret1 = false ;
113+ bool ret2 = false ;
113114 double deltaFCN = fMinimum .Fval () + fFCN .Up ()- minp2.UserState ().Fval ();
114115 double pmid = minp2.UserState ().Value (p2); // starting point for search
115116 double pdir = minp2.UserState ().Error (p2) * deltaFCN/fFCN .Up (); // direction for the search
@@ -125,19 +126,20 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int
125126 } else if (!ret1 && ret2) {
126127 yvalues.push_back (y2);
127128 } else {
128- // otherwise use both points:
129- yvalues.push_back (y1);
130129 // if points are not the same use both
131130 if (std::abs (y1-y2) > 0.0001 * fMinimum .UserState ().Error (p2)) {
132131 // order them in increasing/decreasing y depending on order flag
133132 int orderDir = (order) ? 1 : -1 ;
134- if (orderDir*(y2-y1) > 0 )
133+ if (orderDir*(y2-y1) > 0 ) {
134+ yvalues.push_back (y1);
135135 yvalues.push_back (y2);
136- else {
136+ } else {
137137 yvalues.push_back (y2);
138138 yvalues.push_back (y1);
139139 }
140140 }
141+ else
142+ yvalues.push_back (y1);
141143 }
142144 print.Debug (" Found contour point at the border: " ,ustate.Value (p1)," , " ,yvalues[0 ]);
143145 if (yvalues.size () > 1 ) print.Debug (" Found additional point at : " ,ustate.Value (p1)," , " ,yvalues[1 ]);
@@ -297,68 +299,74 @@ ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int
297299 double a2 = 0.5 ;
298300 double sca = 1 .;
299301
300- L300:
302+ bool validPoint = false ;
301303
302- if (nfcn > maxcalls) {
303- print.Error (" maximum number of function calls exhausted" );
304- return ContoursError (px, py, result, mnex, mney, nfcn);
305- }
304+ do {
306305
307- print.Debug (" Find new contour point between points with max sep: (" ,idist1->first ," , " ,idist1->second ," ) and (" ,
308- idist2->first ," , " ,idist2->second ," ) with weights " ,a1,a2);
309- // find next point between the found 2 with max separation
310- // start from point situated at the middle (a1,a2=0.5)
311- // and direction
312- double xmidcr = a1 * idist1->first + a2 * (idist2)->first ;
313- double ymidcr = a1 * idist1->second + a2 * (idist2)->second ;
314- // direction is the perpendicular one
315- double xdir = (idist2)->second - idist1->second ;
316- double ydir = idist1->first - (idist2)->first ;
317- double scalfac = sca * std::max (std::fabs (xdir * scalx), std::fabs (ydir * scaly));
318- double xdircr = xdir / scalfac;
319- double ydircr = ydir / scalfac;
320- std::vector<double > pmid (2 );
321- pmid[0 ] = xmidcr;
322- pmid[1 ] = ymidcr;
323- std::vector<double > pdir (2 );
324- pdir[0 ] = xdircr;
325- pdir[1 ] = ydircr;
326-
327- print.Debug (" calling MnCross with pmid: " ,pmid[0 ],pmid[1 ], " and pdir " ,pdir[0 ],pdir[1 ]);
328- MnCross opt = cross (par, pmid, pdir, toler, maxcalls);
329- nfcn += opt.NFcn ();
330- if (!opt.IsValid () || opt.AtLimit ()) {
331- // Exclude also case where we are at limits since point is not in that case
332- // on teh contour. If we are at limit maybe we should try more?
333- if (a1 > 0.5 ) {
334- a1 = 0.25 ;
335- a2 = 0.75 ;
336- print.Debug (" Unable to find point, try closer to p2 with weight values" ,a1,a2);
337- goto L300;
338- }
339- if (a1 < 0.3 ) {
340- print.Info (" Unable to find point on Contour" , i + 1 , ' \n ' , " found only" , i, " points" );
306+ if (nfcn > maxcalls) {
307+ print.Error (" maximum number of function calls exhausted" );
341308 return ContoursError (px, py, result, mnex, mney, nfcn);
342309 }
343- a1 = 0.75 ;
344- a2 = 0.25 ;
345- print.Debug (" Unable to find point, try closer to p1 with weight values" ,a1,a2);
346- // std::cout<<"*****switch direction"<<std::endl;
347- // sca = -1.;
348- goto L300;
349- }
350- double aopt = opt.Value ();
351- int pos = result.size ();
352- if (idist2 == result.begin ()) {
353- result.emplace_back (xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr);
354- print.Info (result.back ());
355- } else {
356- print.Info (*idist2);
357- auto itr = result.insert (idist2, {xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr});
358- pos = std::distance (result.begin (),itr);
359- }
360- print.Info (" Found new point - pos: " ,pos,result[pos], " fcn = " ,opt.State ().Fval ());
361- }
310+
311+ print.Debug (" Find new contour point between points with max sep: (" ,idist1->first ," , " ,idist1->second ," ) and (" ,
312+ idist2->first ," , " ,idist2->second ," ) with weights " ,a1,a2);
313+ // find next point between the found 2 with max separation
314+ // start from point situated at the middle (a1,a2=0.5)
315+ // and direction
316+ double xmidcr = a1 * idist1->first + a2 * (idist2)->first ;
317+ double ymidcr = a1 * idist1->second + a2 * (idist2)->second ;
318+ // direction is the perpendicular one
319+ double xdir = (idist2)->second - idist1->second ;
320+ double ydir = idist1->first - (idist2)->first ;
321+ double scalfac = sca * std::max (std::fabs (xdir * scalx), std::fabs (ydir * scaly));
322+ double xdircr = xdir / scalfac;
323+ double ydircr = ydir / scalfac;
324+ std::vector<double > pmid (2 );
325+ pmid[0 ] = xmidcr;
326+ pmid[1 ] = ymidcr;
327+ std::vector<double > pdir (2 );
328+ pdir[0 ] = xdircr;
329+ pdir[1 ] = ydircr;
330+
331+ print.Debug (" calling MnCross with pmid: " ,pmid[0 ],pmid[1 ], " and pdir " ,pdir[0 ],pdir[1 ]);
332+ MnCross opt = cross (par, pmid, pdir, toler, maxcalls);
333+ nfcn += opt.NFcn ();
334+ if (!opt.IsValid () || opt.AtLimit ()) {
335+ // Exclude also case where we are at limits since point is not in that case
336+ // on the contour. If we are at limit maybe we should try more?
337+ if (a1 < 0.3 ) {
338+ // here when having tried with a1=0.5, a1 = 0.75 and a1=0.25
339+ print.Info (" Unable to find point on Contour" , i + 1 , ' \n ' , " found only" , i, " points" );
340+ return ContoursError (px, py, result, mnex, mney, nfcn);
341+ } else if (a1 > 0.5 ) {
342+ a1 = 0.25 ;
343+ a2 = 0.75 ;
344+ print.Debug (" Unable to find point, try closer to p2 with weight values" ,a1,a2);
345+ } else {
346+ a1 = 0.75 ;
347+ a2 = 0.25 ;
348+ print.Debug (" Unable to find point, try closer to p1 with weight values" ,a1,a2);
349+ // std::cout<<"*****switch direction"<<std::endl;
350+ // sca = -1.;
351+ }
352+ } else {
353+ // a point is found
354+ double aopt = opt.Value ();
355+ int pos = result.size ();
356+ if (idist2 == result.begin ()) {
357+ result.emplace_back (xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr);
358+ print.Info (result.back ());
359+ } else {
360+ print.Info (*idist2);
361+ auto itr = result.insert (idist2, {xmidcr + (aopt)*xdircr, ymidcr + (aopt)*ydircr});
362+ pos = std::distance (result.begin (),itr);
363+ }
364+ print.Info (" Found new point - pos: " ,pos,result[pos], " fcn = " ,opt.State ().Fval ());
365+ validPoint = true ;
366+ }
367+ // loop until a valid point has been found
368+ } while (!validPoint);
369+ } // end loop on points
362370
363371 print.Info (" Number of contour points =" , result.size ());
364372
0 commit comments