Просмотр сообщений
|
Страниц: 1 2 [3] 4 5 ... 39
|
31
|
Программирование / Алгоритмы / 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
|
|
|
32
|
Программирование / Алгоритмы / Re: Найти дырки
|
: Июнь 09, 2021, 13:49
|
А где (злополучная) p1 - неизвестно. Напр она может принадлежать контуру дырки...
Не получается уловить контекст вопроса). Точка может быть сразу в нескольких контурах одновременно. Исходная то задача какая? Сформировать контуры для отображения полигонов с дырами? Или просто независимые контуры получить? Если контуры для отображения полигонов с дырами, то там ещё немного с ребрами поработать нужно, тогда можно будет определить, когда контур будет дыркой, а когда нет.
|
|
|
33
|
Программирование / Алгоритмы / Re: Найти дырки
|
: Июнь 09, 2021, 12:13
|
Реализация может быть такой.
::std::unordered_map< Point, size_t > поможет! Только нужно определить ::std::hash для типа QPointF.
1. Для каждой точки посчитать количество вхождений в последовательность (сформировать ::std::unordered_map< QPointF, size_t >). 2. Итерировать одновременно справа и слева до точек с количеством включений больше 1. - если точки совпали, то контур или линию получили - если не совпали -- есть самопересечение!
|
|
|
34
|
Программирование / Алгоритмы / 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
То есть повторяющиеся точки - начало нового контура или линии между контурами. Расставляем "скобки". Всё что внутри извлекаем, оставляя только одну точку. В результате две точки - линия между контурами, больше двух - контур.
|
|
|
35
|
Программирование / С/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; }
|
|
|
36
|
Программирование / С/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 ) {} };
|
|
|
38
|
Программирование / Алгоритмы / Re: Восстановление синусоиды
|
: Март 18, 2021, 21:52
|
Известно, что исходный сигнал это синусоида с неким постоянным периодом. Объем данных - массив из примерно 500-1000 сэмплов. В пределах этого массива сигнал "закольцован", т.е. его начало гарантированно совпадает с концом по значениям амплитуды. Вот требуется восстановить исходную синусоиду (период в общем случае не известен). Есть ли какие-либо известные алгоритмы для этого? "гугл не помог" пока Есть же обычное преобразование Фурье, которое выделит и период и фазовый сдвиг синусоиды. Тем более, что начало гарантированно совпадает с концом по амплитуде (периоду). А если количество сэмплов будет кратно степени 2, то можно и fft алгоритм применить.
|
|
|
39
|
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(); }
корректен? Я считаю, что некорректен, и не стал бы его использовать, так как содержит потенциальную проблему - сегодня работает, а завтра ...
|
|
|
40
|
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(); }
|
|
|
41
|
Qt / Многопоточное программирование, процессы / Re: Thread tried to wait on itself
|
: Март 15, 2021, 12:54
|
Всё даже может быть намного хуже, если полностью прочитать документацию)). Note that deleting a QThread object will not stop the execution of the thread it manages. Deleting a running QThread (i.e. isFinished() returns false) will result in a program crash. Wait for the finished() signal before deleting the QThread.
|
|
|
42
|
Qt / Многопоточное программирование, процессы / Re: Thread tried to wait on itself
|
: Март 15, 2021, 12:49
|
Собственно, это всего лишь предупреждение, и wait в этом случае ничего не делает. Убираем wait, остается выход из циклов обработки событий quit и отложенное удаление объекта QThread с помощью deleteLater. Вопрос остается - это правильно?
Удаление объекта QThread само по себе не завершает активность (Note that deleting a QThread object will not stop the execution of the thread it manages.). Метод wait же ожидает завершения активности. В общем случае, второй вариант допускает "подвешивание" незавершенных активностей, особенно если они реализованы в виде бесконечных циклов (когда реализована собственная версия метода MyThread::run() ).
|
|
|
43
|
Qt / Многопоточное программирование, процессы / Re: Thread tried to wait on itself
|
: Март 15, 2021, 11:42
|
ждать в себе завершения самого себя бессмысленно)).
Это ж и есть ответ на вопрос. Вызов деструктора Worker производится в активности потока workerThread, который и предлагается подождать с помощью workerThread->wait(). В первом же варианте вызов деструктора Controller производится в активности другого (скорее всего, главного) потока, связанного с объектом Controller. Здесь можно и подождать workerThread->wait().
|
|
|
45
|
Qt / Многопоточное программирование, процессы / Re: Не масштабится :-(
|
: Март 10, 2021, 16:48
|
Такое "деление на диапазоны" (иногда называют "stencil") совсем не бесплатно/безобидно. И предрассчитать его получается далеко не всегда.
Найти (или предположить) диапазон значений индексов - откуда здесь могут быть большие затраты? Я бы делал просто "мешком локеров", напр для Qt
Любые локеры сделают только хуже. Здесь может только помочь распараллеливание безо всяких локеров. Все потоки пробегаются по всему циклу, только производят вычисления каждый в своем диапазоне. В своих задачах я формирую массивы типа faces заранее (увеличиваю только при необходимости), чтобы не иметь потерь на new|delete. Использование заранее инициированного пула потоков и ожидание на барьере после первого цикла и далее после второго ничтожно по сравнению с затратами на вычисления. И да, расчеты нормалей, как правило делают на GPU.
|
|
|
|
|