Russian Qt Forum
Ноябрь 25, 2024, 20:18 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4 5   Вниз
  Печать  
Автор Тема: Переделать старые структуры  (Прочитано 36471 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #30 : Август 28, 2017, 09:44 »

union, ничего лишнего не храниться.
Пример
Код
C++ (Qt)
union {
 double value;
 double coordinate[3];
 float color[4];
};
 
sizeof вернет 24 (макс размер)

Но у меня ошибка, у вас наверное сплайн для каждой кривой одного типа, а я думал что для каждой точки свой тип сплайна.
Тип сплайна сейчас один для всех точек, но в каждой точке сидят свои параметры сплайна (причем разные для разных типов данных)

Чем вам Curve как QList<QVariant> не нравиться? а типы как
Код:
template<typename T> Curve 
{ template <typename T>struct Value<T>{T data, in, out; float someOptions[];}
 QMap<double,Value>  }
Опять я вынужден попросить Вас излагать свои мысли менее сумбурно. В первой строке Curve контейнер вариантов, но уже в следующей он шаблонный тип. Как Вас понять?  Улыбающийся
Код
C++ (Qt)
Зачем, зачем ты торопился?
Зачем свою лошадку гнал?
Али урядника боялся
Али в контору задолжал?
Эта старая (печальная) песня явно о Вас  Улыбающийся
« Последнее редактирование: Август 28, 2017, 10:19 от Igors » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #31 : Август 28, 2017, 12:15 »

Почему так упорно выставляется требование "ОДИН класс"? Аргумент "поместить в контейнер" правда, но звучит не очень (ну подумаешь, контейнер). Вот гораздо более наглядный пример. Предположим QImage в Qt был бы реализован так
Код
C++ (Qt)
QImage<format_ARGB32>
QImage<format_GrayScale>
...
 
Какой кайф было бы с ним работать! Улыбающийся Однако почему-то то же самое предлагается для класса Curve...

QImage работает с одним типом данных: цветом. Цвет может быть представлен в разных форматах, но важным является то, что они могут конвертироваться между собой и имеют обобщённый тип. Методы QImage оперируют одним конкретным типом QColor, а не множеством ColorInXxxFormat. Если Вы для своих данных найдете такой общий тип и внятные преобразования между ними, то тоже сможете делать так Улыбающийся.

Когда метод QImage возвращает цвет в QColor, то по нему нельзя узнать, в каком формате он хранился в том QImage, и в большинстве случаев это знание и на фиг не нужно. В вашем же случае наверняка захочется узнать, что же вернул какой-нибудь GetNthKeyValue(int keyIndex): координату или цвет? Улыбающийся
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #32 : Август 29, 2017, 09:10 »

QImage работает с одним типом данных: цветом. Цвет может быть представлен в разных форматах, но важным является то, что они могут конвертироваться между собой и имеют обобщённый тип. Методы QImage оперируют одним конкретным типом QColor, а не множеством ColorInXxxFormat.
Как Вы гладко говорите Улыбающийся Но разве можно конвертировать ARGB32 в GrayScale или RGB32? Такое преобразование по меньшей мере неоднозначно. А внутренний формат не волнует только до тех пор пока не случилось QImage::bits. Поэтому каких-то принципиальных различий нет

Если Вы для своих данных найдете такой общий тип и внятные преобразования между ними, то тоже сможете делать так Улыбающийся.
Да хотя бы то что предложил deMax
Цитировать
class UnionData {
public:
    enum DataType { NO,DOUBLE, COLOR, VECTOR3 };
private:
...
    DataType dataType = NO;
public:
    union {double d; Color c; Vector3 v3;};
    bool isDataType(DataType dataType) {return dataType == this->dataType;}

    UnionData() { dataType = NO; }
    UnionData(double d){ dataType = DOUBLE; this->d = d;}
    UnionData(Color c){ dataType = COLOR; this->c = c;}
    UnionData(Vector3 v3){ dataType = VECTOR3; this->v3 = v3;}
};
(здесь наверняка "щелкнет тумблер" типа "велик!", "костыли" - оно ж не "ис каропки"  Улыбающийся). Зато по сути верно 

В вашем же случае наверняка захочется узнать, что же вернул какой-нибудь GetNthKeyValue(int keyIndex): координату или цвет?
Ну как "наверняка" - хотя неизбежно такие методы будут, но их будет мало. Большинство операций с разношерстными значениями могут быть успешно замкнуты внутри класса Curve. Как и QImage::fill использует внутренний формат, а не обобщенный ARGB32

Да, если класс Curve не шаблонный, то не остается ничего другого как общаться с ним через вариант или его аналог (напр старший, вмещающий тип). Но почему из этого автоматически следует что все должно быть на варианте? Такой вывод, мягко говоря, примитивен. Разве мы не можем сделать "начинку" класса на template?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #33 : Август 29, 2017, 12:59 »

Может еще в таком направлении покопать, ну или мысли какие полезные возникнут:
Код:
#include <typeinfo>

class Base{
    static const QStringList typeId;
public:
    enum TYPE { NO = -1, INT, STR, DBL } type = NO;

    int getData(double, int &data);
    int getData(double, QString &data);
    int getData(double, double &data);
};

template <typename T> class BaseChild: public Base{
    friend Base;
protected:
    T data;
public:
    BaseChild(T data) : data(data) { type = (TYPE)typeId.indexOf(typeid(data).name()); }
};

const QStringList Base::typeId {"i", "7QString", "d"};
int Base::getData(double, int &data) { if(type == (int)INT) data = static_cast<BaseChild<int>*>(this)->data; }
int Base::getData(double, QString &data) { if(type == (int)STR) data = static_cast<BaseChild<QString>*>(this)->data; }
int Base::getData(double, double &data) { if(type == (int)DBL) data = static_cast<BaseChild<double>*>(this)->data; }

int main(int argc, char *argv[])
{
    QList<Base*> list;

    list << new BaseChild<int>(5);
    list << new BaseChild<QString>("5");
    list << new BaseChild<double>(5);

    for(auto i: list)  qDebug() << i->type;

    int a1;
    QString a2;
    double a3;

    list[0]->getData(1, a1);
    list[1]->getData(1, a2);
    list[2]->getData(1, a3);

    qDebug() << a1 << a2 << a3;

    return 0;
}
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #34 : Август 29, 2017, 13:51 »

Как Вы гладко говорите Улыбающийся Но разве можно конвертировать ARGB32 в GrayScale или RGB32? Такое преобразование по меньшей мере неоднозначно. А внутренний формат не волнует только до тех пор пока не случилось QImage::bits. Поэтому каких-то принципиальных различий нет
Ясное дело, что при конвертации между разными форматами могут возникать искажения/потери информации о цвете. Но преобразования выполняются над одни общим типом: цветом. К потерям точности при преобразованиях double <-> float, или даже double <-> int Вы же с пониманием относитесь? В то же самое время для вашего случая, можете предложить адекватное преобразование Color <-> Vector3D?

Ну как "наверняка" - хотя неизбежно такие методы будут, но их будет мало. Большинство операций с разношерстными значениями могут быть успешно замкнуты внутри класса Curve. Как и QImage::fill использует внутренний формат, а не обобщенный ARGB32
То, что замыкается внутри QImage или Curve не так важно, как то, чем они оперируют снаружи (типы параметров публичных методов). QImage оперирует одним QColor. У вас получается {double, Color, Vector3D}. Можно их запихнуть в один variant. При этом ещё появляется switch по этому типу данных, который наверняка не отменяет switch по типу кривой. Оно Вам надо? Улыбающийся Кроме того, в задаче ещё опции сплайнов фигурируют. Их тоже в union/variant пихать предлагаете?

Да, если класс Curve не шаблонный, то не остается ничего другого как общаться с ним через вариант или его аналог (напр старший, вмещающий тип). Но почему из этого автоматически следует что все должно быть на варианте? Такой вывод, мягко говоря, примитивен. Разве мы не можем сделать "начинку" класса на template?
Шаблоны ничего волшебного не делают. На текущий момент они в основном помогают избегать копипасты кода. Напишите класс Curve, как Вы его представляете, увидите там повторяющийся код, его и можно пытаться в шаблоны засунуть.

И, если нравится всё сваливать в одну кучу, и чтобы не изобретать велосипеды, можете обратить внимание на std::variant и std::any.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #35 : Август 29, 2017, 15:28 »

..можете предложить адекватное преобразование Color <-> Vector3D?
По-моему оно аналогично преобразованию ARGB <-> RGB  (по крайней мере по числу компонент)

Их тоже в union/variant пихать предлагаете?
Да я, вообще-то, от Вас хотел услышать какие-то предложения Улыбающийся Ну пока не очень..

И, если нравится всё сваливать в одну кучу, и чтобы не изобретать велосипеды, можете обратить внимание на ..
Как будто я вот ну захотел изобрести велосипед - и все тут! Улыбающийся Но какой у меня выбор? Сидеть дальше с этим калом мамонта? Он уже достало, лезет из всех щелей, а о расширении ф-ционала говорить не приходится.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #36 : Август 29, 2017, 19:13 »

Да я, вообще-то, от Вас хотел услышать какие-то предложения Улыбающийся Ну пока не очень..
Одно из простых "решений в лоб" я предложил здесь. Если есть острая необходимость именно в один класс всё запихнуть, то можете поэкспериментировать с таким франкенштейном (требуется С++17):

Код
C++ (Qt)
#include <iostream>
#include <any>
#include <variant>
#include <vector>
#include <array>
#include <chrono>
 
using namespace std;
 
using Vector3D = array<double, 3>;
using Color = array<int, 4>;
using TimePoint = chrono::system_clock::time_point;
 
struct RatioOption
{
   double inRatioVector;
   double outRatioVector;
};
 
struct WeightOption
{
   int inWeight;
   int outWeight;
};
 
struct Curve
{
   using Key = variant<double, TimePoint>;
   using Point = variant<double, Vector3D, Color>;
   using Option = any;
   struct Data
   {
       Key key;
       Point point;
       Option option;
   };
   using Container = vector<Data>;
 
   Container data;
};
 
int main()
{
   Curve curve;
 
   curve.data.push_back( { 1.5, Color{24,32,64,128}, RatioOption{5.4, 8.7} } );
   curve.data.push_back( { TimePoint::clock::now(), Vector3D{1.2, 3.4, 5.6}, WeightOption{2,6} } );
 
   for (const auto & data : curve.data)
   {
       cout << "key = " << data.key // ??
            << "point = " << data.point // ??
            << "option = " << data.option // ??
            << endl;
   }
 
   return 0;
}
 

Как будто я вот ну захотел изобрести велосипед - и все тут! Улыбающийся Но какой у меня выбор? Сидеть дальше с этим калом мамонта? Он уже достало, лезет из всех щелей, а о расширении ф-ционала говорить не приходится.

Мы с разных сторон к решению задачи подходим. Вы, похоже, заходите со стороны данных, чтобы загнать их в один класс и как-то удобно с ним работать. При этом Вы хотите совместить, грубо говоря, полиморфизм compile-time с полиморфизмом run-time. Но у них разные механизмы реализации и один не может заменить другой. Поэтому то, что хорошо ложится на шаблоны в compile-time, ни фига не работает run-time. Я захожу со стороны кривой как объекта: зачем она вообще нужна, к чему применяется, где/как/кем создаётся/редактируется и т.п. Но это нужно глубоко лезть в кроличью нору Улыбающийся (и писать много(очень много) классов).
« Последнее редактирование: Август 29, 2017, 20:13 от ViTech » Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Август 30, 2017, 11:48 »

Я захожу со стороны кривой как объекта: зачем она вообще нужна, к чему применяется, где/как/кем создаётся/редактируется и т.п. Но это нужно глубоко лезть в кроличью нору Улыбающийся (и писать много(очень много) классов).
Это типовая проблема любой "архитектурной" темы. Разумеется реальные структуры намного сложнее, рассказ о них быстро перегружает слушателей информацией (которую обычно не так уж и легко осознать), ну и быстрый вывод (соскок) "та ну его нафиг во все это вникать - мне бы дай бог в свой проект вникнуть". Поэтому здесь я сознательно даю "по минимуму", по-другому просто не получится. Есть простейший ф-ционал вытекающий из понятия "кривая (график) от времени" - ВСЕ

..зачем она вообще нужна,
Ну а зачем нужен QImage? "Чтобы рисовать". Также и кривая - "чтобы получать значения для заданного времени". Слишком общий ответ? Так и вопрос такой же  Улыбающийся

Если есть острая необходимость именно в один класс всё запихнуть..
Звучит как будто я хочу ну совсем уж что-то "эдакое" (может даже извращенное) Улыбающийся По-моему напротив, мои потребности очень банальны. Как только класс становится "достаточно широко используемым" - он не может быть шаблонным, не пролазит тот шаблон во все дырки. Напр "шаблонный QImage" = бред собачий

..то можете поэкспериментировать с таким франкенштейном (требуется С++17):
Набросать структуры на варианте - полчаса максимум, и не так уж важно что использовать (буст, std или Qt). Но дальше-то жопа непролазная. Напр
Код
C++ (Qt)
struct RatioOption
{
   double inRatioVector;
   double outRatioVector;
};
 
так это "как сейчас", для одного типа данных double. Для 3 типов придется написать так
Код
C++ (Qt)
template <T>
struct RatioOption
{
   T inRatioVector;
   T outRatioVector;
};
 
Но это уже 3 разных типа. Итого я имею (3 типа данных) * (6 типов сплайна) = 18 классов. Разрывать их свитчем всякий раз - ну это не выход
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #38 : Август 30, 2017, 12:06 »

так это "как сейчас", для одного типа данных double. Для 3 типов придется написать так
Код
C++ (Qt)
template <T>
struct RatioOption
{
   T inRatioVector;
   T outRatioVector;
};
 
Но это уже 3 разных типа. Итого я имею (3 типа данных) * (6 типов сплайна) = 18 классов. Разрывать их свитчем всякий раз - ну это не выход
А давайте чуть предметнее, упростим задачу: 2 простых типа(int, double), 2 сплайна(сами приведите попроще из тех что есть) и попробуем набросать код без свитча.
inRatioVector нужен? я просто когда сплайн рисовал, брал N точек вперед и назад из массива и ничего не хранил.

допустим:
Код:
class Spline {
QMap<Time,QVariant> data;
QList<IdData,Qvarint> inData, outData;
Qvariant getData(Time time, SplineType st); //сюда можно вообще callback засунуть например, или разные сплайны будут требовать разные вспомогательные данные
}
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #39 : Август 30, 2017, 12:12 »

Данные мы засунули в некоторую структуру(уже разобрались), теперь в ней будем хранить указатель на функцию под конкретный сплайн и QList<QVariant> - данные для каждой точки под каждый сплайн.

Код:
Spline{
  QList<UnionData> data;
  QList<UnionSplineData> dataForSpline;
  void(*splineFunction)();
}

естественно нужно определить умножение/сложение... чтобы функция сплайна оперировала с UnionType а не свитч на несколько типов
« Последнее редактирование: Август 30, 2017, 12:15 от deMax » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #40 : Август 30, 2017, 15:43 »

Но это уже 3 разных типа. Итого я имею (3 типа данных) * (6 типов сплайна) = 18 классов. Разрывать их свитчем всякий раз - ну это не выход
Хорошо, Вы ссылаетесь на QImage как на образец, который наиболее похож на решение задачи по хранению данных кривых. Да, QImage не шаблонный, но они возможные комбинации параметров шаблона переместили в QImage::Format, который на текущий момент (Qt 5.9) насчитывает 25 позиций и иногда пополняется. Можете сделать аналогично enum Curve::Format{ DateTime_Double, DateTime_Vector3D, DateTime_Color, ..., Key_Point_Option} и свитчевать по этому формату.

Далее про шаблонный template <T> struct RatioOption{}. Вы предполагаете, что там может быть три типа (на самом деле не важно сколько, важно, что больше одного). В Qt повсеместно можно обнаружить перегрузки методов для QPoint/QPointF, QRect/QRectF и т.п. Они не выносят тип в шаблон, они зафиксировали какой-то целочисленный и вещественный типы и дублируют методы для случаев, когда эти типы надо различать. Можете сделать так же RatioOption и RatioOptionF и дублировать методы для них.

Как я говорил раньше, QImage хранит один тип данных: цвет, пусть и в разных форматах. Вы же хотите хранить разные типы данных {double, Vector3D, Color} ещё и отягощенные множеством SplineOption. Поэтому я считаю, что не стоит ориентироваться на QImage. Не надо всё скидывать в одну кучу, а потом героически разгребать её Улыбающийся.

Я бы стремился к такому варианту:
Код
C++ (Qt)
#include <iostream>
#include <vector>
#include <array>
#include <chrono>
#include <memory>
 
using namespace std;
 
using Vector3D = array<double, 3>;
using Color = array<int, 4>;
using TimePoint = chrono::system_clock::time_point;
 
struct EmptyOption
{};
 
template <class T>
struct RatioOption
{
   T inRatioVector;
   T outRatioVector;
};
 
template <class T>
struct WeightOption
{
   T inWeight;
   T outWeight;
};
 
struct AbstractCurve
{
public:
   virtual ~AbstractCurve(){}
 
   virtual void printTo(ostream & stream) const = 0;
};
 
template <class Key, class Point, class Option = EmptyOption>
struct Curve final : public AbstractCurve
{
   struct Data
   {
       Key key;
       Point point;
       Option option;
   };
 
   using Container = vector<Data>;
   Container data;
 
   void printTo(ostream & stream) const override
   {
       stream << "Generic curve [" << endl;
       for (const auto & i : data)
       {
           stream << "    ["
                  << " key = " << i.key
                  << ", point = " << i.point
                  << ", option = " << i.option
                  << " ]" << endl;
       }
       stream << "]" << endl;
   }
};
 
int main()
{
   auto coord_curve = make_unique<Curve<TimePoint, Vector3D>>();
   coord_curve->data.push_back({TimePoint(1s), Vector3D{1.2, 3.4, 5.6}, EmptyOption()});
   coord_curve->data.push_back({TimePoint(2s), {5.6, 3.4, 1.2}, {}});
 
   auto color_curve = make_unique<Curve<double, Color>>();
   color_curve->data.push_back({1.7, Color{1, 2, 3, 4}, {}});
   color_curve->data.push_back({2.5, {5, 6, 7, 8}});
 
   auto coord_ratio_curve = make_unique<Curve<TimePoint, Vector3D, RatioOption<double>>>();
   coord_ratio_curve->data.push_back({TimePoint(1h), {1.2, 3.4, 5.6}, {1.4, 4.1}});
   coord_ratio_curve->data.push_back({TimePoint(2h), {5.6, 3.4, 1.2}, {2.3, 5.7}});
 
   auto color_weight_curve = make_unique<Curve<double, Color, WeightOption<int>>>();
   color_weight_curve->data.push_back({5.8, Color{1, 2, 3, 4}, {1, 2}});
   color_weight_curve->data.push_back({7.2, {5, 6, 7, 8}, {3, 4}});
 
   vector<unique_ptr<AbstractCurve>> curves;
   curves.push_back(move(coord_curve));
   curves.push_back(move(color_curve));
   curves.push_back(move(coord_ratio_curve));
   curves.push_back(move(color_weight_curve));
 
   for (const auto & curve : curves)
       curve->printTo(cout);
 
   return 0;
}
* Полный текст в аттаче, тут убрал перегрузку вывода в поток, чтобы не захлямлять код.

Соответственно нужно стремиться к методам в AbstractCurve, которые не зависят от типов данных кривых: printTo(Stream), saveTo(Storage), loadFrom(Storage), drawIn(QImage), drawBy(QPainter) и т .п. Если требуется редактировать эти кривые в GUI, то для различных типов кривых, я так подозреваю, могут потребоваться разные визуальные редакторы. Для сопоставления кривая <-> редактор, скорей всего, от dynamic_cast или свитча не уйти, се ля ви.

Для сравнения с монолитным Curve можете попробовать туда добавить метод printTo(ostream & stream). И заодно проследить, чтобы в кривую с координатами кто-нибудь цвет не добавил Улыбающийся.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #41 : Август 31, 2017, 07:24 »

Я бы стремился к такому варианту:
Понял, шаблонный класс наследует базовый, (нешаблонный и с виртуалами) и дальше пытаемся все сделать на этих виртуалах. Собсно это единственный способ "замкнуть" темплейты внутри класса что я знаю. Знатоки шаблонов, так ли это? Кстати где же вы вообще?  Улыбающийся

Только почему надо делать это для класса Curve? То же подход но для класса Key мне кажется более логичным. Схема
Код
C++ (Qt)
struct Curve {
...
QVector<Key *> mKeys;  
...
};
 
struct Key {
 ...
 virtual MyVariant GetValue( void );
 virtual void SetValue( const MyVariant & );
 ...
};
 
template <class DataType, class SplineType>
struct CTypedKey : public Key {
...
 virtual MyVariant GetValue( void )  { return mData; }
 virtual void SetValue( const MyVariant & v ) { mData = v; }
...
 DataType mData;
 SplineType mSpline;
};

ViTech, просьба "менее академично".  Время - просто double, делать его тоже шаблонным (так, для примера) не нужно. Использоваться повсеместно будет базовый класс, поэтому ему надо назвать просто и удобно "Curve" (а не тыкать всякий раз в нос "Abstract") и.т.п.

Поэтому я считаю, что не стоит ориентироваться на QImage.
Я и не собирался что-то из него брать. Просто это хороший пример когда данные разные, но шаблонный класс совершенно неприемлем.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #42 : Август 31, 2017, 07:57 »

А давайте чуть предметнее, упростим задачу: 2 простых типа(int, double), 2 сплайна(сами приведите попроще из тех что есть) и попробуем набросать код без свитча.
Давайте. Сейчас, для единственного типа double, это выглядит так (все на С, методов нет, только ф-ции)
Код
C++ (Qt)
double InterpolateValue( Curve * curve, double t )
{
// проверяем частные случаи
 if (t >= MaxTime(curve)) ...
 if (t <= MinTime(curve)) ...
 
 switch (curve->splineType) {
   case SPLINE_LINEAR:
     return InterpolateLinear(curve, t);
 
   case SPLINE_RATIO:
     return InterpolateRatio(curve, t);
 
   .....
 }
}
Простейшая интерполяция - линейная, т.е. точки соединены прямой и все. Формально тоже сплайн, параметров нет
Код
C++ (Qt)
double InterpolateLinear( Curve * curve, double t )
{
  Key * key1 = FindUpperKey(curve, t);  // находим первый ключ с временем больше t
  Key * key0 = GetPreviousKey(key1);   // и предыдущий
 
// интерполируем
  double relativeT = (t - key0->keyTime) / (key1->keyTime - key0->keyTime);
  return key0->keyData * (1 - relativeT) + key1->keyData * relativeT;
}
 
Кстати: FindUpperKey соответствует std::upper_bound (а не std::lower_bound). Это имеет значение т.к. ключи с одинаковым временем разрешены.

Ладно, теперь пример сплайна с параметрами.
Код
C++ (Qt)
// спец случай - постоянное значение до след ключа
  if (TestFlag(key0->spline.ratio.flag, BIT_HOLD)) return key0->keyData;
 
// спец случай - линейное значение до след ключа
  if (TestFlag(key0->spline.ratio.flag, BIT_LINEAR)) return ...
 
// интерполируем
  double relativeT = (t - key0->keyTime) / (key1->keyTime - key0->keyTime);
  double k[4];
  CalcCoefficients(t, k);
  return key0->keyData * k[0] +
            key1->keyData * k[1] +
            key0->spline.ratio.outRatioVector * k[2] +
            key1->spline.ratio.inRatioVector * k[3];
 
Параметры in/outRatioVector и флаги могут настраиваться (как юзером так и втихаря) индивидуально для каждого ключа. Другие сплайны могут потребовать больше соседних точек (один вообще все). В общем нет особого смысла в это вдаваться - есть какая-то математика и она работает.

Если Вы просто хотели убедиться что этот код ляжет под шаблон - то да, конечно ляжет. Что впрочем тоже следует их стартового поста - если для массивов работает (компоненты независимы), то и для структур сработает
« Последнее редактирование: Август 31, 2017, 07:59 от Igors » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #43 : Август 31, 2017, 12:27 »

Поэтому я считаю, что не стоит ориентироваться на QImage.
Я и не собирался что-то из него брать. Просто это хороший пример когда данные разные, но шаблонный класс совершенно неприемлем.
Почему совершенно неприемлем? Можно QImage принять за интерфейс, сделать его методы виртуальными, а классы с конкретными форматами реализовать в шаблонах. И вместо текущего способа создания объекта:
Код
C++ (Qt)
   QImage * image = new QImage(100, 100, QImage::Format_ARGB32);
было бы, например:
Код
C++ (Qt)
   QImage * image = new QFormattedImage<Format_ARGB32>(100, 100);
И теперь прикиньте, если бы Вы захотели расширить QImage каким-то своим форматом, то в каком случае это было бы проще сделать?

Только почему надо делать это для класса Curve? То же подход но для класса Key мне кажется более логичным. Схема
...
Делать можно по-всякому, я же не знаю тонкостей поставленной задачи. В случае с QVector<Key *> в кривой могут оказаться CTypedKey с разными DataType. Это допустимо? Если нет, то как будете это отслеживать?

ViTech, просьба "менее академично".  Время - просто double, делать его тоже шаблонным (так, для примера) не нужно. Использоваться повсеместно будет базовый класс, поэтому ему надо назвать просто и удобно "Curve" (а не тыкать всякий раз в нос "Abstract") и.т.п.
Если тип времени один - это хорошо. Только я бы сделал как минимум "using CurveTime = double;", сегодня оно double, а завтра не совсем double (а то может и совсем не double, например, это время может быть отрицательным?).
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #44 : Сентябрь 01, 2017, 09:49 »

Почему совершенно неприемлем? Можно QImage принять за интерфейс, сделать его методы виртуальными, а классы с конкретными форматами реализовать ...
Так я и говорю что нужен именно интерфейс БЕЗ шаблонов Улыбающийся А в реализации они вполне возможны
 
В случае с QVector<Key *> в кривой могут оказаться CTypedKey с разными DataType. Это допустимо? Если нет, то как будете это отслеживать?
Сделаю конструкторы Key private a Curve friend'ом. Пока перевожу математику сплайнов на template, там тоже не все так уж беоблачно

я же не знаю тонкостей поставленной задачи.
Все тонкости/толстости изложены в стартовом посте, "Дайте больше инфы" часто просто означает "нет идей/решений"
 
Делать можно по-всякому,
Вариант с наследованием от (нешаблонного) интерфейса Key я увидел сразу и уже его реализую. Но меня смущает полное отсутствие каких-либо других путей/возможностей. Конечно реальных, "просто шаблон" или "просто вариант" здесь очевидно не к месту . Поэтому послушать как же "по-всякому" хотелось бы. Но вряд ли услышу, то наверное всего лишь "дежурная фраза"  Улыбающийся
Записан
Страниц: 1 2 [3] 4 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.487 секунд. Запросов: 23.