//---------------------------------------------------------------------------

#pragma hdrstop

#include "Dvutavr_Choice_Alg_0.h"
#include "ListConst.h"
#include "message.h"
#include "ProcExt.h"
#include "Get_param_sect_func.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
extern MATER MaterProp[MAX_MATERIAL];
extern int   Material_Number;

	  #ifdef EMBRAC
static String text, header;
	  #else
static AnsiString text, header;
	  #endif
static AnsiString Astr;

//---------------------------------------------------------------------------
// Выполнить подбор сечения
// Катюшин. Раздел 2.1.5, Таблица 2.
//---------------------------------------------------------------------------
int Dvutavr_Choice_Alg_0(PARAM_CHOSEN_SECT *Param_chosen_sect, SECT_DVUTAVR *sect, double *mat_force, bool *Check_dvut,
					   bool check_equWidth, bool check_equHeight, bool check_min_sten) {
	 double k_tau0;
     double lambda;
	 double lambda_;
	 GEOM_PARAM_SECT param_sect;
	 double k_a0, kR;
	 double psi, W_Mz, del_w;
	 double sig_ext, sig_int;
	 double lambda_w0, lambda_w0_, lambda_w;
	 double h_opt, hw, bw, h_sect;
	 double A1ef, A2ef, t1ef, t2ef, b1ef, b2ef;
	 int i, rc;
	 double gamma_c;
	 bool flag_message;
	 double t_f_min, bef0;
	 double flag_simm_sect;
	 MATER_PARAM mater_param;
	 double Ry, Rs, Rsw, Ey, Ryw;
	 double thick_range[2];


	 bool check_b1 = Check_dvut[0];
	 bool check_h1 = Check_dvut[1];
	 bool check_b = Check_dvut[2];
	 bool check_h = Check_dvut[3];
	 bool check_b2 = Check_dvut[4];
	 bool check_h2 = Check_dvut[5];
	 bool AutoSves = true;
	 if (check_equWidth && check_equHeight)
	   flag_simm_sect = true;
	 else
	   flag_simm_sect = false;

	 Ey = MaterProp[Material_Number].E;
	 // Расчетное сопротивление растяжению, сжатию и изгибу по пределу текучески
	 double t_max = MAX(sect->h1, sect->h2);
	 //  Получить таблицу свойств стали по марке стали
	 rc = Get_Mater_param(MaterProp[Material_Number].title, &mater_param);
	 if (rc>0) return rc;
   // Проверить границы толщин и получить диапазон толщин
	  rc = Get_thick_range(MaterProp[Material_Number].title, t_max, thick_range);
	  if (rc==1 || rc==2) {  // толщины не попадают в диапазон толщин
		return 100;
	  }
	  Ry = Steel_param_Ry(MaterProp[Material_Number].title, t_max, &rc, true);
   //Rs = 0.58*Ry;

	  if (sect->n_group==-1)  // Сварной двутавр
		Ryw = Steel_param_Ry(MaterProp[Material_Number].title, sect->b, &rc, true);
	  else  // Прокатной (фасонный)
		Ryw = Ry;

	  Rsw = Rs = 0.58*Ryw;               // Предел сдвига

	 double lambda0 = Param_chosen_sect->lambda0;
	 double size_a = Param_chosen_sect->size_a;
	 double delta_lambda = Param_chosen_sect->delta_lambda;
	 double delta_w = Param_chosen_sect->delta_w;
	 double delta_f = MAX(1.15, Param_chosen_sect->delta_f);
     if (Param_chosen_sect->round_h <=0 )
       Param_chosen_sect->round_h = 10;
     if (Param_chosen_sect->round_width <=0 )
	   Param_chosen_sect->round_width = 10;
	 double round_h = Param_chosen_sect->round_h;
	 double round_width = Param_chosen_sect->round_width;
	 double ind_round_thick = Param_chosen_sect->round_thick;

	 bool flag_minimax = Param_chosen_sect->flag_minimax;
	 double max_bpol = Param_chosen_sect->max_bpol;
	 double min_bpol = Param_chosen_sect->min_bpol;
	 double max_tpol = Param_chosen_sect->max_tpol;
	 double min_tpol = Param_chosen_sect->min_tpol;
	 double max_tsten = Param_chosen_sect->max_tsten;
	 double min_tsten = Param_chosen_sect->min_tsten;
	 double max_hsten = Param_chosen_sect->max_hsten;
	 double min_hsten = Param_chosen_sect->min_hsten;
	 gamma_c = Param_chosen_sect->gamma_c;

	 double Nx_sign = mat_force[0];
	 double Mz_sign = mat_force[1];
	 double Nx = ABS(mat_force[0]);
	 double Qy = ABS(mat_force[2]);
	 double Mz = ABS(mat_force[1]);

	 if (Mz < 1.0) {
		Mz = Mz_sign = 1.0;
		return -1;
		//return CHOISE_NULL_MZ;
	 }


	 //-----------------------------------------
	 // Катюшин. Раздел 2.1.5, Таблица 2.
	 //-----------------------------------------
	 // 1. Исходные данные
	 kR=sqrt(Ey/Ry);
	 lambda = lambda0;
	 t1ef = sect->h1;
	 t2ef = sect->h2;
	 b1ef = sect->b1;
	 b2ef = sect->b2;
	 bw = sect->b;
	 hw = sect->h;
	 // вычисление геометрических характеристик сечения
	 Get_param_sect(sect, &(param_sect));
	 // напряжения во внешнем поясе
	 sig_ext = -param_sect.Zct*(Mz/param_sect.Izz) + Nx/param_sect.Ar;
	 // напряжения во внутреннем поясе
	 sig_int = (param_sect.Hsect - param_sect.Zct)*(Mz/param_sect.Izz) + Nx/param_sect.Ar;

	 psi = 0.375*Nx*pow(lambda/(Mz*Mz*Ry),0.33333333);
	 if (psi > 1.0) {
	   text = "В сечении psi > 1.0";
	   //i = Application->MessageBox(text.c_str(), "Алгоритм подбора сечений",
	   //    MB_OK | MB_ICONWARNING);
	   InfMessage(text);
	   Mz = (sqrt(0.052734*pow(Nx, 3)*lambda/Ry))/0.9703;
	   psi = 0.375*Nx*pow(lambda/(Mz*Mz*Ry),0.33333333);
	   //psi = 1.0;
	 }
	 // напряжения во внешнем поясе
	 sig_ext = -param_sect.Zct*(Mz_sign/param_sect.Izz) + Nx_sign/param_sect.Ar;
	 // напряжения во внутреннем поясе
	 sig_int = (param_sect.Hsect - param_sect.Zct)*(Mz_sign/param_sect.Izz) + Nx_sign/param_sect.Ar;

	 for (i=0; i<3; i++ ) {
	   // Расчетное сопротивление растяжению, сжатию и изгибу по пределу текучески
	   double t_max = MAX(sect->h1, sect->h2);
	   //  Получить таблицу свойств стали по марке стали
	   rc = Get_Mater_param(MaterProp[Material_Number].title, &mater_param);
	   if (rc>0) return rc;
	   // Проверить границы толщин и получить диапазон толщин
	   rc = Get_thick_range(MaterProp[Material_Number].title, t_max, thick_range);
	   if (rc==1 || rc==2) {  // толщины не попадают в диапазон толщин
		  return 100;
	   }
	   Ry = Steel_param_Ry(MaterProp[Material_Number].title, t_max, &rc, true);

	   if (sect->n_group==-1)  // Сварной двутавр
		 Ryw = Steel_param_Ry(MaterProp[Material_Number].title, sect->b, &rc, true);
	   else  // Прокатной (фасонный)
		 Ryw = Ry;

	   Rsw = Rs = 0.58*Ryw;               // Предел сдвига

	   double Ar = t1ef * b1ef + t2ef * b2ef + hw * bw;
	   double sigma_N = Nx/Ar;

	   //InfMessage("sig_ext="+FloatToStr(sig_ext)+", sig_int="+FloatToStr(sig_int));
	 //----------------------------------------------
	 // 2. вычисление начальных значений параметров
	 //----------------------------------------------
		k_tau0 = 1.316*Qy*pow((lambda/(Mz*Mz*Ry)),0.33333333);

        //k_a0 = sect->h/size_a;
        if (i==0) {
           k_a0 = pow(Mz*lambda/Ry,0.33333333)/size_a;
        }
        else
           k_a0 = h_sect/size_a;

        psi = 0.375*Nx*pow(lambda/(Mz*Mz*Ry),0.33333333);
        if (psi > 1) {
          //psi = 0.99;
          psi = sigma_N/Ry;
        }
     //----------------------------------------------
     // 3. вычисление требуемого момента сопротивления сечения при действии одного изгибающего момента
     //----------------------------------------------
        W_Mz = Mz/(Ry*gamma_c);

     // Определение поправочного коэффициента к k_tau
		if (flag_minimax || check_min_sten) {
		  double hw_q = Round_step(Qy/(Rs*gamma_c*bw), round_h);
		  hw = MAX(hw_q, min_hsten);
		  //k_tau0 /= hw/hw_q;
		  if (hw_q<1e-4) {
			k_tau0 = 1e-4;
		  }
		  else
			k_tau0 /= hw/hw_q;
		}
     //----------------------------------------------
     // 4.  определение начальной предельной гибкости стенки
     //----------------------------------------------
        lambda_w0_ = MAX(1.0, 6.0*(1-0.5*psi)*delta_lambda/
                     (pow(1+12.0*k_tau0*k_tau0/((1+0.76*k_a0)*(1+0.76*k_a0)),0.25)));
        lambda_w0 = lambda_w0_ * kR;

     //----------------------------------------------
     // 6. Определение ооптимальной высоты сечения двутавра
     //----------------------------------------------
		if (flag_simm_sect)
          h_opt = pow(1.5*W_Mz*lambda_w0/(1 - psi), 0.33333333);
        else
          h_opt = pow(1.5*W_Mz*lambda_w0, 0.33333333);
        if (flag_minimax || check_min_sten) {
		  h_opt = MAX(h_opt, min_hsten);
		  h_opt = MIN(h_opt, max_hsten);
		}
     // определение расчетной высоты стенки
        if (!check_h) {
           if (psi >= 0.99) {
			  text="Подбор высоты стенки производится из условия прочности на срез";
			  //header="";
              //rc=Application->MessageBox(text.c_str(), header.c_str(), MB_OK | MB_ICONWARNING);
			  InfMessage(text + " (psi >= 0.99)");
			  hw = Round_step(Qy/(Rs*gamma_c*bw), round_h);
              //i = 2;              // Чтобы выйти из цикла
           }
           else {
             double hw_q = Round_step(Qy/(Rs*gamma_c*bw), round_h);
             hw = Round_step_floor(h_opt, round_h);
             if (hw < hw_q) {
               hw = hw_q;
               //i = 2;
             }
           }
           if (flag_minimax || check_min_sten) {
             hw = MAX(hw, min_hsten);
           }
        }
        if (sig_ext < 0 && sig_int < 0 ) { // Обе полки сжаты
          if (sig_ext < sig_int)
             sig_int = 0;
          else
             sig_ext = 0;
          //return CHOISE_EXCENTR_COMPRESS;
        }
     //----------------------------------------------
     // 7. Назначение высоты сечения двутавра
     //----------------------------------------------
        h_sect = hw + (t1ef + t2ef)*0.5;

     //----------------------------------------------
     // 8. Определение расчетной толщины стенки
     //----------------------------------------------
        if (!check_b)
           bw = Round_row(hw/lambda_w0, ind_round_thick);
        // Установка ограничений на толщину стенки
		if (flag_minimax) {
           bw = MAX(bw, min_tsten);
        }
		if (flag_minimax) {
           bw = MIN(bw, max_tsten);
        }

     //----------------------------------------------
     // 10. Определение фактической гибкости стенки
     //----------------------------------------------
        lambda = hw/bw;

        if (delta_w==0) { // гибкая стенка
            lambda_ = lambda/kR;
            del_w = 5.1*(1/lambda_ - 1/(lambda_*lambda_));
        }
        else
            del_w = delta_w;

     //----------------------------------------------
     // 12. Определение расчетной площади полок
     //----------------------------------------------
     if (psi > 0.5) {
       A1ef = MAX(5*bw, W_Mz/h_sect - (bw*hw*hw*del_w/(6.0*h_sect)));
       A2ef = A1ef;
     }
     else {
		if (flag_simm_sect) {
          A1ef = MAX(5*bw, W_Mz/((1-psi)*h_sect) - (bw*hw*hw*del_w/(6.0*h_sect)));
          A2ef = A1ef;
        }
        else {
          A1ef = MAX(5*bw, W_Mz/((1-psi)*h_sect) - (bw*hw*hw*del_w/(6.0*h_sect))*(1 - 3.0*psi)/(1-psi));
          A2ef = MAX(5*bw, W_Mz/((1+psi)*h_sect) - (bw*hw*hw*del_w/(6.0*h_sect))*(1 + 3.0*psi)/(1+psi));
        }
     }
       //---------------------------------------------------------------------------
       // Сжата внешняя полка
       //---------------------------------------------------------------------------
        if (sig_ext<0) { // внешняя полка сжата
          if (!check_h1) {
            t1ef = delta_f*sqrt(A1ef/kR);
			if (flag_minimax) {
              t1ef = MAX(t1ef, min_tpol);
              t1ef = MIN(t1ef, max_tpol);
            }
          }
          if (!check_b1) {
            b1ef = A1ef/t1ef;
            //bef0 = Get_max_bpol(t1ef, ind_round_thick);
            //if (flag_minimax || ind_round_thick == 2) {
            if (flag_minimax) {
              b1ef = MAX(b1ef, min_bpol);
              //bef0 = MIN(bef0, max_bpol);
              bef0 = max_bpol;
              if (b1ef > bef0) {
                b1ef = MIN(b1ef, bef0);
                t1ef = A1ef/b1ef;
                if (t1ef > max_tpol) {
                //text = "Сечение " + AnsiString(title_sect) + ", внешний пояс. Не удается удовлетворить оба ограничения - на максимальную толщину и ширину полки. Подбор параметров не выполняется";
                //InfMessage(text);
				//rc = Application->MessageBox(text.c_str(), " ", MB_OK | MB_ICONWARNING);
				  return CHOISE_BREAK_LIMIT;
                }
              }
            }
          }
          if (check_equWidth)
            b2ef = b1ef;
          if (!check_h2) {
            t2ef = A2ef/b2ef;
            if (flag_minimax) {
              t2ef = MAX(t2ef, min_tpol);
              if (t2ef > max_tpol) {
                t2ef = MIN(t2ef, max_tpol);
                b2ef = A2ef/t2ef;
                b1ef = b2ef;
                //bef0 = Get_max_bpol(t2ef, ind_round_thick);
                //bef0 = MIN(bef0, max_bpol);
                bef0 = max_bpol;
                if (b2ef > bef0) {
                //text = "Сечение " + AnsiString(title_sect) + ", внутренний пояс. Не удается удовлетворить оба ограничения - на максимальную толщину и ширину полки. Подбор параметров не выполняется";
                //InfMessage(text);
                //rc = Application->MessageBox(text.c_str(), " ", MB_OK | MB_ICONWARNING);
                  return CHOISE_BREAK_LIMIT;
                }
              }
            }
          }
        }
       //---------------------------------------------------------------------------
       // Сжата внутренняя полка
       //---------------------------------------------------------------------------
        if (sig_int < 0) {
          if (!check_h2) {
            t2ef = delta_f*sqrt(A1ef/kR);
            if (flag_minimax) {
              t2ef = MAX(t2ef, min_tpol);
              t2ef = MIN(t2ef, max_tpol);
            }
          }
          if (!check_b2) {
            b2ef = A1ef/t2ef;
            //bef0 = Get_max_bpol(t2ef, ind_round_thick);
            //if (flag_minimax || ind_round_thick == 2) {
            if (flag_minimax) {
              b2ef = MAX(b2ef, min_bpol);
              //bef0 = MIN(bef0, max_bpol);
              bef0 = max_bpol;
              if (b2ef > bef0) {
                b2ef = MIN(b2ef, bef0);
                t2ef = A1ef/b2ef;
                if (t2ef > max_tpol) {
                //text = "Сечение " + AnsiString(title_sect) + ", внутренний пояс. Не удается удовлетворить оба ограничения - на максимальную толщину и ширину полки. Подбор параметров не выполняется";
                //InfMessage(text);
                //rc = Application->MessageBox(text.c_str(), " ", MB_OK | MB_ICONWARNING);
                  return CHOISE_BREAK_LIMIT;
                }
              }
            }
          }
          if (check_equWidth)
            b1ef = b2ef;
          if (!check_h1) {
            t1ef = A2ef/b1ef;
			if (flag_minimax) {
              t1ef = MAX(t1ef, min_tpol);
              if (t1ef > max_tpol) {
                t1ef = MIN(t1ef, max_tpol);
                b1ef = A1ef/t1ef;
                b2ef = b1ef;
                //bef0 = Get_max_bpol(t1ef, ind_round_thick);
                //bef0 = MIN(bef0, max_bpol);
                bef0 = max_bpol;
                if (b1ef > bef0) {
                  //text = "Сечение " + AnsiString(title_sect) + ", внешний пояс. Не удается удовлетворить оба ограничения - на максимальную толщину и ширину полки. Подбор параметров не выполняется";
                  //InfMessage(text);
                  //rc = Application->MessageBox(text.c_str(), " ", MB_OK | MB_ICONWARNING);
                  return CHOISE_BREAK_LIMIT;
                }
              }
            }
          }
        }
       //---------------------------------------------------------------------------
        if (sig_ext > 0 && sig_int >0) {
          //text = "Сечение " + AnsiString(title_sect) + ". Обе полки растянуты, подбор параметров не выполняется";
          //InfMessage(text);
          //rc = Application->MessageBox(text.c_str(), " ", MB_OK | MB_ICONWARNING);
          return CHOISE_TENSION;
        }
     }
     //--------------------------------------------------
     // Чтобы вычислить геометрические параметры сечения
     sect->h = hw;
     sect->b = bw;
     sect->b1 = b1ef;
     sect->h1 = t1ef;
     sect->b2 = b2ef;
     sect->h2 = t2ef;
     // вычисление геометрических характеристик сечения
     Get_param_sect(sect, &(param_sect));
     double Izz0 = param_sect.Izz;
     t1ef = Round_row(t1ef, ind_round_thick);
     t2ef = Round_row(t2ef, ind_round_thick);
     if (ind_round_thick == 2) {
       for (i=0; i<4; i++) {
         bef0 = Get_max_bpol(t1ef, ind_round_thick);
         bef0 = MIN(bef0, Get_max_bpol(t2ef, ind_round_thick));
         if (b1ef > bef0 || b2ef > bef0) {
           sect->b1 = bef0;
           sect->h1 = t1ef;
           sect->b2 = bef0;
           sect->h2 = t2ef;
           Get_param_sect(sect, &(param_sect));
           if (param_sect.Izz < Izz0*0.99) {
             if (t1ef == t2ef) {
               t1ef = Round_row(t1ef+1, ind_round_thick);
               t2ef = Round_row(t2ef+1, ind_round_thick);
             }
             else {
               if (t1ef < t2ef)
                 t1ef = Round_row(t1ef+1, ind_round_thick);
               else
                 t2ef = Round_row(t2ef+1, ind_round_thick);
             }
           }
           else
             break;
         }
         else
           break;
       }
     }
     b1ef = Round_row_bpol(t1ef, b1ef, round_width, ind_round_thick);
     b2ef = Round_row_bpol(t2ef, b2ef, round_width, ind_round_thick);
     if (sect->n_group < 0 ) {   // сварное сечение
        // Проверки свеса
        if (sig_ext < -0.01*Ry) {
          t_f_min = Round_row((b1ef - bw)/kR, ind_round_thick) ;
          if (AutoSves)
            t1ef = MAX(t_f_min, t1ef);
          if (check_equWidth) {
             b2ef = b1ef;
          }
        }
        if (sig_int < -0.01*Ry) {
          t_f_min = Round_row((b2ef - bw)/kR, ind_round_thick) ;
          if (AutoSves)
            t2ef = MAX(t_f_min, t2ef);
          if (check_equWidth) {
             b1ef = b2ef;
          }
        }
        /*
        for (i=0; i<4; i++) {
          bef0 = Get_max_bpol(t1ef, ind_round_thick);
          if (b1ef <= bef0)
            break;
          t1ef = Round_row(t1ef+1, ind_round_thick);
        }
        for (i=0; i<4; i++) {
          bef0 = Get_max_bpol(t2ef, ind_round_thick);
          if (b2ef <= bef0)
            break;
          t2ef = Round_row(t2ef+1, ind_round_thick);
        }
        */
        sect->h = hw;
        sect->b = bw;
        sect->b1 = b1ef;
        sect->h1 = t1ef;
        sect->b2 = b2ef;
        sect->h2 = t2ef;
     }
	 else {
	   ;
	 }
     sect->flag_concl = true;

	  return CHOISE_OK;

}
//---------------------------------------------------
// Контроль кода завершения
void   Dvutavr_OutControl(int rc) {
   int i;

   text = "";
   header = "";
   if (rc==0)
      return;
   switch (rc) {
    case CHOISE_NULL_MZ:
      text="Изгибающий момент равен нулю";
    break;
    case CHOISE_EXCENTR_COMPRESS:
    text="Сжатие в обоих поясах";
    break;
    case CHOISE_BREAK_LIMIT:
      header = "Подбор параметров не выполнен ";
      text="Ограничения на размеры не могут быть удовлетворены";
    break;
    case CHOISE_TENSION:
      header = "Подбор параметров не выполнен ";
      text="Растяжение в обоих поясах";
    break;
   }
   i = Application->MessageBox(text.c_str(), header.c_str(), MB_OK | MB_ICONWARNING);
   return;
}
//---------------------------------------------------------------------------

