double CMinimizerBase::LineMinimizer(CNumVec &position, double dist0, const CNumVec &direction, bool roughly) { LM_direction=&direction; LM_start_pos=&position; double pleft, pmin, pright, pnext; double dleft, dmin, dright, dnext; pleft=0; dleft=dist0; pnext=1; dnext=LineDistance(pnext); if(dleft<dnext) // minimum is less than precision (= gradient norm) deep return(dist0); // try to bracket a minimum along "direction" pmin=pleft; dmin=dleft; do { pleft=pmin; dleft=dmin; pmin=pnext; dmin=dnext; pnext*=2; dnext=LineDistance(pnext); } while(dmin>dnext); if(roughly && pmin>50) // stops exact determination if minimum is far from optimal value { CNumVec p=direction; p*=pleft; position+=p; return(dmin); } pright=pnext; dright=dnext; // Further bracket minimum using "GoldenCut" // Ideally this should be replaced by some function taking into account the // pretty good reproducible function along the line minimization bool longer_interval_right=true; while(pright-pleft>1.0) { if(longer_interval_right) { pnext=pmin+(pright-pmin)*0.38; dnext=LineDistance(pnext); if(dnext<dmin) { pleft=pmin; dleft=dmin; pmin=pnext; dmin=dnext; } else { pright=pnext; dright=dnext; longer_interval_right=false; } } else { pnext=pmin+(pleft-pmin)*0.38; dnext=LineDistance(pnext); if(dnext<dmin) { pright=pmin; dright=dmin; pmin=pnext; dmin=dnext; } else { pleft=pnext; dleft=dnext; longer_interval_right=true; } } } // Change 'position to Minimum position CNumVec p=direction; p*=pmin; position+=p; return(dmin); }
int checkwalls( World *w, View *v ) { extern fixed view_height; Wall *wall = (Wall *) w->walls->table, *mem_wall; double x1, y1, tmp, min = 512.0; int i; x1 = FIXED_TO_FLOAT(v->x); y1 = FIXED_TO_FLOAT(v->y); if ( x1 == x && y1 == y ) return DONT_INTERSECT; for (i = 0; i < TABLE_SIZE(w->walls); i++, wall++ ) { /* Check Distance */ tmp = LineDistance( x1, y1, FIXED_TO_FLOAT(wall->vertex1->x ), FIXED_TO_FLOAT(wall->vertex1->y ), FIXED_TO_FLOAT(wall->vertex2->x ), FIXED_TO_FLOAT(wall->vertex2->y ) ); if ( fabs(tmp) < fabs( min ) ) { min = tmp; mem_wall = wall; } } /* is there any point in checking further. */ if ( fabs( min ) < VECTOR_LEN ) { /* start examine the wall */ fixed ceiling, floor; /* Check the outher side of the object */ if ( min > 0.0 ) { floor = mem_wall->front->floor; ceiling = mem_wall->front->ceiling; } else { floor = mem_wall->back->floor; ceiling = mem_wall->back->ceiling; } /* if the stair is less than FIXED_ONE_QUARTER and the head has goes free and there are enought room. */ if ( FIXED_ONE_QUARTER >= (floor-v->height) && ( ceiling > v->height ) && ( MAN_SIZE <= (ceiling-floor) ) ) { if ( s_wall != mem_wall || ( min > 0.0 && side <= 0.0 ) || (min <= 0.0 && side > 0.0 ) ) { if ( min < 0.0 ) view_height = mem_wall->front->floor+MAN_SIZE; else view_height = mem_wall->back->floor+MAN_SIZE; s_wall = mem_wall; } } else /* am i running towards the wall? */ if ( fabs( min ) < fabs( side ) ) { s_wall = mem_wall; slide_wall( &x, &y, x1, y1, side, min ); v->x = FLOAT_TO_FIXED( x ); v->y = FLOAT_TO_FIXED( y ); return 0; } } side = min; x = x1; y = y1; return 0; }