Просмотр сообщений
|
Страниц: 1 2 [3] 4 5 ... 39
|
31
|
Qt / Многопоточное программирование, процессы / Re: waitForDone
|
: Июль 05, 2021, 09:21
|
Строго говоря, аналогом QThreadPool::waitForDone является QThread::wait. Здесь же требуется дождаться выполнения всех задач в потоке. Возможно, так получится подождать. Сам не пробовал). C++ (Qt) thread->eventDispatcher()->processEvents( QEventLoop::AllEvents )
|
|
|
32
|
Qt / OpenGL / Re: Долгое рисование
|
: Июнь 21, 2021, 21:16
|
Вопрос 2: а что собсно делать если отрисовка не усспевает? Полагаем что после отрисовки каждого (из 25К) объекта вызывается ф-ция IsInterrupred() (достаточно быстрая), без нее все равно не обойтись. И вот она вернула true. Дальше что?
Если в OpenGL отображать каждый элемент отдельно, то никаких ресурсов не хватит). Важным является отображение всей сцены за минимальное количество обращений к контексту OpenGL. Пока рисуется сцена, никаких обработок событий GUI производить не нужно. Формирование кадра отдельно,обработка событий GUI отдельно. Сцена может меняться достаточно интенсивно, после каждого изменения формировать кадр расточительно. Поэтому существует метод update() для отложенного рисования. Если сам процесс формирования кадра занимает 1.6 секунд, то требуется переделка самого процесса отображения. Для 25 тыс. объектов не большой детализации (элементы GUI) приемлемое время не более 20 мс.
|
|
|
33
|
Qt / OpenGL / Re: Долгое рисование
|
: Июнь 21, 2021, 15:20
|
Полагаем что какое-то рисование есть/имеется, насколько оно быстро/оптимально - др вопрос, в любом случае найдется такой объем данных что скорость отрисовки не успеет за активностью юзера. В этой теме хотелось бы поговоритт как отрабатывать такую ситуацию
А что выносить в поток-то тогда)? Основной профит здесь в "прореживании" и "группировке" событий. Если нет независимых этапов, то нечего и "прореживать". Можно хоть миллион потоков сформировать, но, если поток отображения будет их ожидать, то отрисовка и взаимодействие с юзером будет тупить.
|
|
|
34
|
Qt / OpenGL / Re: Долгое рисование
|
: Июнь 21, 2021, 13:28
|
Вопрос имеет архитектурный подтекст. Как минимум, имеется несколько независимых этапа (можно выделить и больше):
- преобразование исходных данных в элементы отображаемой сцены, - преобразование элементов сцены в данные для конвейера OpenGL, - преобразование данных для конвейера OpenGL в кадр.
Эти этапы можно (нужно) выполнять независимо друг от друга. При этом нет необходимости производить отображение при каждом элементарном изменении исходных данных. На каждом этапе можно (нужно) забирать только изменения с предыдущего этапа (например, очередь изменений). При этом события можно "проредить" (например, создание/удаление объекта и последовательное изменение одного и того же свойства и т.д.).
В OpenGL есть трудности с разделением функциональности по подготовке данных для конвейера и формированием кадра. Если разделить все этапы, то "замерзание" GUI будет зависеть только от последнего этапа формирования кадра. А он будет зависеть от выбранной стратегии отображения - использования функциональности разных версий OpenGL, реализации шейдерных программ и т.п.
|
|
|
36
|
Программирование / Алгоритмы / Re: Найти дырки
|
: Июнь 09, 2021, 14:56
|
Триангулировать "комплексные полигоны", т.е. с числом вертексов >= 5, задаются такой полилинией
А в чем трудность в триангуляции такого полигона? Вроде, никаких артефактов для таких форм не замечал. Разве что если специальное сглаживание границ производится. В любом случае, если решать "в лоб", то определить, находится ли один контур внутри другого, можно с помощью простой проверки - находится ли любая точка одного контура внутри геометрии другого. Можно ещё через анализ ребер определить, но тут подумать нужно)... А если кидаться ссылками, то можно здесь что-то полезное почерпнуть https://doc.cgal.org/latest/Manual/packages.html#PartPolygonshttps://doc.cgal.org/latest/Straight_skeleton_2/Straight_skeleton_2_2Create_skeleton_and_offset_polygons_2_8cpp-example.html
|
|
|
37
|
Программирование / Алгоритмы / Re: Найти дырки
|
: Июнь 09, 2021, 13:49
|
А где (злополучная) p1 - неизвестно. Напр она может принадлежать контуру дырки...
Не получается уловить контекст вопроса). Точка может быть сразу в нескольких контурах одновременно. Исходная то задача какая? Сформировать контуры для отображения полигонов с дырами? Или просто независимые контуры получить? Если контуры для отображения полигонов с дырами, то там ещё немного с ребрами поработать нужно, тогда можно будет определить, когда контур будет дыркой, а когда нет.
|
|
|
38
|
Программирование / Алгоритмы / Re: Найти дырки
|
: Июнь 09, 2021, 12:13
|
Реализация может быть такой.
::std::unordered_map< Point, size_t > поможет! Только нужно определить ::std::hash для типа QPointF.
1. Для каждой точки посчитать количество вхождений в последовательность (сформировать ::std::unordered_map< QPointF, size_t >). 2. Итерировать одновременно справа и слева до точек с количеством включений больше 1. - если точки совпали, то контур или линию получили - если не совпали -- есть самопересечение!
|
|
|
39
|
Программирование / Алгоритмы / Re: Найти дырки
|
: Июнь 09, 2021, 12:00
|
Вроде, не сложная задача).
Если заданы точки p1,p2,p3,p4,p5,p6,p4,p7,p8,p3,p9,p1 то контуры будут следующими
p1,p2,(p3,(p4,p5,p6,p4),p7,p8,p3), p9,p1
p4,p5,p6,p4 p3,p4,p7,p8,p3 p1,p2,p3,p9,p1
То есть повторяющиеся точки - начало нового контура или линии между контурами. Расставляем "скобки". Всё что внутри извлекаем, оставляя только одну точку. В результате две точки - линия между контурами, больше двух - контур.
|
|
|
40
|
Программирование / С/C++ / Re: Ассоциации (?)
|
: Апрель 28, 2021, 17:27
|
Если нужен свой велик для С++98, то можно что-то типа этого использовать C++ (Qt) template < typename _Type, int > struct EnumName { static const char * name () { return "<Unknown>"; } }; #define ENUM_NAME( Enum, param_value, param_name ) \ template <> struct EnumName< Enum, param_value > { static const char * name () { return param_name; } }; \ template < typename _Enum, int _value > struct EnumNameHelper { static const char * name ( int value ) { if ( _value == value ) return EnumName< _Enum, _value >::name(); else if ( _value > value ) return EnumNameHelper< _Enum, _value - 1 >::name( value ); else return "<Incorrect>"; } }; template < typename _Enum > struct EnumNameHelper< _Enum, -1 > { static const char * name ( int ) { return "<Corrupted>"; } }; template < typename _Enum > const char * enumValueName ( _Enum value ) { return EnumNameHelper< _Enum, param_Count >::name( value ); }
C++ (Qt) enum MyEnum { param_Amount, param_Velocity, param_Color, param_Coordinate, param_Count }; // или так писать template <> struct EnumName< MyEnum, param_Amount > { static const char * name () { return "Amount"; } }; // или так ENUM_NAME( MyEnum, param_Velocity, "Velocity" ) ENUM_NAME( MyEnum, param_Color, "Color" ) ENUM_NAME( MyEnum, param_Coordinate, "Coordinate" ) #include <iostream> int main ( int narg, char ** vargs ) { // В runtime тоже работает for ( size_t i = 0; i < param_Count; ++i ) ::std::cout << enumValueName< MyEnum >( i ) << ::std::endl; return 0; }
|
|
|
41
|
Программирование / С/C++ / Re: чтение и запись битовых структур данных
|
: Апрель 28, 2021, 07:21
|
На эту тему писал свой велик. Продукт проприетарный, поэтому пока опишу только сами подходы. Реализовывалась работа со структурами специфичного формата данных http://www.eurocontrol.int/services/asterixФормат данных описывается в параметрическом виде, например, xml XML <DataItem id="020"> <DataItemName>Target Report Descriptor</DataItemName> <DataItemDefinition>Type and characteristics of the radar data as transmitted by a radar station.</DataItemDefinition> <DataItemFormat desc="Variable length Data Item comprising a first part of oneoctet, followed by one-octet extents as necessary."> <Variable> <Fixed length="1"> <Bits bit="8"> <BitsShortName>TYP</BitsShortName> <BitsValue val="0">Plot</BitsValue> <BitsValue val="1">Track</BitsValue> </Bits> <Bits bit="7"> <BitsShortName>SIM</BitsShortName> <BitsValue val="0">Actual plot or track</BitsValue> <BitsValue val="1">Simulated plot or track</BitsValue> </Bits> <Bits from="6" to="5"> <BitsShortName>SSRPSR</BitsShortName> <BitsValue val="0">No detection</BitsValue> <BitsValue val="1">Sole primary detection</BitsValue> <BitsValue val="2">Sole secondary detection</BitsValue> <BitsValue val="3">Combined primary and secondary detection</BitsValue> </Bits> <Bits bit="4"> <BitsShortName>ANT</BitsShortName> <BitsValue val="0">Target report from antenna 1</BitsValue> <BitsValue val="1">Target report from antenna 2</BitsValue> </Bits> <Bits bit="3"> <BitsShortName>SPI</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Special Position Identification</BitsValue> </Bits> <Bits bit="2"> <BitsShortName>RAB</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Plot or track from a fixed transponder</BitsValue> </Bits> <Bits bit="1" fx="1"> <BitsShortName>FX</BitsShortName> <BitsValue val="0">End of Data Item</BitsValue> <BitsValue val="1">Extension into first extent</BitsValue> </Bits> </Fixed> <Fixed length="1"> <Bits bit="8"> <BitsShortName>TST</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Test target indicator</BitsValue> </Bits> <Bits from="7" to="6"> <BitsShortName>DS1DS2</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Unlawful interference (code 7500)</BitsValue> <BitsValue val="2">Radio-communication failure (code 7600)</BitsValue> <BitsValue val="3">Emergency (code 7700)</BitsValue> </Bits> <Bits bit="5"> <BitsShortName>ME</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Military emergency</BitsValue> </Bits> <Bits bit="4"> <BitsShortName>MI</BitsShortName> <BitsValue val="0">Default</BitsValue> <BitsValue val="1">Military identification</BitsValue> </Bits> <Bits from="3" to="2"> <BitsShortName>spare</BitsShortName> <BitsName>spare bits set to 0</BitsName> <BitsConst>0</BitsConst> </Bits> <Bits bit="1" fx="1"> <BitsShortName>FX</BitsShortName> <BitsValue val="0">End of Data Item</BitsValue> <BitsValue val="1">Extension into next extent</BitsValue> </Bits> </Fixed> </Variable> </DataItemFormat> </DataItem> <DataItem id="040"> <DataItemName>Measured Position in Polar Coordinates</DataItemName> <DataItemDefinition>Measured position of an aircraft in local polar coordinates.</DataItemDefinition> <DataItemFormat desc="Four-octet fixed length Data Item."> <Fixed length="4"> <Bits from="32" to="17"> <BitsShortName>RHO</BitsShortName> <BitsUnit max="512" scale="0.0078125">NM</BitsUnit> </Bits> <Bits from="16" to="1"> <BitsShortName>THETA</BitsShortName> <BitsUnit scale="0.0054931640625">deg</BitsUnit> </Bits> </Fixed> </DataItemFormat> </DataItem>
Для этого файла пишется парсер, который формирует структуры с описанием формата данных. Сами данные представляются в виде последовательности байт, которая обобщена между полями структуры. Поле структуры - это, собственно, ссылка на описание формата данных и на место размещения этих данных в памяти. Если требуется работать с динамически изменяющимися структурами, то доступ к полям в runtime осуществляется по имени примерно так C++ (Qt) record.item( "040" ).field( "RHO" );
Если состав структуры известен на этапе компиляции, то по формату xml можно сгенерировать исходники, как предлагал Old или так C++ (Qt) struct Record { Bytes m_bytes; // BitField< Byte number, First bit, Last bit > BitField<0, 0, 1> flag; BitField<0, 1, 5> mode; BitField<0, 5, 14> address; Record () : flag( m_bytes ), mode( m_bytes ), address( m_bytes ) {} };
|
|
|
43
|
Программирование / Алгоритмы / Re: Восстановление синусоиды
|
: Март 18, 2021, 21:52
|
Известно, что исходный сигнал это синусоида с неким постоянным периодом. Объем данных - массив из примерно 500-1000 сэмплов. В пределах этого массива сигнал "закольцован", т.е. его начало гарантированно совпадает с концом по значениям амплитуды. Вот требуется восстановить исходную синусоиду (период в общем случае не известен). Есть ли какие-либо известные алгоритмы для этого? "гугл не помог" пока Есть же обычное преобразование Фурье, которое выделит и период и фазовый сдвиг синусоиды. Тем более, что начало гарантированно совпадает с концом по амплитуде (периоду). А если количество сэмплов будет кратно степени 2, то можно и fft алгоритм применить.
|
|
|
44
|
Qt / Многопоточное программирование, процессы / Re: Thread tried to wait on itself
|
: Март 15, 2021, 15:12
|
Спасибо за напоминание, что "хэндл" живет в потоке, в котором он создан)) Но откуда следует, что остановить поток (quit) можно только из того потока, откуда он был запущен?
Это QObject, с которым могут связаны какие-нибудь сигналы, и слоты вызываются в основном потоке. Сама обертка QThread не помечена, как thread-safe, таким образом одновременный вызов методов из разных потоков может привести к плачевным результатам. Иначе говоря, код C++ (Qt) Worker::~Worker() { workerThread->quit(); workerThread->deleteLater(); }
корректен? Я считаю, что некорректен, и не стал бы его использовать, так как содержит потенциальную проблему - сегодня работает, а завтра ...
|
|
|
45
|
Qt / Многопоточное программирование, процессы / Re: Thread tried to wait on itself
|
: Март 15, 2021, 13:11
|
Вот пример по шагам C++ (Qt) // деструктор вызывается в потоке workerThread Worker::~Worker() { // в потоке workerThread обращаемся к объекту главного потока workerThread // (возможны проблемы с конкурентным доступом) с командой завершения QEventLoop workerThread->quit(); // в потоке workerThread обращаемся к объекту главного потока workerThread // (возможны проблемы с конкурентным доступом) с командой ожидания завершения активности данного потока // получаем игнорирование команды и не завершенный поток workerThread workerThread->wait(); // в очередь главный поток отправляем событие удаления объекта workerThread, // которое может быть обработано в главном потоке даже до завершения этого деструктора, // когда активность потока workerThread фактически не завершена. workerThread->deleteLater(); }
|
|
|
|
|