Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Algorytm generowania koloru RGB na podstawie niedużych liczb całkowitych.

Ostatnio zmodyfikowano 2014-06-21 17:03
Autor Wiadomość
akwes
Temat założony przez niniejszego użytkownika
[C++] Algorytm generowania koloru RGB na podstawie niedużych liczb całkowitych.
» 2014-06-21 00:10:29
Witam,

Mam przed sobą taki problem: rysuję sobie wykres i słupki muszą mieć różne kolory (dobrze odróżniające słupki). Chciałbym generować kolor słupka na podstawie kolejnego numeru. Czyli aby dla wartości 1,2,3... generowało całkiem sensownie różne od siebie kolorki. Problem polega na tym, że słupków może być nawet i 50. Staram się w różne sposoby chodzić po przestrzeni RGB, ale żadnych sensownych efektów nie uzyskałem.

Generowanie kolorów losowo odpada z racji tego, że mogą wyjść bardzo podobne do siebie kolory obok siebie.

Póki co rozwiązuje to stworzeniem 10 podstawowych jasnych kolorów i na ich podstawie generowaniu kolejnych 5 wyraźnie ciemniejących odcieni.
P-112424
DejaVu
» 2014-06-21 00:36:52
Wygeneruj wykres z 50-100 kolorami w Excelu i sprawdź jak sobie radzi z tym Microsoft. Niewykluczone, że rozwiązanie Microsoftu nie będzie powalało na kolana, co znacznie powinno ułatwić ci zaimplementowanie Twojego algorytmu :) W zasadzie możesz sobie wygenerować std::vector kolorów tak:
C/C++
std::vector < unsigned > vKolory( 100 );
for( size_t i = 0; i < vKolory.size(); ++i )
     vKolory[ i ] =( 0xffffff / vKolory.size() - 1 ) * i;

A potem wykonać np taki algorytm:
C/C++
std::vector < unsigned > vTmp = vKolory;
unsigned iSkok = static_cast < unsigned >( ceil( sqrt( vTmp.size() ) ) );
for( size_t i = 0; i < vTmp.size(); ++i )
     vKolory[ i ] = vTmp[( i * iSkok ) + i % iSkok ) % vTmp.size() ];


(może się nie kompilować - nawiasy na chybił trafił wstawiałem ;p)
P-112425
pekfos
» 2014-06-21 00:42:35
Może użyj kolorów HSV i potem konwertuj na RGB?
P-112427
DejaVu
» 2014-06-21 01:45:55
C/C++
#include <SFML/Graphics.hpp>
#include <cmath>
#include <vector>

void generujKolory( std::vector < unsigned >& _vKolory, int _iSkokSkladowej )
{
    // Generowanie kolorów.
    _vKolory.clear();
    int iSkok = _iSkokSkladowej;
    for( signed r = 0xff; r >= 0; r -= iSkok )
    for( signed g = 0xff; g >= 0; g -= iSkok )
    for( signed b = 0xff; b >= 0; b -= iSkok )
    {
        _vKolory.push_back(((( r << 8 ) + g ) << 8 ) + b );
        printf( "%3d, %3d, %3d\n", r, g, b );
    }
   
    // Zmiana kolejności kolorów.
    std::vector < unsigned > vTmp = _vKolory;
    unsigned iKwadrat = static_cast < unsigned >( ceil( sqrt( vTmp.size() ) ) );
    for( size_t i = 0; i < vTmp.size(); ++i )
    {
        int iIndeks =(( i % iKwadrat ) * iKwadrat + i ) % vTmp.size();
        _vKolory[ i ] = vTmp[ iIndeks ];
        printf( "%d => %d\n", i, iIndeks );
    } //for
}

int main()
{
    std::vector < unsigned > vKolory;
    generujKolory( vKolory, 50 );
   
    sf::RenderWindow okno( sf::VideoMode( 800, 600 ), "Kurs SFML 2.0 - http://cpp0x.pl" );
    while( okno.isOpen() )
    {
        // Obsługa zdarzeń.
        sf::Event ev;
        while( okno.pollEvent( ev ) )
        {
            if( ev.type == sf::Event::Closed )
                 okno.close();
           
        }
        okno.clear();
        // Renderowanie kolorów.
        unsigned iSkok = static_cast < unsigned >( ceil( sqrt( vKolory.size() ) ) );
        for( int i = 0; i < vKolory.size(); ++i )
        {
            sf::RectangleShape shape;
            unsigned kolor = vKolory[ i ];
            unsigned r =( kolor >> 16 ) & 0xff;
            unsigned g =( kolor >> 8 ) & 0xff;
            unsigned b =( kolor >> 0 ) & 0xff;
            shape.setFillColor( sf::Color( r, g, b ) );
            shape.setSize( sf::Vector2f( 40, 40 ) );
            shape.setPosition(( i % iSkok ) * 40,( i / iSkok ) * 40 );
            okno.draw( shape );
        }
       
        okno.display();
    }
   
    return 0;
}

Efekt:
Wygenerowana paleta kolorów do wykresów
P-112428
DejaVu
» 2014-06-21 02:12:22
C/C++
void generujKolory( std::vector < unsigned >& _vKolory, int _iSkokSkladowej )
{
    _vKolory.clear();
    // Generujemy kolory.
    int iKolorowNaSkladowa = 0xff / _iSkokSkladowej;
    for( signed r = 0xff; r >= 0; r -= _iSkokSkladowej )
    for( signed g = 0xff; g >= 0; g -= _iSkokSkladowej )
    for( signed b = 0xff; b >= 0; b -= _iSkokSkladowej )
    {
        _vKolory.push_back(((( r << 8 ) + g ) << 8 ) + b );
        printf( "%3d, %3d, %3d\n", r, g, b );
    }
   
    // Zmieniamy kolejność kolorów.
    std::vector < unsigned > vTmp = _vKolory;
    int iKolor = 0;
    for( size_t k = 0; k < iKolorowNaSkladowa; ++k )
    for( size_t i = k; i < vTmp.size(); i += iKolorowNaSkladowa )
    if( iKolor < _vKolory.size() )
    {
        int iIndeks = i % vTmp.size();
        printf( "%d => %d\n", iKolor, iIndeks );
        _vKolory[ iKolor++ ] = vTmp[ iIndeks ];
    } //for
}
Tutaj efekt zastosowania powyższej funkcji do generowania kolorów przy wywołaniu:
C/C++
std::vector < unsigned > vKolory;
generujKolory( vKolory, 50 );

Wygenerowana paleta kolorów do wykresów (druga wersja)
P-112429
DejaVu
» 2014-06-21 02:18:29
Dodam jeszcze, że prawdopodobnie najbardziej satysfakcjonującą paletę dla stosunkowo małej liczby kolorów uzyskasz przy takiej konfiguracji:
C/C++
generujKolory( vKolory, 85 );
P-112430
akwes
Temat założony przez niniejszego użytkownika
» 2014-06-21 17:03:01
Dzięki DejaVu :D Nawet nie mam nic do dodania bo rozwiązanie dokładnie pasuje.
P-112468
« 1 »
  Strona 1 z 1