/// <summary> /// Вычислить результирующее значение функции между 2-мя заданными точками /// </summary> /// <param name="x">Значение аргумента функции</param> /// <param name="fRunk">Ранг (порядок) аргумента</param> /// <param name="rangePt">Диапазон известных ближайших точек</param> /// <returns>Значение функции в точке</returns> private float calc(float x, FRUNK fRunk, RangePOINT rangePt) { float fRes = -1F; fRes = calc(x, rangePt.Left.X(fRunk), rangePt.Left.f, rangePt.Right.X(fRunk), rangePt.Right.f); return(fRes); }
/// <summary> /// Конструктор основной (с параметрами) /// </summary> /// <param name="id">Идентификатор записи в таблице БД</param> /// <param name="a1">1-ый аргумент</param> /// <param name="a2">2-ой аргумент</param> /// <param name="a3">3-ий аргумент</param> /// <param name="f">Значение функции для аргументов</param> public POINT(int id, float a1, float a2, float a3, float f) { m_idRec = id; this.a1 = a1; this.a2 = a2; this.a3 = a3; this.f = f; Runk = ((!(a2 == 0F)) || (!(a3 == 0F))) ? (!(a3 == 0F)) ? FRUNK.F3 : (!(a2 == 0F)) ? FRUNK.F2 : FRUNK.F1 : FRUNK.F1; }
/// <summary> /// Возвратить все аргументы функции для указанного ранга /// </summary> /// <param name="nameAlg">Наименование функции</param> /// <returns>Массив аргументов функции</returns> private List <PointPairList> getPointPairListValues(string nameAlg) { FRUNK fRunk = m_dictValues[nameAlg].Runk; List <PointPairList> listRes = new List <PointPairList> (); PointPairList item = null; bool bNewItem = false; foreach (POINT pt in m_dictValues[nameAlg]) { bNewItem = true; if (listRes.Count == 0) { ; } else { foreach (PointPairList ppl in listRes) { if (ppl.ContainsKey(pt) == true) { item = ppl; bNewItem = false; } else { ; } } } if (bNewItem == true) { item = new PointPairList(pt, fRunk); listRes.Add(item); } else { ; } if (!(item == null)) { item.Add(new PointPair(pt.X(FRUNK.F1), pt.f)); } else { ; } } return(listRes); }
/// <summary> /// Найти ближайшие реперные (узловые) точки /// </summary> /// <param name="nameAlg">Наименование функции</param> /// <param name="x">Аргумент функции, относительно которой производится поиск</param> /// <param name="fRunk">Ранг аргумента</param> /// <returns>Массив точек</returns> private RangePOINT getNearby(string nameAlg, float x, FRUNK fRunk, ListLIMIT listLimit) { RangePOINT rangeRes = null; INDEX_NEAR indxNearby = INDEX_NEAR.UNKNOWN; //Получить диапазон аргументов, значений rangeRes = getRange(nameAlg, fRunk, listLimit); //Определитть порядок назначения ближайших соседних реперных точек if ((!(x < rangeRes.Left.X(fRunk))) && (!(x > rangeRes.Right.X(fRunk)))) { // точка внутри диапазона - использовать интерполяцию indxNearby = INDEX_NEAR.COUNT; } else // точка вне диапазона if (x < rangeRes.Left.X(fRunk)) { // точка "слева" от диапазона - требуется уточнение правой границы indxNearby = INDEX_NEAR.LEFT; // левая - не изменяется } else if (x > rangeRes.Right.X(fRunk)) { // точка "справа" от диапазона - требуется уточнение левой границы indxNearby = INDEX_NEAR.RIGHT; // правая - не изменяется } else { ; } //Назначить ближайшие соседние реперные точки if (indxNearby == INDEX_NEAR.COUNT) { // внутри диапазона interpolation(nameAlg, x, fRunk, ref rangeRes, listLimit); } else { // вне диапазона extrapolation(nameAlg, x, fRunk, ref rangeRes, indxNearby, listLimit); } return(rangeRes); }
/// <summary> /// Уточнить диапазон соседних реперных (узловых) точек к указанному значению аргумента /// </summary> /// <param name="nameAlg">Наименование функции</param> /// <param name="xValue">Значение аргумента</param> /// <param name="fRunk">Ранг аргумента</param> /// <param name="arNearby">Массив с реперными точками, требующий уточнения (приближение к значению)</param> private void interpolation(string nameAlg, float xValue, FRUNK fRunk, ref RangePOINT rangeNearby, ListLIMIT listLimit) { float x = -1F , min = rangeNearby.Left.X(fRunk), max = rangeNearby.Right.X(fRunk); foreach (POINT pt in m_dictValues[nameAlg]) { if (listLimit.IsAllowedPoint(pt) == true) { x = pt.X(fRunk); if (((xValue - x) < (xValue - min)) && (!((xValue - x) < 0)) && (!(x == max))) { min = x; rangeNearby.Left = pt; continue; } else { ; } if (((x - xValue) < (max - xValue)) && (!((x - xValue) < 0)) && (!(x == min))) { max = x; rangeNearby.Right = pt; } else { ; } } else { ; } } }
/// <summary> /// Возвратить диапазон точек по указанному рангу аргумента (кол-во точек должно быть - не меньше 1-ой) /// </summary> /// <param name="nameAlg">Наименование функции</param> /// <param name="fRunk">Ранг аргумента</param> /// <returns>Массив точек</returns> private RangePOINT getRange(string nameAlg, FRUNK fRunk, ListLIMIT listLimit) { RangePOINT rangeRes = new RangePOINT(); //Результат float x = -1F //Аргумент функции , min = float.MaxValue, max = float.MinValue; foreach (POINT pt in m_dictValues[nameAlg]) { if (listLimit.IsAllowedPoint(pt) == true) { x = pt.X(fRunk); if (x < min) { min = x; rangeRes.Left = pt; } else { ; } if (x > max) { max = x; rangeRes.Right = pt; } else { ; } } else { ; } } return(rangeRes); }
public float X(FRUNK fRunk) { float fRes = float.NaN; switch (fRunk) { case FRUNK.F1: fRes = a1; break; case FRUNK.F2: fRes = a2; break; case FRUNK.F3: fRes = a3; break; default: break; } return(fRes); }
/// <summary> /// Вычислить значения для функции /// по заданным аргументам /// для одного аргумента все считает /// для двух - ошибка в вычислении /// для трех - алгоритм недописан /// </summary> /// <param name="args">Аргументы для вычисления функции</param> /// <returns>Значение функции по заданным аргументам</returns> public float Calculate(string nameALG, FRUNK fRunkVar, params float[] args) { m_nameAlg = nameALG; FRUNK fRunk = _fRunk; ////??? для универсализации расчета //int iRunk = -1 // , iPow = -1 // , iRow =-1, iCol = -1; List <RangePOINT[, ]> listPointNearby = new List <RangePOINT[, ]>((int)(fRunk + 1)); List <float [, ]> listRes = new List <float[, ]> (); if ((fRunkVar > FRUNK.UNKNOWN) && // ранг введенной переменной д.б. известен (!((int)fRunkVar > args.Length)) && // ранг введенной переменной д.б. не больше кол-ва аргументов (m_dictValues[nameALG].Count > 1)) // для вычислений требуется как минимум 2 точки { ////??? попытка универсализации расчета //for (iRunk = (int)FRUNK.F1; iRunk < ((int)fRunk + 1); iRunk++) //{ // iPow = (int)(fRunk - iRunk); // iRow = (int)(Math.Pow((fRunk == FRUNK.F1 ? 1F : (float)fRunk), iPow) / (iPow == 0 ? 1 : iPow)); // iCol = iPow == 0 ? 1 : iPow; // listPointNearby.Insert(iRunk, new RangePOINT[iRow, iCol]); // listRes.Insert(iRunk, new float[iRow, iCol]); //} //for (iRunk = (int)FRUNK.F1; iRunk < ((int)fRunk + 1); iRunk++) // for (int i = 0; i < listPointNearby[(int)iRunk].GetLength(0); i++) // for (int j = 0; j < listPointNearby[(int)iRunk].GetLength(1); j++) // ; switch (fRunk) { case FRUNK.F1: //??? не универсальное добавление элементов listPointNearby.Insert((int)FRUNK.F1, new RangePOINT[1, 1]); listRes.Insert((int)FRUNK.F1, new float[1, 1]); // получить ближайшие реперные (узловые) точки listPointNearby[(int)FRUNK.F1][0, 0] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT()); // вычисление промежуточных значений ... - нет // вычисление рез-та listRes[(int)fRunk][0, 0] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][(int)FRUNK.F1, (int)FRUNK.F1]) //-1F по умолчанию ; break; case FRUNK.F2: //??? не универсальное добавление элементов listPointNearby.Insert((int)FRUNK.F1, new RangePOINT[2, 1]); listRes.Insert((int)FRUNK.F1, new float[2, 1]); listPointNearby.Insert((int)FRUNK.F2, new RangePOINT[1, 1]); listRes.Insert((int)FRUNK.F2, new float[1, 1]); // получить ближайшие реперные (узловые) точки listPointNearby[(int)FRUNK.F2][0, 0] = getNearby(nameALG, args[(int)FRUNK.F2] , FRUNK.F2 , new ListLIMIT()); listPointNearby[(int)FRUNK.F1][0, 0] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F2, x = listPointNearby[(int)FRUNK.F2][0, 0].Left.a2 } } ); listPointNearby[(int)FRUNK.F1][1, 0] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F2, x = listPointNearby[(int)FRUNK.F2][0, 0].Right.a2 } } ); // вычисление промежуточных значений // 1-ый ранг listRes[(int)FRUNK.F1][0, 0] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][0, 0]); listRes[(int)FRUNK.F1][1, 0] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][1, 0]); // вычисление рез-та listRes[(int)fRunk][0, 0] = calc(args[(int)FRUNK.F2] , listPointNearby[(int)FRUNK.F2][0, 0].Left.X(FRUNK.F2) , listRes[(int)FRUNK.F1][0, 0] , listPointNearby[(int)FRUNK.F2][0, 0].Right.X(FRUNK.F2) , listRes[(int)FRUNK.F1][1, 0]) //-1F по умолчанию ; break; case FRUNK.F3: //??? не универсальное добавление элементов listPointNearby.Insert((int)FRUNK.F1, new RangePOINT[2, 2]); listRes.Insert((int)FRUNK.F1, new float[2, 2]); listPointNearby.Insert((int)FRUNK.F2, new RangePOINT[2, 1]); listRes.Insert((int)FRUNK.F2, new float[2, 1]); listPointNearby.Insert((int)FRUNK.F3, new RangePOINT[1, 1]); listRes.Insert((int)FRUNK.F3, new float[1, 1]); // получить ближайшие реперные (узловые) точки listPointNearby[(int)FRUNK.F3][0, 0] = getNearby(nameALG, args[(int)FRUNK.F3] , FRUNK.F3 , new ListLIMIT()); listPointNearby[(int)FRUNK.F2][0, 0] = getNearby(nameALG, args[(int)FRUNK.F2] , FRUNK.F2 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F3, x = listPointNearby[(int)FRUNK.F3][0, 0].Left.a3 } } ); listPointNearby[(int)FRUNK.F2][1, 0] = getNearby(nameALG, args[(int)FRUNK.F2] , FRUNK.F2 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F3, x = listPointNearby[(int)FRUNK.F3][0, 0].Right.a3 } } ); listPointNearby[(int)FRUNK.F1][0, 0] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F3, x = listPointNearby[(int)FRUNK.F3][0, 0].Left.a3 } , new LIMIT() { fRunk = FRUNK.F2, x = listPointNearby[(int)FRUNK.F2][0, 0].Left.a2 } } ); listPointNearby[(int)FRUNK.F1][1, 0] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F3, x = listPointNearby[(int)FRUNK.F3][0, 0].Left.a3 } , new LIMIT() { fRunk = FRUNK.F2, x = listPointNearby[(int)FRUNK.F2][0, 0].Right.a2 } } ); listPointNearby[(int)FRUNK.F1][0, 1] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F3, x = listPointNearby[(int)FRUNK.F3][0, 0].Right.a3 } , new LIMIT() { fRunk = FRUNK.F2, x = listPointNearby[(int)FRUNK.F2][1, 0].Left.a2 } } ); listPointNearby[(int)FRUNK.F1][1, 1] = getNearby(nameALG, args[(int)FRUNK.F1] , FRUNK.F1 , new ListLIMIT() { new LIMIT() { fRunk = FRUNK.F3, x = listPointNearby[(int)FRUNK.F3][0, 0].Right.a3 } , new LIMIT() { fRunk = FRUNK.F2, x = listPointNearby[(int)FRUNK.F2][1, 0].Right.a2 } } ); // вычисление промежуточных значений // 1-ый ранг listRes[(int)FRUNK.F1][0, 0] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][0, 0]); listRes[(int)FRUNK.F1][1, 0] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][1, 0]); listRes[(int)FRUNK.F1][0, 1] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][0, 1]); listRes[(int)FRUNK.F1][1, 1] = calc(args[(int)FRUNK.F1] , FRUNK.F1 , listPointNearby[(int)FRUNK.F1][1, 1]); // 2-ой ранг listRes[(int)FRUNK.F2][0, 0] = calc(args[(int)FRUNK.F2] , listPointNearby[(int)FRUNK.F2][0, 0].Left.X(FRUNK.F2) , listRes[(int)FRUNK.F1][0, 0] , listPointNearby[(int)FRUNK.F2][0, 0].Right.X(FRUNK.F2) , listRes[(int)FRUNK.F1][1, 0]); listRes[(int)FRUNK.F2][1, 0] = calc(args[(int)FRUNK.F2] , listPointNearby[(int)FRUNK.F2][1, 0].Left.X(FRUNK.F2) , listRes[(int)FRUNK.F1][0, 1] , listPointNearby[(int)FRUNK.F2][1, 0].Right.X(FRUNK.F2) , listRes[(int)FRUNK.F1][1, 1]); // вычисление рез-та listRes[(int)fRunk][0, 0] = calc(args[(int)FRUNK.F3] , listPointNearby[(int)FRUNK.F3][0, 0].Left.X(FRUNK.F3) , listRes[(int)FRUNK.F2][0, 0] , listPointNearby[(int)FRUNK.F3][0, 0].Right.X(FRUNK.F3) , listRes[(int)FRUNK.F2][1, 0]) //-1F по умолчанию ; break; default: break; } } else { ; } m_nameAlg = string.Empty; return(listRes[(int)fRunk][0, 0]); }
/// <summary> /// Уточнить диапазон соседних реперных (узловых) точек к указанному значению аргумента /// </summary> /// <param name="nameAlg">Наименование функции</param> /// <param name="xValue">Значение аргумента</param> /// <param name="fRunk">Ранг аргумента</param> /// <param name="arNearby">Массив с реперными точками, требующий уточнения (приближение к значению)</param> /// <param name="indxConstNearby">Граница диапазона, остающейся постоянной</param> private void extrapolation(string nameAlg, float xValue, FRUNK fRunk, ref RangePOINT rangeNearby, INDEX_NEAR indxConstNearby, ListLIMIT listLimit) { float min = -1F, max = -1F , x = -1F; min = float.MaxValue; //rangeNearby.Left.X(fRunk); max = float.MinValue; //rangeNearby.Right.X(fRunk); foreach (POINT pt in m_dictValues[nameAlg]) { if (listLimit.IsAllowedPoint(pt) == true) { x = pt.X(fRunk); if (min == float.MaxValue) { min = x; rangeNearby.Left = pt; continue; } else { ; } if ((max == float.MinValue) && (!(min == x))) { max = x; rangeNearby.Right = pt; continue; } else { ; } if ((!(min == float.MaxValue)) && (!(max == float.MinValue))) { if ((Math.Abs(xValue - x) < Math.Abs(xValue - min)) && (!(x == max))) { if ((xValue - min) < (xValue - max)) { max = min; rangeNearby.Right = rangeNearby.Left; } else { ; } min = x; rangeNearby.Left = pt; } else { ; } } else if ((Math.Abs(xValue - x) < Math.Abs(xValue - max)) && (!(x == min))) { max = x; rangeNearby.Right = pt; } else { ; } } else { ; } } }
/// <summary> /// Конструктор - основной /// </summary> /// <param name="key">Ключ для линии</param> /// <param name="fRunk">Ранг (порядок) линии</param> public PointPairList(POINT key, FRUNK fRunk) { this.key = key; this.fRunk = fRunk; }