Example #1
0
 /// <summary>
 /// Получить годограф функции плотного размещения круга и геометрического объекта.
 /// </summary>
 /// <param name="geometric_this">Геометрический объект.</param>
 /// <param name="circle">Круг.</param>
 /// <returns>Годограф функции плотного размещения.</returns>
 public static Geometric2d Годограф_функции_плотного_размещения(Geometric2d geometric_this, Geometric2dWithPointScalar circle)
 {
     if (geometric_this is Geometric2dWithPointScalar)
         return Circle2dExt.Годограф_функции_плотного_размещения(geometric_this as Geometric2dWithPointScalar, circle);
     if (geometric_this is Plane2d)
         return Plane2dExt.Годограф_функции_плотного_размещения(geometric_this as Plane2d, circle);
     return null;
 }
Example #2
0
        public static Geometric2dWithPointScalar Круг_Делоне(params Geometric2d[] geometrics)
        {
            int dim = geometrics.Length - 1;

            Geometric2dWithPointScalar circle_base = null;
            System.Collections.Generic.List<double[]> matr = new System.Collections.Generic.List<double[]>(dim + 1);

            #region Создание системы линейных уравнений.
            for (int i = 0; i < dim + 1; i++)
            {
                if (geometrics[i] is Geometric2dWithPointScalar)
                {
                    if (circle_base == null)
                        circle_base = geometrics[i] as Geometric2dWithPointScalar;
                    else
                    {
                        Geometric2dWithPointScalar circle = geometrics[i] as Geometric2dWithPointScalar;
                        double[] vect = new double[dim + 2];
                        for (int j = 0; j < dim; j++)
                        {
                            vect[j] = circle.Pole[j + 1] - circle_base.Pole[j + 1];
                            vect[dim + 1] -= vect[j] * (circle.Pole[j + 1] + circle_base.Pole[j + 1]);
                        }
                        vect[dim] = circle.Scalar - circle_base.Scalar;
                        vect[dim + 1] += vect[dim] * (circle.Scalar + circle_base.Scalar);
                        vect[dim + 1] /= 2;
                        matr.Add(vect);
                    }
                }
                else if (geometrics[i] is Plane2d)
                {
                    Plane2d plane = geometrics[i] as Plane2d;
                    double[] vect = new double[dim + 2];
                    for (int j = 0; j < dim; j++)
                    {
                        vect[j] = plane.Normal[j + 1];
                        vect[dim + 1] -= vect[j] * plane.Pole[j + 1];
                    }
                    vect[dim] = -1;
                    matr.Add(vect);
                }
                else
                    return null;
            }
            #endregion

            if (matr.Count < dim)
                return null; // Исключительная ситуация! Недостаточно информации!!

            #region Решение системы линейных уравнений.
            int m = matr.Count;
            int index = dim;
            for (int i = 0; i < m; i++)
            {
                #region Получаем диагональный (базисный) элемент.
                double a;
                if (i < index) // Тут ошибка.
                    a = matr[i][i];
                else
                    a = matr[i][i + 1];
                #endregion
                if (a != 0)
                {
                    #region Превращаем диагональный элемент в 1.
                    for (int j = i; j < dim + 2; j++)
                        matr[i][j] /= a;
                    #endregion

                    #region Для каждой строки...
                    for (int ii = 0; ii < m; ii++)
                    {
                        #region Получаем поддиагональный (подбазисный) элемент.
                        if (i < index)
                            a = matr[ii][i];
                        else
                            a = matr[ii][i + 1];
                        #endregion

                        #region Превращаем поддиагональный (подбазисный) элемент в 0. Пропускаем строку с диагональным (базисным) элементом и строки, которые не надо изменять.
                        if (ii != i && a != 0)
                            for (int j = 0; j < dim + 2; j++)
                                matr[ii][j] -= matr[i][j] * a;
                        #endregion
                    }
                    #endregion
                }
                else
                {
                    #region Поиск строки с базисным элементом не 0.
                    int ii = i + 1;
                    while (ii < m && matr[ii][i] == 0)
                        ii++;
                    #endregion

                    #region Если такой элемент найден, то меняем местами строки. Иначе меняем значение index.
                    if (ii < m)
                    {
                        double[] t = matr[i];
                        matr[i] = matr[ii];
                        matr[ii] = t;
                    }
                    else if (index == dim)
                        index = i;
                    else
                        return null;
                    i--;
                    #endregion
                }
            }
            #endregion

            if (circle_base != null)
            {
                #region Получение результата.
                double[,] res = new double[2, dim + 1];
                for (int i = 0; i < index; i++)
                {
                    res[0, i] = -matr[i][index];
                    res[1, i] = -matr[i][dim + 1];
                }

                res[0, index] = 1;
                res[1, index] = 0;

                for (int i = index; i < m; i++)
                {
                    res[0, i + 1] = -matr[i][index];
                    res[1, i + 1] = -matr[i][dim + 1];
                }
                #endregion

                #region Построение квадратичного уравнения.
                for (int i = 0; i < dim; i++)
                    res[1, i] -= circle_base.Pole[i + 1];
                res[1, dim] += circle_base.Scalar;

                double A = -res[0, dim] * res[0, dim];
                double B = -res[0, dim] * res[1, dim];
                double C = -res[1, dim] * res[1, dim];
                for (int i = 0; i < dim; i++)
                {
                    A += res[0, i] * res[0, i];
                    B += res[0, i] * res[1, i];
                    C += res[1, i] * res[1, i];
                }

                for (int i = 0; i < dim; i++)
                    res[1, i] += circle_base.Pole[i + 1];
                res[1, dim] -= circle_base.Scalar;
                #endregion

                #region Решение квадратичного уравнения.
                double D = B * B - A * C;
                if (D < 0)
                    return null;

                D = Math.Sqrt(D);
                double r_prev = (-B - D) / A;
                double r_next = (-B + D) / A;

                if (A == 0) // Откуда? Практика показала, что такая ситуация возможна. Может ошибка в другом?
                {
                    r_prev = -C / B / 2;
                    r_next = -C / B / 2;
                }
                #endregion

                #region Построение кругов Делоне.
                Geometric2dWithPointScalar circle_delone_prev = new Geometric2dWithPointScalar { Scalar = res[0, dim] * r_prev + res[1, dim] };
                Geometric2dWithPointScalar circle_delone_next = new Geometric2dWithPointScalar { Scalar = res[0, dim] * r_next + res[1, dim] };
                for (int i = 0; i < dim; i++)
                {
                    circle_delone_prev.Pole[i + 1] = res[0, i] * r_prev + res[1, i];
                    circle_delone_next.Pole[i + 1] = res[0, i] * r_next + res[1, i];
                }
                #endregion

                #region Выбор правильного круга Делоне.
                Vector2d[] vectors = new Vector2d[dim + 1];
                for (int i = 0; i < dim + 1; i++)
                {
                    if (geometrics[i] is Geometric2dWithPointScalar)
                        vectors[i] = ((geometrics[i] as Geometric2dWithPointScalar).Pole - circle_delone_prev.Pole) / ((geometrics[i] as Geometric2dWithPointScalar).Scalar + circle_delone_prev.Scalar);
                    else
                        vectors[i] = (geometrics[i] as Plane2d).Normal * (-1);
                }
                // Векторное произведение? Определитель матрицы, состоящей из векторов.
                double s = vectors[0].X * (vectors[1].Y - vectors[2].Y) + vectors[1].X * (vectors[2].Y - vectors[0].Y) + vectors[2].X * (vectors[0].Y - vectors[1].Y);

                if (s * circle_delone_prev.Scalar > 0)
                    return circle_delone_prev;
                else
                    return circle_delone_next;
                #endregion
            }
            else
            {
                #region Возврат решения линейного уравнения.
                if (index == dim && matr[dim][dim] != 0)
                {
                    Geometric2dWithPointScalar circle_delone = new Geometric2dWithPointScalar { Scalar = -matr[dim][dim + 1] };
                    for (int i = 0; i < dim; i++)
                        circle_delone.Pole[i + 1] = -matr[i][dim + 1];
                    return circle_delone;
                }
                else
                    return null;
                #endregion
            }
        }