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

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

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

Сообщений: 11445


Просмотр профиля
« : Август 23, 2017, 08:39 »

Добрый день

Есть класс Curve (кривая) которая задается контейнером "ключей" (контрольных точек) + типом сплайна. Curve выдает значение параметра для заданного времени t (т.е. просто (редактируемый график). Значения бывают 3 типов

- число (double)
- вектор (3 double x, y, z)
- цвет с альфой (4 uchar)

Реализован это класс был в незапамятные времена, наверное еще на паскале, потом кое-как переведен на С, и вот дожил до наших дней
Код
C++ (Qt)
struct Curve {
// общие данные для всех типов кривых
int dataType;  // тип значения кривой
union {
  DoubleCurve * doubleCurve;
  VectorCurve * vectorCurve;
  СolorCurve * colorCurve;
};
};
 
Возможно тут Вы ожидали что каждая кривая хранит контейнер значений своего типа - но это не так. VectorCurve хранит 3 контейнера для каждой компоненты, СolorCurve - 4 контейнера
Код
C++ (Qt)
struct VectorCurve {
 ...
 Container<Key> xList;
 Container<Key> yList;
 Container<Key> zList;
};
 
struct Key {
 double time;
 double val;
 union {
    // опции сплайна
 };
};
Ну и работа с такими структурами мгновенно сваливается в бесконечное свитчевание по dataType. Масса кода дублируетcя т.к. его надо повторять для каждого контейнера x, y, z (a, r, g, b). Напр вместо одной вставки ключа - 3 или даже 4. Это уже просто неграмотно.

Очевидно нужны template. Но вот почему-то ничего хорошего не жду. Охотно играются с финтифлюшками на темплейтах, дают советы "на будущИе". но вот когда доходит до дела - следуют рекомендации типа " делай сам" или более мягкое "работает? - так ото не трогай". Ну ладно, посмотрим, может я и неправ.

Так как же привести это в божеский вид ?

Спасибо
Записан
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


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

А вот кто и как эту курву пользует? Тут контекст использования играет ключевую роль.
Не зная оного, можно давать лишь абстрактные советы, насколько я понял, изрядно Вас нервирующие.

Типа (ну кроме template), сделать Curve абстрактным классом и...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

А вот кто и как эту курву пользует? Тут контекст использования играет ключевую роль.
В стартовом посте написано
Есть класс Curve (кривая) которая задается контейнером "ключей" (контрольных точек) + типом сплайна. Curve выдает значение параметра для заданного времени t (т.е. просто (редактируемый график).
Если так, то как минимум налицо простейший базовый ф-ционал: добавить/удалить контрольyую точку(и), изменить ее время и/или значение. И этого совершенно достаточно для построения, разработки структур данных (данная тема). И объяснять это специально не нужно, т.к. здесь малограмотных нет.

Не зная оного, можно давать лишь абстрактные советы, насколько я понял, изрядно Вас нервирующие.
Я совсем не против абстракции, ведь данные что я привел абстрактны - реальные структуры содержат много десятков членов. А вот обычная песенка сачка "надо знать задачу" - да, нервирует  Улыбающийся

Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



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

Может вместо union сделать 3 наследника или QVariant?

Зачем вы разные кривые в одну структуру засунули?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



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

Структуру поменять на класс, нечего с полями работать.
Интерфейс типа:
Цитировать
Curve c;
void c.setDoubles(QList<double>);
void c.setVectors(QList<Qpoint3D>);
void c.setColors(QList<QColor>);
double c.getDouble(QDateTime t);
Qvector3d c.getVector(QDateTime t);
QColor c.getColor(QDateTime t);

Вроде все просто, напрямую работать со структурой, это плодить одинаковый код.
Или тут есть некая хитрость? Опишите каким бы вы хотели видеть интерфейс, а мы подумаем как это реализовать.
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #5 : Август 23, 2017, 14:02 »

Я бы вообще сделал класс сплайн(или готовый взял) с тремя функциями:
Цитировать
class Spline {
static double     c.getDouble(const QList<double> &data,     const QDateTime t);
static Qpoint3D c.getVector (const QList<Qpoint3D> &data, const QDateTime t);
static QColor     c.getColor   (const QList<QColor> &data,     const QDateTime t);
};
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #6 : Август 23, 2017, 14:05 »

А вот кто и как эту курву пользует? Тут контекст использования играет ключевую роль.
В стартовом посте написано

Не стоит принижать роль контекста/вариантов использования. Я тоже считаю, что это имеет важное значение. В частности набор и тип векторов в кривой задаётся на этапе компиляции или может меняться в рантайме? В объекте типа Curve в рантайме можно поменять dataType и соответственно вектор данных? Доступ к элементам кривой предпочтителен в виде набора параметров в заданной точке, или желателен/необходим доступ к параметру в виде вектора. В зависимости ответов на эти вопросы реализация класса кривой, её компонентов, и работа с ними может различаться кардинально.
Записан

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

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Август 23, 2017, 17:14 »

В частности набор и тип векторов в кривой задаётся на этапе компиляции или может меняться в рантайме? В объекте типа Curve в рантайме можно поменять dataType и соответственно вектор данных?
Если юзер создал кривую типа "число" - то он никак не сможет преобразовать ее в тип "вектор" или "цвет", и наоборот. Можно только удалить кривую и создать новую, это нормально. А вот поменять тип сплайна (см класс Key) может. Сейчас тип сплайна один для всей кривой, но есть желание чтобы можно было задавать тип сплайна для каждого ключа (контрольной точки) индивидуально. 

Доступ к элементам кривой предпочтителен в виде набора параметров в заданной точке, или желателен/необходим доступ к параметру в виде вектора.
Да, есть векторные операции. напр сместить кривую или вписать ее в диапазон по х/y. Но они не крытычны, могут быть спокойно сделаны в цикле for. Главное - чтобы их (и другиx) не пришлось мучительно расписывать (дублировать) для каждого типа кривой.

В зависимости ответов на эти вопросы реализация класса кривой, её компонентов, и работа с ними может различаться кардинально.
Ну да, для точного экспертного анализа нужны точные данные - а как же иначе?  Увы, мой жизненный опыт показывает обратное: чем больше наводящих вопросов - тем меньше содержательного.

Я бы вообще сделал класс сплайн(или готовый взял) с тремя функциями:
Цитировать
class Spline {
static double     c.getDouble(const QList<double> &data,     const QDateTime t);
static Qpoint3D c.getVector (const QList<Qpoint3D> &data, const QDateTime t);
static QColor     c.getColor   (const QList<QColor> &data,     const QDateTime t);
};
Опять "резвости" хоть отбавляй Улыбающийся Вот параметры всего лишь одного из сплайнов (для каждого ключа)
Код
C++ (Qt)
double inRatioVector; // Incoming Vector
double outRatioVector; // Outgoing Vector
double inRatioAngle; // Incoming Angle
double outRatioAngle; // Outgoing Angle
double inWeight; // Incoming Weight
double outWeight; // Outgoing Weight
int ratioFlags; // Flags governing the interpolation
 
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



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

Доступ к элементам кривой предпочтителен в виде набора параметров в заданной точке, или желателен/необходим доступ к параметру в виде вектора.
Да, есть векторные операции. напр сместить кривую или вписать ее в диапазон по х/y. Но они не крытычны, могут быть спокойно сделаны в цикле for. Главное - чтобы их (и другиx) не пришлось мучительно расписывать (дублировать) для каждого типа кривой.

Здесь, похоже, возникли непонятки из-за многозначности слова "вектор". Я имел в виду вектор как контейнер для каждого параметра. Например:

Код
C++ (Qt)
struct XYColorCurve
{
   vector<double> x;
   vector<double> y;
   vector<Color> c;
}
 

И "перпендикулярное" предыдущему представление:
Код
C++ (Qt)
struct XYColor
{
   double x;
   double y;
   Color c;
}
 
using XYColorCurve = vector<XYColor>;
 

Какой из двух вариантов предпочтителен? Это как раз зависит от вариантов использования. Например, для передачи координат в буферы OpenGL может быть предпочтителен первый вариант. А если больше приходится работать с отдельными "точками" - то второй.

В зависимости ответов на эти вопросы реализация класса кривой, её компонентов, и работа с ними может различаться кардинально.
Ну да, для точного экспертного анализа нужны точные данные - а как же иначе?  Увы, мой жизненный опыт показывает обратное: чем больше наводящих вопросов - тем меньше содержательного.

В С++ способы организации классов и работы с ними довольно сильно различаются для случаев "compile time" и "run time". Грубо говоря: шаблоны - они про  "compile time", базовый класс -> наследник + виртуальные методы - они про "run time". Можно попытаться это совместить, но не факт что из этого что-то хорошее выйдет. Поэтому и нужно заранее знать, что для чего делается и как использоваться будет.

Опять "резвости" хоть отбавляй Улыбающийся Вот параметры всего лишь одного из сплайнов (для каждого ключа)
Код
C++ (Qt)
double inRatioVector; // Incoming Vector
double outRatioVector; // Outgoing Vector
double inRatioAngle; // Incoming Angle
double outRatioAngle; // Outgoing Angle
double inWeight; // Incoming Weight
double outWeight; // Outgoing Weight
int ratioFlags; // Flags governing the interpolation
 

Вот этот набор параметров он формируется в  "compile time" или пользователь может его изменять в "run time"? Например, удалить из этого набора inWeight,  outWeight и добавить какой-нибудь Color?

Если набор параметров формируется в "compile time", то чем не подходит грубое:
Код
C++ (Qt)
struct RatioWeight
{
   double inRatioVector; // Incoming Vector
   double outRatioVector; // Outgoing Vector
   double inRatioAngle; // Incoming Angle
   double outRatioAngle; // Outgoing Angle
   double inWeight; // Incoming Weight
   double outWeight; // Outgoing Weight
   int ratioFlags; // Flags governing the interpolation
}
 
using RatioWeightCurve = map<Key, RatioWeight>;
 
Записан

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

Сообщений: 11445


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

ViTech, для краткости цитирование опускаю. Разумеется хотелось бы иметь нормальную структуру (а не кучу разобщенных массивов). Предположим есть 1 тип данных (напр вектор) и 1 тип сплайна. Тогда
Код
C++ (Qt)
struct Key {
 double time;  // время  
 Vector vec;    // данные
 
 int splineOption1;   // параметры сплайна
 ...
 double splineOptionN;
};
Ну и кривая - просто контейнер Key, возможно еще с доп данными для всех ключей. Однако данные могут быть 3 типов, а сплайны 6 типов. Собсно это первое (и наверное главное) что хотят от template, задача очень банальна.

Сейчас по существу реализован вариант с "расслоением", т.е. заводится контейнер на каждую компоненту вектора (x, y, z). Очевидно такая работа "покомпонентно" весьма затратна с любой точки зрения. Помнится Вы говорили что template схопывает код - ну вот Вам и карты в руки, схлопывайте.
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



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

Однако данные могут быть 3 типов, а сплайны 6 типов. Собсно это первое (и наверное главное) что хотят от template, задача очень банальна.
Жуткие структуры с жуткой логикой надо оборачивать в класс, а потом заменить. По шаблону могу предположить:
Код:
template<class T> Curve 
{
  QMap<Key, T> data;
public:
  void getData(&T, QDateTime t)
}

Curve<QVector3D> c1;
Curve<QColor> c2;
Curve<double> c3;
если c1,c2,c3 нужно засунуть зачем то в контейнер, сделайте базовый класс от которого они будут унаследованы. Так как шаблоные функции не могут быть виртуальными, придется конкретизировать наследника(или может можно как нибудь обмануть плюсы?)
Код:
double data;
 static_cast<Curve<double>* >(curveBasePointer)->getData(&data);

Я так понял у вас типа хэш массива, QMap<Key, QVector3D> будет быстрее доступ к элементу чем в трёх итераторах искать QMap<Key, int x>, QMap<Key, int y>, QMap<Key, int z>.

Почти для всех типов QVector3D, QColor, double умножение деление есть, так что сплайн будет работать.
Ну разве только у вас не QColor, а struct XYColor{    double x;    double y;    Color c; }. Тогда придется в этой структуре определить базовые операции.
« Последнее редактирование: Август 24, 2017, 09:17 от deMax » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Код:
template<class T> Curve 
{
  QMap<Key, T> data;
public:
  void getData(&T, QDateTime t)
}
Это только тип данных, а есть еще тип сплайна - оставим сишный union (со всеми вытекающими)? И время - просто double (а не QDateTime), не простираются мои кривые неделями и годами  Улыбающийся

Код
C++ (Qt)
Curve<QVector3D> c1;
Curve<QColor> c2;
Curve<double> c3;
 
Ни за что не додумался бы так сделать! Улыбающийся Только вот что я буду делать с зоопарком разных (с точки зрения компилятора) классов - хз.

сделайте базовый класс от которого они будут унаследованы. Так как шаблоные функции не могут быть виртуальными, придется конкретизировать наследника..
Наконец-то хоть слабые намеки на содержательную часть. Ну хорошо, допустим я оперирую с базовым классом
Код
C++ (Qt)
struct Curve {
 ...
 ??? GetData( double time ) const;   // возвращает значение для времени time
 void SetData( double time. const ??? & value );   // устанавливает значение для времени time
 ...
};
 
Что вместо вопросиков?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



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

Это только тип данных, а есть еще тип сплайна - оставим сишный union (со всеми вытекающими)? И время - просто double (а не QDateTime), не простираются мои кривые неделями и годами  Улыбающийся
QDateTime - для примера т.к. это универсально, в данном вопросе не важно.

Я правильно понял задачу? Задача:
есть класс который хранил либо массив точек, либо массив чисел, либо массив цветов. Для каждой точки массива устанавливается один из видов сплайна(всего их минимум 6). Требуется по времени извлечь аппроксимированную точку.

Цитировать
Непонимающий GetData( double time ) const;   // возвращает значение для времени time
Что вместо вопросиков?
хороший наводящий вопрос, будет QVariant  Подмигивающий   а код будет примерно такой:
Код:
QVariant GetData( double time ) const
switch(currentType) {
case (DOUBLE): double d; static_cast<Curve<double>* >(this)->getData(&d); return Qvariant(d);
....
« Последнее редактирование: Август 24, 2017, 11:22 от deMax » Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



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

Если QVariant не нравиться, можно создать класс типа UnionData{union {double d; Color c; Vector3d v}} с тремя конструкторами и тремя функциями get и математикой(для сплайна). Тогда и шаблон в принципе не нужен.

Цитировать
Ну хорошо, допустим я оперирую с базовым классом
в принципе можно вместо curve->setData(d), писать ((Curve<double>)curve)->setData(d); если это не внутри шаблона, вы и так знаете тип.
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



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

Итого:
class UnionData{union {double d; Color c; Vector3d v}} с тремя конструкторами и тремя функциями get и математикой(для сплайна)
class Key { double time, ..... }
Spline { QMap<Key, UnionData> map; void set(Key, UnionData); UnionData get(Key); }
Записан
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


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