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

#ifndef MultiSupportBeamH
#define MultiSupportBeamH

#define L1000   1000  // множитель, приводящий м -> мм, и кН -> Н
#define F1000   1000   // множитель, приводящий м -> мм, и кН -> Н

//---------------------------------------------------------------------------
class BeamRegion {

        private:
        public:
        double X0;
        /**
         * Длина региона
         */
        double Len;
        /**
         * Значение физической величины в начале региона (при минимальном
         * значении координаты X балки).
         */
        double begValue;
        /**
         * Значение физической величины в конце региона (при максимальном
         * значении координаты X балки).
         */
        double endValue;
		// Конструктор по умолчанию
        BeamRegion();
        //void BeamRegion_a(double len);
        //void BeamRegion_b(BeamRegion *new_region, BeamRegion base, double x0, double len);
        double valueAt(double x);

};
//---------------------------------------------------------------------------------------------
class BeamResults {
        private:
        public:
        /**
         * Продольная сила.
         */
        double N;
        /**
         * Поперечная сила.
         */
        double Q;
        /**
         * Изгибающий момент.
         */
        double Mz;
        /**
         * Погонная реакция упругого основания.
         */
        double R;
        /**
         * Горизонтальное перемещение сечения.
         */
        double u;
        /**
         * Вертикальное перемещение сечения.
         */
        double v;
        /**
         * Угол поворота сечения.
         */
        double c;
        BeamResults();
        //@Override
        //String toString();
};
//---------------------------------------------------------------------------------------------
class Constraint {  //   Класс описания опоры
        /**
         * Координата опоры.
         */
        public:
        double X;
        /**
         * Жесткость опоры в горизонтальном направлении. Отрицательная
         * жесткость означает абсолютно жесткую опору.
         */
        double u;
        /**
         * Жесткость опоры в вертикальном направлении. Отрицательная
         * жесткость означает абсолютно жесткую опору.
         */
        double v;
         /**
         * Жесткость опоры в направлении угла поворота сечения. Отрицательная
         * жесткость означает абсолютно жесткую опору.
         */
        double c;
        Constraint();
};
//---------------------------------------------------------------------------------------------
class Load { // Класс описания сосредоточенны нагрузок.
       public:
        /**
         * Координата точки приложения силы или момента.
         */
       double X;
        /**
         * Сила в горизонтальном направлении
         */
       double u;
        /**
         * Сила в вертикальном направлении.
         */
       double v;
        /**
         * Момент.
         */
       double c;

       Load();
};
//---------------------------------------------------------------------------------------------
class ExtremalValue {  // Класс описания эксремального значения
        public:
        /**
         * Величина эксремального значения.
         */
        double value;
        /**
         * Координата экстремального значения.
         */
        double XCoord;

        ExtremalValue();
        //@Override
        //String toString();
};
//---------------------------------------------------------------------------------------------
class BeamFE {
       private:
        /**
         * Перемещения узлов конечного элемента. Порядок следование перемещений:
		 * <ul>
         * <li> 0 - вертикальное перемещение первого узла.
         * <li> 1 - угол поворота первого узла.
         * <li> 2 - горизонтальное перемещение первого узла.
         * <li> 3 - вертикальное перемещение второго узла.
         * <li> 4 - угол поворота второго узла.
         * <li> 5 - горизонтальное перемещение второго узла.
         * </ul>
         */
        public:
        BeamRegion EI;
        BeamRegion EF;
        BeamRegion q;
        BeamRegion N;
        BeamRegion m;
        BeamRegion kpe;
        BeamRegion r;    // Реакция упругого основания
        double dsp[6];
        /**
         * Нагрузки, приведенные от распределенных по элементу сил.
         * Порядок следования аналогичен перемещениям.
		 */
        double load[6];
        double ke[6][6];
        double kg[6][6];
        double F[6];     // Узловые силы элемента
        public:
        ExtremalValue FEumax;
        ExtremalValue FEumin;
        // Максимальное вертикальное перемещение сечения балки.
        ExtremalValue FEvmax;
        // Минимальное вертикальное перемещение сечения балки.
        ExtremalValue FEvmin;
        // Максимальный угол поворота сечения балки.
        ExtremalValue FEcmax;
        // Минимальный угол поворота сечения балки.
        ExtremalValue FEcmin;
        ExtremalValue FENmax;
        ExtremalValue FENmin;
        // Максимальная величина поперечной силы в балке
        ExtremalValue FEQmax;
        // Минимальная величина поперечной силы в балке
		ExtremalValue FEQmin;
        // Максимальная величина изгибающего момента в балке
        ExtremalValue FEMmax;
        // Минимальная величина изгибающего момента в балке
        ExtremalValue FEMmin;
        // Конструктор по умолчанию
        //BeamFE();
        // конструктор
		BeamFE(double x0, double len, BeamRegion EIr, BeamRegion EFr,
				BeamRegion qr, BeamRegion pr, BeamRegion mr); //, BeamRegion kpr);
        void  beam_ke();
        void  beam_load();
        void  beam_results();
        BeamResults resultsAt(double X);
        void BeamRegion_b(BeamRegion *new_region, BeamRegion base, double x0, double len);

};
//---------------------------------------------------------------------------------------------
class MultiSupportBeam
{
  private:
	double ConstConstr;     // жесткость бесконечно жесткой опоры
	double ConstSingular;  // константа, характеризующая вырожденность
    // Данные по регионам балки
    BeamRegion* EI_BM;
    BeamRegion* EF_BM;
    BeamRegion* q_BM;
    BeamRegion* p_BM;
	BeamRegion* m_BM;
    BeamRegion* kp_BM;
	Load* loads_0;
    Constraint* constr_0;

    double beamLength;
    BeamFE* fem;
    int fem_length;
    ExtremalValue umax;
    ExtremalValue umin;
    ExtremalValue Nmax;
    ExtremalValue Nmin;

  public:
	int EI_length;
	int EF_length;
    int q_length;
    int m_length;
    int N_length;
    int kp_length;
    int loads_length;
    int constr_length;
    int constr_force_length;
	int EI_BM_length;
	double maxElementLength;
	int N_break;

	double H_beam;   // Высота сечения
	double Zct_beam;  // координта ц.т. сечения относительно внешней грани
	double I_beam;  // момент инерции сечения
	double F_beam;  // площадь сечения

  // Конструктор по умолчанию
	MultiSupportBeam();
	void MultiSupportBeam_(int N_break0, double maxElemLen, double H_beam0, double Zct_beam0, double I_beam0, double F_beam0);
	// Параметры решения
	/**
     * Код ошибки, соответствующий вырожденности матрицы жесткости
     */
    int ErrSingular;
	/**
     * Код ошибки в исходных данных. Координаты нагрузок или опор следую не в порядке возрастания
	 * координаты X.
	 */
    int ErrData;
	/**
     * Массив реакций в опорах.
     */
    Load* ConstrForces;  // реакции в точечных связях
     /**
     * Максимальное вертикальное перемещение сечения балки.
     */
    ExtremalValue vmax;
     /**
     * Минимальное вертикальное перемещение сечения балки.
     */
    ExtremalValue vmin;
     /**
     * Максимальный угол поворота сечения балки.
     */
    ExtremalValue cmax;
    /**
     * Минимальный угол поворота сечения балки.
	 */
	ExtremalValue cmin;
    /**
	 * Максимальная величина поперечной силы в балке
     */
    ExtremalValue Qmax;
    /**
     * Минимальная величина поперечной силы в балке
     */
    ExtremalValue Qmin;
    /**
     * Максимальная величина изгибающего момента в балке
     */
    ExtremalValue Mmax;
    /**
     * Минимальная величина изгибающего момента в балке
     */
    ExtremalValue Mmin;
	int normaliseRegions(BeamRegion* EI, BeamRegion* N_, BeamRegion* qy,
						 BeamRegion* mz,
						 //BeamRegion* ky,
						 Load* loads, Constraint* constraints, double FE_beam);
	int addRegion(int length, double len, double x, BeamRegion* EIv, BeamRegion* EI, int ind, int *kv);
    int Solver();
	int Solver_Mesh(int N_break0, double length_break);
    int mcond_front(int n0, int m0, double **mat0, double *load0);
    void mback_front(int n_break, int m, double **g_factor, double *l_factor, double *d_beam);
    int msolv(int nfr, double **k1, double *rst, double *bu);
	int calculate(BeamRegion* EI,
                  BeamRegion* N_, BeamRegion* qy,
				  BeamRegion* mz,
				  //BeamRegion* ky,
				  Load* loads, Constraint* constraints, double FE_beam);
    BeamResults getResults(double X);
    void MaxExtremValue(int i, ExtremalValue* max, ExtremalValue *FEmax);
    void MinExtremValue(int i, ExtremalValue* min, ExtremalValue *FEmin);

};

double **allocmat(int n, int m);
int cmp_Load(Load *elem1, Load *elem2);
int cmp_Constraint(Constraint *elem1, Constraint *elem2);

#endif
