//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <process.h>
#pragma hdrstop

#include "MultiSupport.h"
#include "ListConst.h"
#include "ProcExt.h"
#include "Data_Gen.h"
#include "message.h"
#include "Alinit.h"
#include "SelectMod_Param.h"
#include "pCanvas_func.h"
#include "alinit.h"
#include "SortP.h"

#include "GrapFunc.h"

#include "OutGraphic.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CSPIN"
#pragma resource "*.dfm"

#define MAXLENGTH   10;
#define RadMoment   30;

extern FILE *input_g;

TMultiSupportForm *MultiSupportForm;
extern TGrapFunc   GrapFunc;

extern int  list_index_type[MAX_ADD_SECT];  // список индексов типов сечений списка
extern int  list_index_order[MAX_ADD_SECT];  // список порядковых номеров сечений, помещенных в список для выбора
extern int  index_choice[MAX_ADD_SECT];

extern int  Page_Height;
extern int  Page_Width;
extern bool flag_image;


static int NAddFunc;
static double koeff_add[20][20];
static int num_fun[20][20];
static int n_fun[20];
//static int Nfun_Add;
static char nfu[8*1000];
static char nfu_add[8*20];
static bool flag_add;
static double MaxFun, MinFun;


double Round_scale(double scale0, double step);

//---------------------------------------------------------------------------
__fastcall TMultiSupportForm::TMultiSupportForm(TComponent* Owner)
    : TForm(Owner)
{
	 Data = new TData3;
	 Data->Color = clWhite;
	 Shape1->Brush->Color =clWhite;
	 NAddFunc=0;
	 index_portion = 0;  // размер массива регионов
	 Alloc_region(PORTION_REGION);
	 n_beam = 0;
	 k_beam = -1;
	 matr_result = NULL;
	 x_result = NULL;
	 Margins = 10;
	 HText = 10;
	 StepGrid = 20;

}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::FormShow(TObject *Sender)
{
     if (index_portion!=0) {
         delete(EI);
         delete(q_);
         delete(N_);
         delete(m_);
         delete(kp);
         delete(loads);
         delete(constr);
     }
	 if (SelectMod_ParamForm==NULL)
         Application->CreateForm(__classid(TSelectMod_ParamForm), &SelectMod_ParamForm);
     index_portion = PORTION_REGION;
     EI = new BeamRegion[PORTION_REGION];  // Регионы поперечной жесткости
     q_ = new BeamRegion[PORTION_REGION];  // Регионы погонной поперечной нагрузки
     N_ = new BeamRegion[PORTION_REGION];  // Регионы эпюры продольных сил
     m_ = new BeamRegion[PORTION_REGION]; // Регионы погонного момента
     kp = new BeamRegion[PORTION_REGION];  // Регионы погонной жесткости упругого основания
     loads = new Load[PORTION_REGION];       // Точки задания сосредоточенных нагрузок
     constr = new Constraint[PORTION_REGION]; // Точки задания связей (опор)
	//beam_mod.EI_length = 0;
     //beam_mod.q_length = 0;
     //beam_mod.N_length = 0;
     //beam_mod.m_length = 0;
     //beam_mod.kp_length = 0;
     //beam_mod.loads_length = 0;
     //beam_mod.constr_length = 0;
	 //Edit_ID->Text = n_beam + 1;
	   type_region = 5;
       PageControl_Param->ActivePage=TabSheet_ConcentrLoad;

       SelectRow = 0;
	   CheckBox_LinearClick(Sender);
	   BitBtn_NewClick(Sender);
	 PageControl1->ActivePage=TabSheetSourse;
	 CheckBox_LinearClick(Sender);

}
//---------------------------------------------------------------------------
//

void __fastcall TMultiSupportForm::BitBtnChoiceColorClick(TObject *Sender)
{
      int j;
      char str0[80];

      if (ColorDialog1->Execute()) {
          Data->Color = ColorDialog1->Color;
          Shape1->Brush->Color = ColorDialog1->Color;
          if  (n_fun>0) {
              DrawOut(n_fun, n_result, index_fun);
          }
      }
}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::DrawOut(int nfun, int n_result, int *index)
{
    int i,j,k,m;
    int rc,n0,nSa;
    int  numr[100];
    double rez[1000];
    double *Sa;
    double **matr;
    double t0;
    double koeff;
    char str[240];
    char str0[24];
    int  flagSa;
    char funSa[24];
    double sa_max;
    TColor LineColor[]={clTeeColor, clTeeColor, clTeeColor, clTeeColor,
    clTeeColor, clTeeColor, clTeeColor, clTeeColor};


	koeff = strtod(((AnsiString)ComboBoxKoeff->Text).c_str(),NULL);
        Series1->LinePen->Width=CSpinEditLineWidth->Value;
        Series2->LinePen->Width=CSpinEditLineWidth->Value;
        Series3->LinePen->Width=CSpinEditLineWidth->Value;
        Series4->LinePen->Width=CSpinEditLineWidth->Value;
        Series5->LinePen->Width=CSpinEditLineWidth->Value;
        Series6->LinePen->Width=CSpinEditLineWidth->Value;
        Series7->LinePen->Width=CSpinEditLineWidth->Value;
        Series8->LinePen->Width=CSpinEditLineWidth->Value;
        if (Data->Color!=clWhite) {
           LineColor[0]=Data->Color;
		   LineColor[1]=Data->Color;
           LineColor[2]=Data->Color;
           LineColor[3]=Data->Color;
           LineColor[4]=Data->Color;
           LineColor[5]=Data->Color;
           LineColor[6]=Data->Color;
           LineColor[7]=Data->Color;
        }
        Series1->Clear();
        Series2->Clear();
        Series3->Clear();
        Series4->Clear();
        Series5->Clear();

       for(i=0; i<n_result; i++) {
          Series1->AddXY(x_result[i], matr_result[i][index[0]]*koeff,"",  LineColor[0]);
          if (n_fun == 1) continue;
          Series2->AddXY(x_result[i], matr_result[i][index[1]]*koeff,"",  LineColor[1]);
          if (n_fun == 2) continue;
          Series3->AddXY(x_result[i], matr_result[i][index[2]]*koeff,"",  LineColor[2]);
          if (n_fun == 3) continue;
          Series4->AddXY(x_result[i], matr_result[i][index[3]]*koeff,"",  LineColor[3]);
          if (n_fun == 4) continue;
          Series5->AddXY(x_result[i], matr_result[i][index[4]]*koeff,"",  LineColor[4]);
       }
       Chart1->Title->Text->Clear();
       sprintf(str,"%s: max=%g, x=%g;  min=%g, x=%g",
               ListBox1->Items->Strings[index[0]].c_str(),
               koeff*Max_Value[index[0]], Round(Max_X[index[0]], 0),
			   koeff*Min_Value[index[0]], Round(Min_X[index[0]], 0));
       Chart1->Title->Text->Add(str);
       
       Repaint();
}
//---------------------------------------------------------------------------


void __fastcall TMultiSupportForm::ComboBoxKoeffChange(TObject *Sender)
{
    if  (n_fun>0) {
      DrawOut(n_fun, n_result, index_fun);
    }
}
//---------------------------------------------------------------------------



void __fastcall TMultiSupportForm::CSpinEditLineWidthChange(TObject *Sender)
{
      int j;
      DrawOut(n_fun, n_result, index_fun);

}
//---------------------------------------------------------------------------
// Добавить параметр

void __fastcall TMultiSupportForm::BitBtnCloseClick(TObject *Sender)
{
   Close();
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::BitBtnCancelClick(TObject *Sender)
{
   Close();
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::BitBtn_AddClick(TObject *Sender)
{
   int rc;
   
   InsertToGridFromText(-1);

   rc = LoadDataFromGrid_param();
   if (rc>0) return;

   Draw_beam();
}
//-----------------------------------------------------------------------------
// Вставить данные в k-ю строку таблицы
void __fastcall TMultiSupportForm::InsertToGridFromText(int index_row) {
   int rc, k;
   double x0, Len, p1, p2;
   char stroka[120];
   BeamRegion br;
   Load ld;
   Constraint cn;
   double x20;

   n_fun = 0;
   n_result = 0;

   if (type_region<=4) {
       if (index_row<0)
         k = StringGrid_param->RowCount - 1;
       else
         k = index_row - 1;
       if (k>0) {
          rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][k], &x0);
          if (rc>0) return;
          rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[2][k], &Len);
          if (rc>0) return;
          x20 = x0 + Len;
       }
	   else
          x20 = 0;
      if (type_region > 0) {
        rc = String_double_zero_plus(Label_x0->Caption, Edit_x0->Text, &x0);
        if (rc>0) return;
      }
      else {
        x0 = x20;
      }
      rc = String_double_zero_plus(Label_Len->Caption, Edit_Len->Text, &Len);
      if (rc>0) return;
	  rc = String_double(Label_p1->Caption, Edit_p1->Text, &p1);
      if (rc>0) return;
      rc = String_double(Label_p2->Caption, Edit_p2->Text, &p2);
      if (rc>0) return;
      if (type_region==0 ) {
         if (p1 <=0 || p2 <=0) {
			rc = ApplicationMessageBox("Изгибная жесткость на участке должна быть больше нуля",
                          " ", MB_OK | MB_ICONERROR);
            return;
         }
      }
      if (type_region==3 ) {
         if (p1 <=0) {
			rc = ApplicationMessageBox("Коэффициент жесткости упругого основания на участке должен быть больше нуля",
                          " ", MB_OK | MB_ICONERROR);
            return;
         }
      }
      if (type_region==0 ) {
		 if (p1 <=0 || p2 <=0) {
			rc = Application->MessageBox(("Изгибная жесткость на участке должна быть больше нуля",                             FloatToStr(x20)+")").c_str(),
						  L" ", MB_OK | MB_ICONERROR);
            return;
         }
      }
      if (x0 < x20) {
            rc = Application->MessageBox(("Координата начала участка X0 не должна быть меньше координаты конца предыдущего участка ("+
                                          FloatToStr(x20)+")").c_str(),
						  L" ", MB_OK | MB_ICONERROR);
			return;
      }
      if (type_region>0) {
		if (x0 + Len > CalcLengthBeam()) {
          rc = Application->MessageBox(("Заданный участок выходит за пределы балки, длина которой равна "+FloatToStr(Length_beam)+", и определяется участками EI").c_str(),
                          L" ", MB_OK | MB_ICONERROR);
          return;
        }
      }
      br.X0 = x0;
      br.Len = Len;
      br.begValue = p1;
      br.endValue = p2;

      BeamRegionToGrid_param(br, index_row);

      //Edit_x0->Text = FloatToStr(x0 + Len);
    }
    else {
	  if (type_region==5) {
		rc = String_double_zero_plus(Label_X0Load->Caption, Edit_X0Load->Text, &x0);
        if (rc>0) return;
		rc = String_double(Label_Fz->Caption, Edit_Fz->Text, &p1);
		if (rc>0) return;
		rc = String_double(Label_My->Caption, Edit_My->Text, &p2);
        if (rc>0) return;
        if (p1 == 0 && p2==0) {
			rc = ApplicationMessageBox("Значение силы и момента не могут одновременно задаваться нулевыми",
                          " ", MB_OK | MB_ICONERROR);
			return;
        }
		if (x0 > CalcLengthBeam()) {
		  rc = Application->MessageBox(("Значение координаты выходит за пределы балки, длина которой "+FloatToStr(Length_beam)+
										" м. Установить длину "+FloatToStr(x0)+" м ?").c_str(), L" ",
							  MB_YESNO | MB_ICONQUESTION);
		  if (rc==IDYES) {
			Length_beam = x0;
			Edit_Length->Text = FloatToStr(Length_beam);
		  }
		  else {
			return;
		  }
		}
        ld.X = x0;
        ld.u = 0;
        ld.v = p1;
        ld.c = p2;
        LoadToGrid_param(ld, index_row);
      }
      else {
        rc = String_double_zero_plus(Label_X0Constr->Caption, Edit_X0Constr->Text, &x0);
        if (rc>0) return;
        Len = x0;
		if (x0 > CalcLengthBeam()) {
          rc = Application->MessageBox(("Значение координаты выходит за пределы балки, длина которой "+FloatToStr(Length_beam)+" определяется участками EI").c_str(),
						  L" ", MB_OK | MB_ICONERROR);
          return;
        }
		cn.X = x0;
        cn.u = 0;
        cn.v = p1;
        cn.c = p2;
        ConstraintToGrid_param(cn, index_row);
      }
    }
}
//---------------------------------------------------------------------------
// Подсчет длины балки
double __fastcall TMultiSupportForm::CalcLengthBeam()
{
   int rc;
   double ss;
   rc = String_double(Label_Length->Caption, Edit_Length->Text, &ss);
   if (rc>0) {
	 Length_beam = 0;
	 return 0.0;
   }
   else {
	 Length_beam = ss;
	 return Length_beam;
   }
}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::BeamRegionToGrid_param(BeamRegion br, int index_row)
{
   int k, rc;
   double x0, x1, Len;
	  if (index_row<0)  {  // добавить в конец
         StringGrid_param->RowCount++;
         k = StringGrid_param->RowCount - 1;
      }
      else {
         k = index_row;
      }
      if (k==1) {
        x1 = 0;
      }
      else {
         StringGrid_param->Cells[1][k] = br.X0;
         rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][k-1], &x0);
         if (rc>0) return;
         rc = String_double_zero_plus(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][k-1], &Len);
         if (rc>0) return;
         x1 = x0 + Len;
      }
      if (x1 != br.X0) {
        StringGrid_param->Cells[0][k] = k;
        StringGrid_param->Cells[1][k] = x1;
        StringGrid_param->Cells[2][k] = br.X0 - x1;
        StringGrid_param->Cells[3][k] = 0;
        StringGrid_param->Cells[4][k] = 0;
        StringGrid_param->RowCount++;
        k++;
      }
      StringGrid_param->Cells[0][k] = k;
      StringGrid_param->Cells[1][k] = br.X0;
	  StringGrid_param->Cells[2][k] = br.Len;
      StringGrid_param->Cells[3][k] = br.begValue;
      StringGrid_param->Cells[4][k] = br.endValue;
}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::LoadToGrid_param(Load ld, int index_row)
{
   int k;
      if (index_row <0) {
        StringGrid_param->RowCount++;
        k = StringGrid_param->RowCount - 1;
      }
      else
        k = index_row;
      StringGrid_param->Cells[0][k] = k;
      StringGrid_param->Cells[1][k] = ld.X;
      StringGrid_param->Cells[2][k] = ld.v;
      StringGrid_param->Cells[3][k] = ld.c;
}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::ConstraintToGrid_param(Constraint cn, int index_row)
{
   int k;
      if (index_row <0) {
        StringGrid_param->RowCount++;
        k = StringGrid_param->RowCount - 1;
      }
      else
        k = index_row;
	  StringGrid_param->Cells[0][k] = k;
      StringGrid_param->Cells[1][k] = cn.X;
      StringGrid_param->Cells[2][k] = cn.v;
      StringGrid_param->Cells[3][k] = cn.c;
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::CheckBox_LinearClick(TObject *Sender)
{
    if (CheckBox_Linear->Checked) {
      Label_p1->Caption = "Параметр 1";
      Label_p2->Visible = true;
      Edit_p2->Visible = true;
	}
    else {
      Label_p1->Caption = "Параметр";
      Label_p2->Visible = false;
      Edit_p2->Visible = false;
	}
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::Edit_p1Change(TObject *Sender)
{
   if (!CheckBox_Linear->Checked) {
      Edit_p2->Text = Edit_p1->Text;
   }
}
//---------------------------------------------------------------------------


void __fastcall TMultiSupportForm::BitBtn_CalculateClick(TObject *Sender)
{
     int rc, i;
     char stroka[240];
     double MaxLength;
     double *Xsort;
     int *index;

     MaxLength = MAXLENGTH;


     if (beam_mod.EI_length == 0) {
		rc = ApplicationMessageBox("Не задана изгибная жесткоть ни на одном участке балки. Решение не может быть выполнено",
                          " ", MB_OK | MB_ICONERROR);
         return;
     }
     if (beam_mod.q_length == 0 && beam_mod.m_length == 0 && beam_mod.loads_length == 0) {
		rc = ApplicationMessageBox("На балке не задан ни один из видов нагрузки",
                          " ", MB_OK | MB_ICONERROR);
         return;
     }
     if (beam_mod.kp_length == 0 && beam_mod.constr_length == 0) {
		rc = ApplicationMessageBox("Для балки не заданы опоры",
                          " ", MB_OK | MB_ICONERROR);
         return;
     }
     int kv = 0;
	 int kc = 0;
     for (int i = 0; i<beam_mod.constr_length; i++) {
       if (constr[i].v!=0) kv ++;
       if (constr[i].c!=0) kc ++;
     }
     if ((kv >= 1 && kc >= 1) || kv >= 2)
        flag_rigid = false;
     if (beam_mod.kp_length == 0 && flag_rigid) {
		rc = ApplicationMessageBox("Заданные опоры балки не исключают перемещения твердого тела",
                          " ", MB_OK | MB_ICONERROR);
         return;
     }
     if (beam_mod.q_length == 0) {
       beam_mod.q_length = 1;
       q_[0].X0 = 0;
       q_[0].Len = 0;
       q_[0].begValue = 0;
       q_[0].endValue = 0;
     }
     if (beam_mod.N_length == 0) {
       beam_mod.N_length = 1;
       N_[0].X0 = 0;
       N_[0].Len = 0;
       N_[0].begValue = 0;
       N_[0].endValue = 0;
     }
     if (beam_mod.m_length == 0) {
       beam_mod.m_length = 1;
       m_[0].X0 = 0;
	   m_[0].Len = 0;
       m_[0].begValue = 0;
       m_[0].endValue = 0;
     }
     if (beam_mod.kp_length == 0) {
       beam_mod.kp_length = 1;
       kp[0].X0 = 0;
       kp[0].Len = 0;
       kp[0].begValue = 0;
       kp[0].endValue = 0;
     }
     if (beam_mod.loads_length == 0) {
       beam_mod.loads_length = 1;
       loads[0].X = 0;
       loads[0].u = 0;
       loads[0].v = 0;
       loads[0].c = 0;
     }
     if (beam_mod.constr_length == 0) {
       beam_mod.constr_length = 1;
       constr[0].X = 0;
       constr[0].u = 0;
       constr[0].v = 0;
       constr[0].c = 0;
     }
     // Сортировать нагрузки и закрепления по координатам
     if (beam_mod.loads_length > 1) {
       qsortk((char*)loads, beam_mod.loads_length, sizeof(Load), (fptr)cmp_Load);
     }
	 if (beam_mod.constr_length > 1) {
       qsortk((char*)constr, beam_mod.constr_length, sizeof(Constraint), (fptr)cmp_Constraint);
     }


     beam_mod.MultiSupportBeam_(MaxLength);

     rc = beam_mod.calculate(EI, N_, q_, m_, kp, loads, constr);
     if (rc>0) {
        if (rc == beam_mod.ErrSingular) {
			i = ApplicationMessageBox("Для заданного распределения продольных усилий коэффициент критической нагрузки потери устойчивости по Эйлеру больше или равен 1.0", " ",
                   MB_OK | MB_ICONERROR);
        }
        else {
			i = Application->MessageBox(("При расчете балки произошла программная ошибка с кодом "+IntToStr(rc)).c_str(), L" ",
                   MB_OK | MB_ICONERROR);
        }
        return;
     }
     // Восстановить исходные данные
     rc = Get_beam_data(k_beam);
     // Получить результаты на балке
     GetResult(10*CalcLengthBeam()/MaxLength);


	 ListBox1Click(Sender);

     PageControl1->ActivePage=TabSheetResult;

	 double Lbeam = CalcLengthBeam();
     printExtremum(beam_mod);

     printResult(0);
     printResult(Lbeam/2 - 1);
     printResult(Lbeam/2);
     printResult(Lbeam/2 + 1);
     printResult(Lbeam);

     for (int i=0; i < beam_mod.constr_force_length; i++) {
       sprintf(stroka,"   координата %g: Rv=%g, Rc=%g ", beam_mod.ConstrForces[i].X,
               beam_mod.ConstrForces[i].v, beam_mod.ConstrForces[i].c );
       InfMessage((AnsiString)stroka);
     }
}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::BitBtn_NewClick(TObject *Sender)
{
     int i;

     n_fun = 0;
     n_result = 0;

     // Собрать балку

	 beam_mod.EI_length = 0;
     beam_mod.q_length = 0;
     beam_mod.N_length = 0;
     beam_mod.m_length = 0;
	 beam_mod.kp_length = 0;
     beam_mod.loads_length = 0;
     beam_mod.constr_length = 0;
     type_region = -1;
     if (index_portion!=0) {
         delete(EI);
         delete(q_);
         delete(N_);
         delete(m_);
         delete(kp);
         delete(loads);
         delete(constr);
     }
     flag_rigid = true;
     index_portion = PORTION_REGION;
     EI = new BeamRegion[PORTION_REGION];  // Регионы поперечной жесткости
     q_ = new BeamRegion[PORTION_REGION];  // Регионы погонной поперечной нагрузки
     N_ = new BeamRegion[PORTION_REGION];  // Регионы эпюры продольных сил
     m_ = new BeamRegion[PORTION_REGION]; // Регионы погонного момента
     kp = new BeamRegion[PORTION_REGION];  // Регионы погонной жесткости упругого основания
     loads = new Load[PORTION_REGION];       // Точки задания сосредоточенных нагрузок
     constr = new Constraint[PORTION_REGION]; // Точки задания связей (опор)
     Edit_X0Constr->Text = 0;
	 CheckBox_Tx->Checked = false;
	 CheckBox_Tz->Checked = false;
	 CheckBox_Ry->Checked = false;
     Edit_X0Load->Text = 0;
	 Edit_Fx->Text = 0;
	 Edit_Fz->Text = 0;
	 Edit_My->Text = 0;
     Edit_x0->Text = 0;
     Edit_Len->Text = 0;
     Edit_p1->Text = 0;
     Edit_p2->Text = 0;

}
//---------------------------------------------------------------------------
// Прочитать данные из табицы и сформировать регионы
int __fastcall TMultiSupportForm::LoadDataFromGrid_param()
{
   int i, k, rc;
   double F0, M0;
   double y0, len, q1, q2;
   char stroka[240];
   double x10;

   if (type_region >=0) {
    k = StringGrid_param->RowCount - 1;
    *A_length = 0;
    if (type_region <= 4) {
      x10 = 0;
      for (i=0; i<k; i++) {
       rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][i+1], &y0);
       if (rc>0) return rc;
       rc = String_double_plus(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][i+1], &len);
       if (rc>0) return rc;
       rc = String_double(StringGrid_param->Cells[3][0], StringGrid_param->Cells[3][i+1], &q1);
       if (rc>0) return rc;
	   rc = String_double(StringGrid_param->Cells[4][0], StringGrid_param->Cells[4][i+1], &q2);
       if (rc>0) return rc;
       Arbit[i].X0 = y0;
       Arbit[i].Len = len;
       Arbit[i].begValue = q1;
       Arbit[i].endValue = q2;
       x10 = y0 + len;
     }
    }
	else {
      if (type_region == 5) {
        for (i=0; i<k; i++) {
          rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][i+1], &y0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][i+1], &F0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[3][0], StringGrid_param->Cells[3][i+1], &M0);
          if (rc>0) return rc;
          loads[i].X = y0;
          loads[i].u = 0;
          loads[i].v = F0;
          loads[i].c = M0;
        }
      }
      if (type_region == 6) {  // Закрепления
        for (i=0; i<k; i++) {
          rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][i+1], &y0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][i+1], &F0);
		  if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[3][0], StringGrid_param->Cells[3][i+1], &M0);
          if (rc>0) return rc;
          constr[i].X = y0;
          constr[i].u = 0;
          constr[i].v = F0;
          constr[i].c = M0;
        }
      }
	}
    *A_length = k;
   }
   return 0;
}
//---------------------------------------------------------------------------
// Прочитать данные из табицы и заполнить соответствующие поля
int __fastcall TMultiSupportForm::LoadDataFromGrid_ToText()
{
   int i, k, rc;
   double F0, M0;
   double y0, len, q1, q2;
   char stroka[240];
   double x10;

  if (type_region >=0) {
    i = SelectRow-1;
    if (type_region <= 4) {
       rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][i+1], &y0);
       if (rc>0) return rc;
	   rc = String_double_plus(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][i+1], &len);
       if (rc>0) return rc;
       rc = String_double(StringGrid_param->Cells[3][0], StringGrid_param->Cells[3][i+1], &q1);
       if (rc>0) return rc;
       rc = String_double(StringGrid_param->Cells[4][0], StringGrid_param->Cells[4][i+1], &q2);
       if (rc>0) return rc;
       Edit_x0->Text = y0;
       Edit_Len->Text = len;
       Edit_p1->Text = q1;
	   Edit_p2->Text = q2;
       if (q1 != q2) {
         CheckBox_Linear->Checked = true;
       }
       else {
         CheckBox_Linear->Checked = false;
       }
    }
    else {
      if (type_region == 5) {
          rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][i+1], &y0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][i+1], &F0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[3][0], StringGrid_param->Cells[3][i+1], &M0);
          if (rc>0) return rc;
          Edit_X0Load->Text = y0;
		  Edit_Fz->Text = F0;
		  Edit_My->Text = M0;
	  }
	  if (type_region == 6) {  // Закрепления
          rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[1][i+1], &y0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[2][0], StringGrid_param->Cells[2][i+1], &F0);
          if (rc>0) return rc;
          rc = String_double(StringGrid_param->Cells[3][0], StringGrid_param->Cells[3][i+1], &M0);
          if (rc>0) return rc;
          Edit_X0Constr->Text = y0;
	  }
	}
  }
  return 0;
}
//-----------------------------------------------------------------------------
void __fastcall TMultiSupportForm::LoadDataToGrid_param(int type_param) {
   BeamRegion  *Arbit;
   int i;
   int length;
   if (type_param >=0 && type_param <= 4) {
     switch (type_param) {
     case 0:
       Arbit = EI;
       length = beam_mod.EI_length;
     break;
     case 1:
       Arbit = q_;
       length = beam_mod.q_length;
     break;
     case 2:
	   Arbit = m_;
       length = beam_mod.m_length;
     break;
     case 3:
       Arbit = kp;
       length = beam_mod.kp_length;
     break;
     case 4:
       Arbit = N_;
	   length = beam_mod.N_length;
     break;
     }
     for (i=0; i<length; i++) {
        BeamRegionToGrid_param(Arbit[i], -1);
     }
   }
   else {
      if (type_param == 5) {
        for (i=0; i<beam_mod.loads_length; i++) {
         LoadToGrid_param(loads[i], -1);
        }
      }
      if (type_param == 6) {  // Закрепления
        for (i=0; i<beam_mod.constr_length; i++) {
          ConstraintToGrid_param(constr[i], -1);
        }
      }
   }
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::printExtremum (MultiSupportBeam oneFE){
    char stroka[240];

    sprintf(stroka,"V max: Значение = %g при X = %g", oneFE.vmax.value, oneFE.vmax.XCoord);
    InfMessage((AnsiString)stroka);
    sprintf(stroka,"V min: Значение = %g при X = %g", oneFE.vmin.value, oneFE.vmin.XCoord);
    InfMessage((AnsiString)stroka);
	sprintf(stroka,"C max: Значение = %g при X = %g", oneFE.cmax.value, oneFE.cmax.XCoord);
    InfMessage((AnsiString)stroka);
    sprintf(stroka,"C min: Значение = %g при X = %g", oneFE.cmin.value, oneFE.cmin.XCoord);
    InfMessage((AnsiString)stroka);
    sprintf(stroka,"Q max: Значение = %g при X = %g", oneFE.Qmax.value, oneFE.Qmax.XCoord);
    InfMessage((AnsiString)stroka);
    sprintf(stroka,"Q min: Значение = %g при X = %g", oneFE.Qmin.value, oneFE.Qmin.XCoord);
    InfMessage((AnsiString)stroka);
    sprintf(stroka,"M max: Значение = %g при X = %g", oneFE.Mmax.value, oneFE.Mmax.XCoord);
    InfMessage((AnsiString)stroka);
    sprintf(stroka,"M min: Значение = %g при X = %g", oneFE.Mmin.value, oneFE.Mmin.XCoord);
    InfMessage((AnsiString)stroka);

}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::GetResult(int n_break){
    int i, rc, k, m, lres;
    double Lbeam, X;
    float del;

	m = 0;
    Lbeam = CalcLengthBeam();
    lres = beam_mod.EI_length*n_break + beam_mod.kp_length*4 + beam_mod.loads_length*2 + beam_mod.constr_length*2;
    if (x_result!=NULL) {
      FREEVEC_(x_result);
    }
    ALLOCVEC_(x_result, lres+10, float);

    for (i=0; i<beam_mod.EI_length; i++) {
	  del = EI[i].Len/n_break;
      for (k=0; k<n_break; k++) {
        x_result[m] = EI[i].X0 + del*k;
        m++;
      }
    }
    for (i=0; i<beam_mod.kp_length; i++) {
      x_result[m] = kp[i].X0;
      m++;
      x_result[m] = kp[i].X0 + Lbeam/10000;
      m++;
      x_result[m] = kp[i].X0 + kp[i].Len;
      m++;
      x_result[m] = kp[i].X0 + kp[i].Len + Lbeam/10000;
      m++;
    }
    for (i=0; i<beam_mod.loads_length; i++) {
        x_result[m] = loads[i].X;
        m++;
        x_result[m] = loads[i].X + Lbeam/10000;
		m++;
    }
    for (i=0; i<beam_mod.constr_length; i++) {
        x_result[m] = constr[i].X;
        m++;
        x_result[m] = constr[i].X + Lbeam/10000;
        m++;
    }
    qsortk((char*)x_result, m, sizeof(float), (fptr)cmpf);
	k = 0;
    for (i=1; i<m; i++) {
      if (x_result[i] > Lbeam)
         break;
      if (x_result[k] != x_result[i]) {
         x_result[k+1] = x_result[i];
         k++;
      }
    }
    k++;
    // k - число точек
    if (matr_result!=NULL) {
      FREEMAT_(matr_result);
    }
	//ALLOCMAT_F_(matr_result, k, 5);
	matr_result = (float**)almat_f(k, 5, &rc);
	if (rc>0) {
	   rc = Application->MessageBox(L"Error almat_f", L" ", MB_OK | MB_ICONERROR);
	   return;
	}

    for (i=0; i<6; i++) {
      Max_Value[i] = -1e20;
      Min_Value[i] = 1e20;
    }

    for (i=0; i<k; i++) {
      X = x_result[i];
      matr_result[i][0] = beam_mod.getResults(X).Q;
	  matr_result[i][1] = beam_mod.getResults(X).Mz;
      matr_result[i][2] = beam_mod.getResults(X).v;
      matr_result[i][3] = beam_mod.getResults(X).c;
      matr_result[i][4] = beam_mod.getResults(X).R;
      if (Max_Value[4] < matr_result[i][4]) {
         Max_Value[4] = matr_result[i][4];
         Max_X[4] = X;
      }
      if (Min_Value[4] > matr_result[i][4]) {
         Min_Value[4] = matr_result[i][4];
         Min_X[4] = X;
      }
    }
    n_result = k;

    Max_Value[0] = beam_mod.Qmax.value;
    Max_X[0] = beam_mod.Qmax.XCoord;
    Min_Value[0] = beam_mod.Qmin.value;
    Min_X[0] = beam_mod.Qmin.XCoord;

	Max_Value[1] = beam_mod.Mmax.value;
    Max_X[1] = beam_mod.Mmax.XCoord;
    Min_Value[1] = beam_mod.Mmin.value;
    Min_X[1] = beam_mod.Mmin.XCoord;

    Max_Value[2] = beam_mod.vmax.value;
    Max_X[2] = beam_mod.vmax.XCoord;
    Min_Value[2] = beam_mod.vmin.value;
    Min_X[2] = beam_mod.vmin.XCoord;

    Max_Value[3] = beam_mod.cmax.value;
    Max_X[3] = beam_mod.cmax.XCoord;
    Min_Value[3] = beam_mod.cmin.value;
    Min_X[3] = beam_mod.cmin.XCoord;
    /*
    Max_Value[4] = beam_mod.cmax.value;
    Max_X[4] = beam_mod.cmax.XCoord;
    Min_Value[4] = beam_mod.cmin.value;
    Min_X[4] = beam_mod.cmin.XCoord;
    */


}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::printResult(double X){
    char stroka[240];
     sprintf(stroka,"Q=%g, M=%g, R=%g, v=%g, c=%g", (beam_mod.getResults(X)).Q, (beam_mod.getResults(X)).Mz,
            (beam_mod.getResults(X)).R, (beam_mod.getResults(X)).v, (beam_mod.getResults(X)).c);
     InfMessage("Значения в точке "+FloatToStr(X)+": "+(AnsiString)stroka);
}
// Запись данных о балке
int __fastcall TMultiSupportForm::SaveBeamData(FILE* BD_file) {

   FData * data1;
   int param[16];
   int i, rc;

   param[0] = n_beam;

   data1 = BD_WOpenData(BD_file, "MultSuppBeam", 0, param, &rc);
   if (rc>0) {
     PrinCodOpenData(rc);
     return rc;
   }
   for (i=0; i<param[0]; i++) {
      rc = Write_beam_data(i, data1);
      if (rc>0) {
        BD_CloseData(data1);
        return rc;
      }
   }
   BD_CloseData(data1);
   return 0;
}
//---------------------------------------------------------------------------------
// Чтение данных о балке
int __fastcall TMultiSupportForm::OpenBeamData(FILE* BD_file) {

   FData * data1;
   int param[16];
   int i, rc;

   n_beam = 0;
   data1 = BD_ROpenData(BD_file, "MultSuppBeam", 0, param, &rc);
   if (rc == 0) {
      // переписать балки в память
      for (i=0; i<param[0]; i++) {
		 rc = Read_beam_data(i,data1);
         if (rc>0) {
           BD_CloseData(data1);
           return rc;
         }
      }
      n_beam = param[0];
   }
   BD_CloseData(data1);
   return rc;
}
//---------------------------------------------------------------------------
// Размещение депозитария регионов
void __fastcall TMultiSupportForm::Alloc_region(int n_reg) {
     EI_v = (BeamRegion*)calloc(n_reg, sizeof(BeamRegion));  // Регионы поперечной жесткости
	 q_v = (BeamRegion*)calloc(n_reg, sizeof(BeamRegion));  // Регионы погонной поперечной нагрузки
     N_v = (BeamRegion*)calloc(n_reg, sizeof(BeamRegion));  // Регионы эпюры продольных сил
     m_v = (BeamRegion*)calloc(n_reg, sizeof(BeamRegion)); // Регионы погонного момента
     kp_v = (BeamRegion*)calloc(n_reg, sizeof(BeamRegion));  // Регионы погонной жесткости упругого основания
     loads_v = (Load*)calloc(n_reg, sizeof(Load));       // Точки задания сосредоточенных нагрузок
	 constr_v = (Constraint*)calloc(n_reg, sizeof(Constraint)); // Точки задания связей (опор)

	 index_place_v = (int*)calloc(n_reg, sizeof(int));
	 dist_v = (double*)calloc(n_reg, sizeof(double));

}
//---------------------------------------------------------------------------
// Повторное размещение депозитария регионов
void __fastcall TMultiSupportForm::ReAlloc_region(int n_reg) {
	 realloc(EI_v, n_reg*sizeof(BeamRegion));  // Регионы поперечной жесткости
     realloc(q_v, n_reg*sizeof(BeamRegion));  // Регионы погонной поперечной нагрузки
	 realloc(N_v, n_reg*sizeof(BeamRegion));  // Регионы эпюры продольных сил
     realloc(m_v, n_reg*sizeof(BeamRegion)); // Регионы погонного момента
     realloc(kp_v, n_reg*sizeof(BeamRegion));  // Регионы погонной жесткости упругого основания
	 realloc(loads_v, n_reg*sizeof(Load));       // Точки задания сосредоточенных нагрузок
	 realloc(constr_v, n_reg*sizeof(Constraint)); // Точки задания связей (опор)

     realloc(index_place_v, n_reg*sizeof(int));
	 realloc(dist_v, n_reg*sizeof(double));

}
//---------------------------------------------------------------------------
// Освобождение депозитария регионов
void __fastcall TMultiSupportForm::Free_region() {
     free(EI_v);
     free(q_v);
     free(N_v);
     free(m_v);
     free(kp_v);
     free(loads_v);
	 free(constr_v);

	 free(index_place_v);
	 free(dist_v);

}
//---------------------------------------------------------------------------
// Пеоместить регион в депозитарий
// Проверка и сдвиг региона
void __fastcall TMultiSupportForm::CheckRegion_at_Put(BeamRegion *P_v, int iP, int P_length, int k, int nP) {
   int i, shift;

   if (iP + P_length > index_beam[k][0]) {
	  shift = iP + P_length - index_beam[k][0];
	  if (index_beam[n_beam-1][0] + shift >Len_v)
		 ReAlloc_region(PORTION_REGION);
	  // Сдвиг
      for (i = index_beam[n_beam-1][0]-1; i >= index_beam[k][0]; i--) {
        memcpy(P_v+i+shift, P_v+i, sizeof(BeamRegion));
      }
   }
}
//---------------------------------------------------------------------------
// Проверка и сдвиг нагрузок
void __fastcall TMultiSupportForm::CheckLoad_at_Put(Load *P_v, int iP, int P_length, int k, int nP) {
   int i, shift;

   if (iP + P_length > index_beam[k][0]) {
      shift = iP + P_length - index_beam[k][0];
      if (index_beam[n_beam-1][0] + shift >Len_v)
         ReAlloc_region(PORTION_REGION);
      // Сдвиг
      for (i = index_beam[n_beam-1][0]-1; i >= index_beam[k][0]; i--) {
        memcpy(P_v+i+shift, P_v+i, sizeof(Load));
      }
   }
}
//---------------------------------------------------------------------------
// Проверка и сдвиг закреплений
void __fastcall TMultiSupportForm::CheckConstraint_at_Put(Constraint *P_v, int iP, int P_length, int k, int nP) {
   int i, shift;

   if (iP + P_length > index_beam[k][0]) {
      shift = iP + P_length - index_beam[k][0];
      if (index_beam[n_beam-1][0] + shift >Len_v)
         ReAlloc_region(PORTION_REGION);
      // Сдвиг
      for (i = index_beam[n_beam-1][0]-1; i >= index_beam[k][0]; i--) {
        memcpy(P_v+i+shift, P_v+i, sizeof(Constraint));
      }
   }
}
//---------------------------------------------------------------------------
// Взять регион из депозитария
int __fastcall TMultiSupportForm::Get_beam_data(int k) {
   int iEI, iq_, im_, ikp, iN_, ild, icn;
   if (k > n_beam-1)
      return 1;
   if (k==0) {
     iEI = 0;
     iq_ = 0;
     im_ = 0;
     ikp = 0;
     iN_ = 0;
	 ild = 0;
     icn = 0;
   }
   else {
     iEI = index_beam[k-1][0];
	 iq_ = index_beam[k-1][1];
     im_ = index_beam[k-1][2];
     ikp = index_beam[k-1][3];
     iN_ = index_beam[k-1][4];
     ild = index_beam[k-1][5];
     icn = index_beam[k-1][6];
   }
   beam_mod.EI_length = index_beam[k][0] - iEI;
   beam_mod.q_length = index_beam[k][1] - iq_;
   beam_mod.m_length = index_beam[k][2] - im_;
   beam_mod.kp_length = index_beam[k][3] - ikp;
   beam_mod.N_length = index_beam[k][4] - iN_;
   beam_mod.loads_length = index_beam[k][5] - ild;
   beam_mod.constr_length = index_beam[k][6] - icn;

   memcpy(EI, EI_v+iEI, sizeof(BeamRegion)*beam_mod.EI_length);
   memcpy(q_, q_v+iq_, sizeof(BeamRegion)*beam_mod.q_length);

   memcpy(index_place, index_place_v+iq_, sizeof(int)*beam_mod.q_length);
   memcpy(dist, dist_v+iq_, sizeof(double)*beam_mod.q_length);

   memcpy(m_, m_v+im_, sizeof(BeamRegion)*beam_mod.m_length);
   memcpy(kp, kp_v+ikp, sizeof(BeamRegion)*beam_mod.kp_length);
   memcpy(N_, N_v+iN_, sizeof(BeamRegion)*beam_mod.N_length);
   memcpy(loads, loads_v+ild, sizeof(Load)*beam_mod.loads_length);
   memcpy(constr, constr_v+icn, sizeof(Constraint)*beam_mod.constr_length);
   memcpy(NameBeam, NameBeam_v+k*80, 80);
   return 0;
}
//---------------------------------------------------------------------------
// Запись k-го региона
int __fastcall TMultiSupportForm::Write_beam_data(int k, FData * data1) {
   int iEI, iq_, im_, iN_, ikp, ild, icn;
   int lEI, lq_, lm_, lN_, lkp, lld, lcn;
   int Len_reg[7];
   int rc;

   if (k==0) {
     iEI = 0;
     iq_ = 0;
     im_ = 0;
     ikp = 0;
     iN_ = 0;
     ild = 0;
     icn = 0;
   }
   else {
     iEI = index_beam[k-1][0];
     iq_ = index_beam[k-1][1];
     im_ = index_beam[k-1][2];
     ikp = index_beam[k-1][3];
     iN_ = index_beam[k-1][4];
     ild = index_beam[k-1][5];
     icn = index_beam[k-1][6];
   }

   lEI = index_beam[k][0] - iEI;
   lq_ = index_beam[k][1] - iq_;
   lm_ = index_beam[k][2] - im_;
   lkp = index_beam[k][3] - ikp;
   lN_ = index_beam[k][4] - iN_;
   lld = index_beam[k][5] - ild;
   lcn = index_beam[k][6] - icn;
   Len_reg[0] = lEI;
   Len_reg[1] = lq_;
   Len_reg[2] = lm_;
   Len_reg[3] = lkp;
   Len_reg[4] = lN_;
   Len_reg[5] = lld;
   Len_reg[6] = lcn;

   rc = BD_WriteData((char *)NameBeam_v+k*80, 80, 1, data1);
   if (rc!=1) return 1;
   rc = BD_WriteData((char *)Len_reg, sizeof(int), 7, data1);
   if (rc!=7) return 1;
   rc = BD_WriteData((char *)EI_v+iEI, sizeof(BeamRegion), lEI, data1);
   if (rc!=lEI) return 1;
   rc = BD_WriteData((char *)q_v+iq_, sizeof(BeamRegion), lq_, data1);
   if (rc!=lq_) return 1;
   rc = BD_WriteData((char *)m_v+im_, sizeof(BeamRegion), lm_, data1);
   if (rc!=lm_) return 1;
   rc = BD_WriteData((char *)kp_v+ikp, sizeof(BeamRegion), lkp, data1);
   if (rc!=lkp) return 1;
   rc = BD_WriteData((char *)N_v+iN_, sizeof(BeamRegion), lN_, data1);
   if (rc!=lN_) return 1;
   rc = BD_WriteData((char *)loads_v+ild, sizeof(Load), lld, data1);
   if (rc!=lld) return 1;
   rc = BD_WriteData((char *)constr_v+icn, sizeof(Constraint), lcn, data1);
   if (rc!=lcn) return 1;

   return 0;
}
//---------------------------------------------------------------------------
// Чтение k-го региона
int __fastcall TMultiSupportForm::Read_beam_data(int k, FData * data1) {
   int iEI, iq_, im_, ikp, iN_, ild, icn;
   int lEI, lq_, lm_, lkp, lN_, lld, lcn;
   int rc;
   int Len_reg[7];

   if (k==0) {
     iEI = 0;
     iq_ = 0;
     im_ = 0;
     ikp = 0;
     iN_ = 0;
     ild = 0;
     icn = 0;
   }
   else {
     iEI = index_beam[k-1][0];
     iq_ = index_beam[k-1][1];
     im_ = index_beam[k-1][2];
     ikp = index_beam[k-1][3];
     iN_ = index_beam[k-1][4];
     ild = index_beam[k-1][5];
	 icn = index_beam[k-1][6];
   }
   rc = BD_ReadData((char *)NameBeam_v + k*80, 80, 1, data1);
   if (rc!=1) return 1;
   rc = BD_ReadData((char *)Len_reg, sizeof(int), 7, data1);
   if (rc!=7) return 1;
   lEI = Len_reg[0];
   lq_ = Len_reg[1];
   lm_ = Len_reg[2];
   lkp = Len_reg[3];
   lN_ = Len_reg[4];
   lld = Len_reg[5];
   lcn = Len_reg[6];
   index_beam[k][0] = index_beam[k-1][0] + lEI;
   index_beam[k][1] = index_beam[k-1][1] + lq_;
   index_beam[k][2] = index_beam[k-1][2] + lm_;
   index_beam[k][3] = index_beam[k-1][3] + lkp;
   index_beam[k][4] = index_beam[k-1][4] + lN_;
   index_beam[k][5] = index_beam[k-1][5] + lld;
   index_beam[k][6] = index_beam[k-1][6] + lcn;
   rc = BD_ReadData((char *)EI_v+iEI, sizeof(BeamRegion), lEI, data1);
   if (rc!=lEI) return 1;
   rc = BD_ReadData((char *)q_v+iq_, sizeof(BeamRegion), lq_, data1);
   if (rc!=lq_) return 1;
   rc = BD_ReadData((char *)m_v+im_, sizeof(BeamRegion), lm_, data1);
   if (rc!=lm_) return 1;
   rc = BD_ReadData((char *)kp_v+ikp, sizeof(BeamRegion), lkp, data1);
   if (rc!=lkp) return 1;
   rc = BD_ReadData((char *)N_v+iN_, sizeof(BeamRegion), lN_, data1);
   if (rc!=lN_) return 1;
   rc = BD_ReadData((char *)loads_v+ild, sizeof(Load), lld, data1);
   if (rc!=lld) return 1;
   rc = BD_ReadData((char *)constr_v+icn, sizeof(Constraint), lcn, data1);
   if (rc!=lcn) return 1;

    return 0;
}
//-------------------------------------------------------------------



void __fastcall TMultiSupportForm::BitBtnDeleteClick(TObject *Sender)
{
    int i, k1, k0, j0, j;
    double x00, x0, x1, p1, p2, Len;
    char stroka[240];
    int rc;

    n_fun = 0;
    n_result = 0;

    k1 = SelectRow;
    k0 = StringGrid_param->RowCount;
	//if (ComboBox_type->ItemIndex <=4) {
	//  j0 = 5;
	//}
	//else {
	//  j0 = 4;
	//}
	j0 = 4;
    if (k1>0) {
        for (i = k1+1; i<k0; i++) {
          for (j=1; j<j0; j++) {
			StringGrid_param->Cells[j][i-1] = StringGrid_param->Cells[j][i];
          }
        }
        StringGrid_param->RowCount--;
    }
	*A_length = StringGrid_param->RowCount-1;
	rc = LoadDataFromGrid_param();
	if (rc>0) return;

    Draw_beam();
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::StringGrid_paramSelectCell(
      TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
      int rc;
      SelectRow = ARow;
      if (ARow>0) {
      // Поместить данные строки таблицы в поля
         rc = LoadDataFromGrid_ToText();
      }   
}
//---------------------------------------------------------------------------
void __fastcall TMultiSupportForm::Draw_beam() {
  float scale, scale_force, scale_kp, scale_q, scale_m, scale_N, Value;
  int i;
  double Width, Height;
  double L_beam, H_beam, H_beam1, H_beam2, B_beam, I_beam;
  TPoint points[10];
  TPoint vert[13];
  double zero_px, zero_py;


// Определить масштаб для рисования балки
  if (flag_image) {
    Width = Image1->Width;
    Height = Image1->Height;
  }
  else {
    Width = Page_Width;
    Height = Page_Height;
  }

  L_beam = CalcLengthBeam();
  if (L_beam==0)
    return;

  H_beam = L_beam/30;
  I_beam = 0;
  for (i=0; i<beam_mod.EI_length; i++) {
    I_beam = MAX(I_beam, EI[i].begValue);
    I_beam = MAX(I_beam, EI[i].endValue);
  }
  //B_beam = 12*I_beam/(pow(H_beam, 3.0));
  B_beam = 12*I_beam/(pow(H_beam, 2.0));
  scale = (Width - 60)/L_beam;

  //---------------------------------------------------
  Value = 0;
  for (i=0; i<beam_mod.loads_length; i++) {
     Value = MAX(Value, (ABS(loads[i].v)));
  }
  if (Value!=0)
     scale_force = (Height - 30)/(2*Value);
  else
     scale_force = 0;
  //---------------------------------------------------
  Value = 0;
  for (i=0; i<beam_mod.q_length; i++) {
     Value = MAX(Value, (ABS(q_[i].begValue)));
     Value = MAX(Value, (ABS(q_[i].endValue)));
  }
  if (Value!=0)
     scale_q = (Height - 30)/(4*Value);
  else
     scale_q = 0;
  //---------------------------------------------------
  Value = 0;
  for (i=0; i<beam_mod.m_length; i++) {
     Value = MAX(Value, (ABS(m_[i].begValue)));
     Value = MAX(Value, (ABS(m_[i].endValue)));
  }
  if (Value!=0)
     scale_m = (Height - 30)/(5*Value);
  else
     scale_m = 0;
  //---------------------------------------------------
  Value = 0;
  for (i=0; i<beam_mod.kp_length; i++) {
     Value = MAX(Value, (ABS(kp[i].begValue)));
     Value = MAX(Value, (ABS(kp[i].endValue)));
  }
  if (Value!=0)
     scale_kp = (Height - 30)/(9*Value);
  else
     scale_kp = 0;
  //---------------------------------------------------
  Value = 0;
  for (i=0; i<beam_mod.N_length; i++) {
     Value = MAX(Value, (ABS(N_[i].begValue)));
     Value = MAX(Value, (ABS(N_[i].endValue)));
  }
  if (Value!=0)
     scale_N = (Height - 30)/(7*Value);
  else
     scale_N = 0;

  TRect NewRect = Rect(0, 0, Width, Height);

  pBrush_Color(Image1, clGray);
  //pBrush_Color(Image1, clBlack);
  pCanvas_FillRect(Image1, NewRect);
  zero_px = 30;
  zero_py = Height/2;
  // Рисование балки
  pBrush_Color(Image1, clGreen);
  pPen_Color(Image1, clLime);
  for (i=0; i<beam_mod.EI_length; i++) {
    H_beam1 = sqrt(12*EI[i].begValue/B_beam);
    H_beam2 = sqrt(12*EI[i].endValue/B_beam);
    //H_beam1 = pow(12*EI[i].begValue/B_beam, 1/3.0);
    //H_beam2 = pow(12*EI[i].endValue/B_beam, 1/3.0);
    points[0] = Point(zero_px+EI[i].X0*scale, zero_py-H_beam1*scale/2);
    points[1] = Point(points[0].x, zero_py+H_beam1*scale/2);
    points[2] = Point(points[0].x+EI[i].Len*scale, zero_py+H_beam2*scale/2);
    points[3] = Point(points[2].x, zero_py-H_beam2*scale/2);
    points[4] = points[0];
    pCanvas_Polygon(Image1, points, 4);
  }
  pPen_Color(Image1, clWhite);
  points[0] = Point(zero_px, zero_py);
  points[1] = Point(points[0].x + L_beam*scale, zero_py);
  pCanvas_Polyline(Image1, points, 1);
  // Рисование эпюры продольных нагрузок
  for (i=0; i<beam_mod.N_length; i++) {
    Draw_N(clNavy, clSkyBlue, N_, zero_px, zero_py, i, scale, scale_N, 40.0);
  }
  // Рисование опор
  for (i=0; i<beam_mod.constr_length; i++) {
    Draw_opora(zero_px, zero_py, i, scale);
  }
  // Рисование сосредоточенных нагрузок
  for (i=0; i<beam_mod.loads_length; i++) {
    Draw_load(zero_px, zero_py, i, scale, scale_force);
  }
  // Рисование распределенных нагрузок
  for (i=0; i<beam_mod.q_length; i++) {
    Draw_q_or_kp("q=",clRed, 1.0, q_, zero_px, zero_py, i, scale, scale_q, 40.0);
  }
  // Рисование распределенных нагрузок
  for (i=0; i<beam_mod.m_length; i++) {
    Draw_q_or_kp("m=",clPurple, 1.0, m_, zero_px, zero_py, i, scale, scale_m, 40.0);
  }
  // Рисование упругого основания
  for (i=0; i<beam_mod.kp_length; i++) {
    Draw_q_or_kp("kp=",clFuchsia, -1.0, kp, zero_px, zero_py, i, scale, scale_kp, 40.0);
  }
}
//-------------------------------------------------------------
#define  CONST_OPORA  21
void __fastcall TMultiSupportForm::Draw_opora(double zero_px, double zero_py, int i, float scale ) {
  TPoint points[10];
  TPoint point_0;

  point_0 = Point(zero_px + constr[i].X*scale, zero_py);
  // Рисование балки
  pBrush_Color(Image1, clLtGray);
  pPen_Color(Image1, clBlue);
  if (constr[i].v!=0 && constr[i].c!=0) {  // заделка
    points[0] = Point(point_0.x, point_0.y - CONST_OPORA);
    points[1] = Point(point_0.x, point_0.y + CONST_OPORA);
    pCanvas_Polyline(Image1, points, 1);
    Shtrih(points, 7.0, -1.0, 1.0);
  }
  if (constr[i].v!=0 && constr[i].c==0) {  // шарнирная опора
    points[0] = Point(point_0.x, point_0.y);
    points[1] = Point(points[0].x + CONST_OPORA*0.5, point_0.y + CONST_OPORA);
    points[2] = Point(points[0].x - CONST_OPORA*0.5, point_0.y + CONST_OPORA);
    points[3] = points[0];
    pCanvas_Polygon(Image1, points, 3);
    Shtrih(points+1, 7.0, -1.0, 1.0);
  }
  if (constr[i].v==0 && constr[i].c!=0) {  //
    points[0] = Point(point_0.x - 5 , point_0.y - CONST_OPORA);
    points[1] = Point(point_0.x - 5 , point_0.y + CONST_OPORA);
    pCanvas_Polyline(Image1, points, 1);
    Shtrih(points, 7.0, -1.0, 1.0);

    points[0] = Point(point_0.x + 5 , zero_py - CONST_OPORA);
    points[1] = Point(point_0.x + 5 , zero_py + CONST_OPORA);
    pCanvas_Polyline(Image1, points, 1);
    Shtrih(points, 7.0, 1.0, 1.0);
  }
  pCanvas_Ellipse(Image1, point_0.x+3, point_0.y+3, point_0.x-3, point_0.y-3);
}
//-------------------------------------------------------------
// Штриховка
void __fastcall TMultiSupportForm::Shtrih(TPoint *points, float s_s, float mx, float my) {
    // points - точки линии
    // s_s - шаг штриховки
    // mx, my: +1 или -1  - множители, определяющие направление штриховки
    float delx, dely;
	int k;
    TPoint vert[2];
    float l_s;

    delx = points[1].x - points[0].x;
    dely = points[1].y - points[0].y;
    l_s = sqrt(delx*delx + dely*dely);

    for (k=0; k < l_s; k += s_s) {
      vert[0] = Point(points[0].x + delx*k/l_s, points[0].y + dely*k/l_s);
      vert[1] = Point(vert[0].x + mx*s_s, vert[0].y +my*s_s);
      pCanvas_Polygon(Image1, vert, 1);
    }
}
//------------------------------------------------------------------------------------------------------
// Рисование сосредоточенных нагрузок
void __fastcall TMultiSupportForm::Draw_load(double zero_px, double zero_py, int i, float scale, float scale_load) {
  TPoint points[10];
  TPoint vert[10];
  TPoint point_0;
  int X1, X2, X3, X4, Y1, Y2, Y3, Y4;

    pPen_Color(Image1, clMaroon);
    pBrush_Color(Image1, clMaroon);
    pBrush_Style(Image1, bsClear);

    point_0 = Point(zero_px + loads[i].X*scale, zero_py);

    if (loads[i].v!=0) {
	  points[0] = point_0;
      points[1] = Point(point_0.x, point_0.y - loads[i].v*scale_load);
      CoorAx.PutArrow(points, 0, MAX_PIC);
      CoorAx.SetArrow();

      pPen_Width(Image1, 1);;
      pCanvas_Polyline(Image1, CoorAx.LArrow, 2);
      pCanvas_Polyline(Image1, CoorAx.Ar, 3);
      pFont_Color(Image1, clWhite);
      pCanvas_TextOut(Image1, points[1].x+2, points[1].y, "Py="+FloatToStr(loads[i].v));
      pBrush_Style(Image1, bsSolid);
    }
    if (loads[i].c!=0) {

      X1 = point_0.x - RadMoment;
      Y1 = point_0.y - RadMoment;
      X2 = point_0.x + RadMoment;
      Y2 = point_0.y + RadMoment;
      X3 = point_0.x;
      Y3 = point_0.y + RadMoment;
      X4 = point_0.x;
      Y4 = point_0.y - RadMoment;
      vert[2] = Point(X1, Y1);
      vert[3] = Point(X2, Y2);
      vert[0] = Point(X3, Y3);
      vert[1] = Point(X4, Y4);
      if (loads[i].c < 0) {
        points[0] = Point(X2, Y2 - 5);
        points[1] = Point(X3, Y3);
	  }
      else {
        points[0] = Point(X2, Y1 + 5);
        points[1] = Point(X4, Y4);
      }
      CoorAx.PutArrow(points, 0, MAX_PIC);
      CoorAx.SetArrow();

      pPen_Width(Image1, 1);;
      pCanvas_Arc(Image1, vert, vert + 2);
      pBrush_Style(Image1, bsSolid);
      pCanvas_Ellipse(Image1, point_0.x - 2, point_0.y - 2, point_0.x + 2, point_0.y + 2);
      pBrush_Color(Image1, clMaroon);
      pCanvas_Polygon(Image1, CoorAx.Ar, 3);
      pCanvas_Ellipse(Image1, point_0.x - 2, point_0.y - 2, point_0.x + 2, point_0.y + 2);
      pFont_Color(Image1, clWhite);
      pBrush_Style(Image1, bsClear);
      pCanvas_TextOut(Image1, points[1].x + 5, points[1].y + 2, "Mz="+FloatToStr(loads[i].c));
      pBrush_Style(Image1, bsSolid);
    }
}
//----------------------------------------------------------------------------------------------------
// Рисование распределенных нагрузок и упругого основания
void __fastcall TMultiSupportForm::Draw_q_or_kp(AnsiString Name, TColor color, float mult, BeamRegion* Ar, double zero_px, double zero_py, int i, float scale, float scale_load, float step) {
  TPoint points[10];
  TPoint vert[10];
  TPoint point_0;
  TPoint point_1;
  TPoint point_d;
  int k, n;
  float del;

    if (Ar[i].begValue==0 && Ar[i].endValue==0)
       return;
    pPen_Color(Image1, color);
    pBrush_Style(Image1, bsClear);

    point_0 = Point(zero_px + Ar[i].X0*scale, zero_py);
    point_1 = Point(point_0.x + Ar[i].Len*scale, zero_py);
    n = ceil(Ar[i].Len*scale/step);

    points[0] = point_0;
    points[1] = Point(point_0.x, point_0.y - mult*Ar[i].begValue*scale_load);
    del = (Ar[i].endValue - Ar[i].begValue)*scale_load;
    for (k=0; k <=n ; k++) {

      vert[0] = Point(point_0.x + k*Ar[i].Len*scale/n, point_0.y);
      vert[1] = Point(vert[0].x, points[1].y - mult*del*k/n);
      if (mult == -1) {  // перевернуть
        point_d = vert[0];
        vert[0] = vert[1];
        vert[1] = point_d;
      }
      CoorAx.PutArrow(vert, 0, MAX_PIC);
      CoorAx.SetArrow();

      pPen_Width(Image1, 1);
      pCanvas_Polyline(Image1, CoorAx.LArrow, 2);
	  pCanvas_Polyline(Image1, CoorAx.Ar, 3);
    }
    if (mult == -1) {
       points[2] = vert[0];
    }
    else
       points[2] = vert[1];
    pCanvas_Polyline(Image1, points+1, 1);
    if (mult == -1) {
      Shtrih(points+1, 10.0, -1.0, 1.0);
    }

    pFont_Color(Image1, clWhite);
    pCanvas_TextOut(Image1, points[1].x+2, points[1].y, Name+FloatToStr(Ar[i].begValue));
    pBrush_Style(Image1, bsSolid);
}
//----------------------------------------------------------------------------------------------------
// Рисование эпюры продольных нагрузок
void __fastcall TMultiSupportForm::Draw_N(TColor colorPen, TColor colorBrush, BeamRegion* Ar, double zero_px, double zero_py, int i, float scale, float scale_load, float step) {
  TPoint vert[10];
  TPoint point_0;
  TPoint point_1;
  int n, k;

    if (Ar[i].begValue==0 && Ar[i].endValue==0)
       return;
    pPen_Color(Image1, colorPen);
    pBrush_Color(Image1, colorBrush);

	point_0 = Point(zero_px + Ar[i].X0*scale, zero_py);
    point_1 = Point(point_0.x + Ar[i].Len*scale, zero_py);

    vert[0] = point_0;
    vert[1] = Point(point_0.x, point_0.y - Ar[i].begValue*scale_load);
    vert[2] = Point(point_0.x + Ar[i].Len*scale, vert[1].y);
    vert[3] = Point(vert[2].x, point_1.y);
    vert[4] = vert[0];
    //pCanvas_Polygon(Image1, vert, 4);
    pCanvas_Polyline(Image1, vert, 4);
    n = ceil(Ar[i].Len*scale/step);
    for (k=1; k<n; k++) {
      vert[2] = Point(point_0.x + k*Ar[i].Len*scale/n, vert[0].y);
      vert[3] = Point(vert[2].x, vert[1].y);
      pCanvas_Polyline(Image1, vert+2, 1);
    }

    pBrush_Style(Image1, bsClear);
    pFont_Color(Image1, clWhite);
    pCanvas_TextOut(Image1, vert[1].x+2, vert[1].y, "N="+FloatToStr(Ar[i].begValue));
    pBrush_Style(Image1, bsSolid);
}
//--------------------------------------------------------------------
void __fastcall TMultiSupportForm::BitBtn_InsertClick(TObject *Sender)
{
    int rc;
    rc = LoadDataFromGrid_param();
    if (rc>0) return;

	Draw_beam();
}
//---------------------------------------------------------------------------

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

void __fastcall TMultiSupportForm::ListBox1Click(TObject *Sender)
{
     int i,j;

     for (i=0, j=0; i<5; i++) {
         if (ListBox1->Selected[i]==true) {
             index_fun[j] = i;
             j++;
         }
     }
     n_fun = j;
     if (n_fun > 0) {
        DrawOut(n_fun, n_result, index_fun);
	 }

}
//---------------------------------------------------------------------------


void __fastcall TMultiSupportForm::BitBtnOutEMFClick(TObject *Sender)
{
      char *ch;
	  char str[240];
      int  i,rc;
      FILE *fp;

      strcpy(str,Data->Variant.c_str());
      for (i=strlen(str)-1; i>=0; i--)
         if (str[i]=='\\') break;
      ch=strchr(str+i+1,(int)'.');
      if (ch==NULL) ch=str+i+1;
      for (i=0; i<100; i++) {
        sprintf(ch,"%.2d.emf",i);
        fp=fopen(str,"rb");
        if (fp==NULL)
          break;
        fclose(fp);
      }
      Chart1->SaveToMetafileEnh(str);
        
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::BitBtnOutGrapClick(TObject *Sender)
{
  //        
}
//---------------------------------------------------------------------------

void __fastcall TMultiSupportForm::BitBtnCancel2Click(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------------


void __fastcall TMultiSupportForm::BitBtn_ReplaceClick(TObject *Sender)
{
   double x00;
   int i, rc;
   double Len;
   
   if (SelectRow<=0) {
	   rc = ApplicationMessageBox("Не выбрана строка таблицы",
                          " ", MB_OK | MB_ICONERROR);
        return;
   }
   InsertToGridFromText(SelectRow);

   *A_length = StringGrid_param->RowCount-1;
   //if (ComboBox_type->ItemIndex<=4) {
	  // Корректировка начал участков
      x00 = 0;
	  for (i=0; i<*A_length; i++) {
        StringGrid_param->Cells[0][i+1] = i+1;
        StringGrid_param->Cells[1][i+1] = x00;
        rc = String_double_zero_plus(StringGrid_param->Cells[1][0], StringGrid_param->Cells[2][i+1], &Len);
        if (rc>0) return;
        x00 += Len;
      }
	  // Проверить суммарную длину
	  //if (ComboBox_type->ItemIndex>0) {
        if (x00 > CalcLengthBeam()) {
		   rc = Application->MessageBox(("Суммарная длина участков "+FloatToStr(x00)+" больше длины балки "+
                                         FloatToStr(CalcLengthBeam())).c_str(),
						  L" ", MB_OK | MB_ICONERROR);
          return;
        }
	  //}
	//}

    rc = LoadDataFromGrid_param();
    if (rc>0) return;

    Draw_beam();
}
//---------------------------------------------------------------------------
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов         */
 /*  сравнение заканчивается, когда последние элементы =0;            */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_Load(Load *elem1, Load *elem2)
{
       if ( elem1->X > elem2->X)
          return 1;
	   if ( elem1->X < elem2->X)
          return -1;
       else
          return 0;
}
 /*-------------------------------------------------------------------*/
 /*  Функция сравнения массивов         */
 /*  сравнение заканчивается, когда последние элементы =0;            */
 /*  Возвращаемое значение :                                          */
 /*         -1   -первый элемент "меньше" второго;                    */
 /*          0   -элементы "равны";                                   */
 /*          1   -первый элемент "больше" второго.                    */
 /*-------------------------------------------------------------------*/
int   cmp_Constraint(Constraint *elem1, Constraint *elem2)
{
       if ( elem1->X > elem2->X)
          return 1;
       if ( elem1->X < elem2->X)
          return -1;
       else
          return 0;
}



void __fastcall TMultiSupportForm::PageControl_ParamChange(TObject *Sender)
{
   int i, k, rc;
   double F0, M0;
   double y0, len, q1, q2;
   char stroka[240];
   double x10;
   int type_region0;

	if (PageControl_Param->ActivePage==TabSheet_ConcentrLoad)
	  type_region0 = 5;
	if (PageControl_Param->ActivePage==TabSheet_LinearLoad)
	  type_region0 = 1;
	if (PageControl_Param->ActivePage==TabSheet_DistrN)
	  type_region0 = 4;
	if (PageControl_Param->ActivePage==TabSheet_Constraint)
	  type_region0 = 6;


	  Label_x0->Visible = true;
	  Edit_x0->Visible = true;
      Edit_x0->Text = 0;
	  CheckBox_Linear->Enabled=true;
   // Прочитать данные из таблицы
   rc = LoadDataFromGrid_param();
   if (rc>0) return;

   if (type_region != type_region0) {
	  StringGrid_param->RowCount = 1;
	  // Загрузка данных участков нового типа в таблицу
	  //LoadDataToGrid_param(ComboBox_type->ItemIndex);
	  LoadDataToGrid_param(1);

	  Edit_x0->Text = 0;
	  Edit_Len->Text = 0;
	  Edit_p1->Text = 0;
	  Edit_p2->Text = 0;
   }
   type_region = type_region0;
   if (type_region >=0 && type_region <= 5) {
	 StringGrid_param->ColCount = 5;
     StringGrid_param->DefaultColWidth = 85;
	 StringGrid_param->Cells[0][0] = " Номер участка";
	 StringGrid_param->Cells[1][0] = " Координата, м";
	 StringGrid_param->Cells[2][0] = " Длина, м ";
     switch (type_region) {
	 case 0:
	   StringGrid_param->Cells[3][0] = " EI (1)";
	   StringGrid_param->Cells[4][0] = " EI (2)";
	   Arbit = EI;
	   A_length = &beam_mod.EI_length;
	 break;
	 case 1:
       StringGrid_param->Cells[3][0] = " q (1)";
	   StringGrid_param->Cells[4][0] = " q (2)";
       Arbit = q_;
       A_length = &beam_mod.q_length;
     break;
     case 2:
       StringGrid_param->Cells[3][0] = " m (1)";
       StringGrid_param->Cells[4][0] = " m (2)";
       Arbit = m_;
	   A_length = &beam_mod.m_length;
     break;
     case 3:
       StringGrid_param->Cells[3][0] = " kp (1)";
	   StringGrid_param->Cells[4][0] = " kp (2)";
	   Arbit = kp;
       A_length = &beam_mod.kp_length;
     break;
	 case 4:
	   StringGrid_param->Cells[3][0] = " N (1)";
	   StringGrid_param->Cells[4][0] = " N (2)";
	   Arbit = N_;
	   A_length = &beam_mod.N_length;
	 break;
	 case 5:
	   StringGrid_param->Cells[0][0] = "Номер нагрузки";
	   StringGrid_param->Cells[1][0] = " Координата, м";
	   StringGrid_param->Cells[2][0] = " Сила Fx (кН)";
	   StringGrid_param->Cells[3][0] = " Сила Fz (кН)";
	   StringGrid_param->Cells[4][0] = " Момент My (кН*м)";
	   A_length = &beam_mod.loads_length;
	 break;
	 }
   }
   else {
	 StringGrid_param->ColCount = 5;
	 StringGrid_param->DefaultColWidth = 100;
	   StringGrid_param->Cells[0][0] = " Номер опоры";
	   StringGrid_param->Cells[1][0] = " Координата, м";
	   StringGrid_param->Cells[2][0] = " Жесткость V";
	   StringGrid_param->Cells[3][0] = " Жесткость Fi";
	   A_length = &beam_mod.constr_length;
   }
   Draw_beam();

}
//---------------------------------------------------------------------------

