[Kstars-devel] KDE/kdeedu/kstars/kstars/skyobjects

Alexey Khudyakov alexey.skladnoy at gmail.com
Mon Nov 2 22:11:50 CET 2009


SVN commit 1044021 by khudyakov:

Optimize StarObject drawing code.

* Simple 2D c-style array is used as cache instead of QHash<QString,QPixmap>
  Function to compute index for spectral class is added. This gives about 10%
  speedup for whole map redrawing with maximum star density.

* Pixmap now have fixed size 15x15 pixels as maximum.

* ColorMap now is local for initImages(). Casuaties - function
  StarObject::color(). But it wasn't used anyway

CCMAIL: kstars-devel at kde.org

 M  +88 -64    starobject.cpp  
 M  +0 -29     starobject.h  


--- trunk/KDE/kdeedu/kstars/kstars/skyobjects/starobject.cpp #1044020:1044021
@@ -37,9 +37,37 @@
 
 #include "skycomponents/skylabeler.h"
 
-QMap<QString, QColor> StarObject::ColorMap;
-QHash<QString, QPixmap> StarObject::StarImage;
+namespace {
 
+    // Convert spectral class to numerical index.
+    // If spectral class is invalid return index for white star (A class)
+    int harvardToIndex(char c) {
+        switch( c ) {
+        case 'o': case 'O': return 0;
+        case 'b': case 'B': return 1;
+        case 'a': case 'A': return 2;
+        case 'f': case 'F': return 3;
+        case 'g': case 'G': return 4;
+        case 'k': case 'K': return 5;
+        case 'm': case 'M': return 6;
+        // For unknown spectral class assume A class (white star)
+        default: return 2;
+        }
+    }
+
+    // Total number of sizes of stars.
+    const int nStarSizes = 15;
+    // Total number of specatral classes
+    // N.B. Must be in sync with harvardToIndex
+    const int nSPclasses = 7;
+
+    // Cache for star images.
+    //
+    // These pixmaps are never deallocated. Not really good...
+    QPixmap* imageCache[nSPclasses][nStarSizes] = {{0}};
+}
+
+
 // DEBUG EDIT. Uncomment for testing Proper Motion
 // You will also need to uncomment all related blocks
 // from this file, starobject.h and also the trixel-boundaries
@@ -239,49 +267,49 @@
 
 
 void StarObject::initImages() {
-    SkyMap *map = SkyMap::Instance();
-    double scale = 1.0;
+    QMap<char, QColor> ColorMap;
     const int starColorIntensity = Options::starColorIntensity();
 
-    if ( map && map->scale() > 1.0 ) scale = map->scale();
-
-    if ( Options::starColorMode() == 0 ) { //Real colors
-        ColorMap.insert( "O", QColor::fromRgb(   0,   0, 255 ) );
-        ColorMap.insert( "B", QColor::fromRgb(   0, 200, 255 ) );
-        ColorMap.insert( "A", QColor::fromRgb(   0, 255, 255 ) );
-        ColorMap.insert( "F", QColor::fromRgb( 200, 255, 100 ) );
-        ColorMap.insert( "G", QColor::fromRgb( 255, 255,   0 ) );
-        ColorMap.insert( "K", QColor::fromRgb( 255, 100,   0 ) );
-        ColorMap.insert( "M", QColor::fromRgb( 255,   0,   0 ) );
-    } else if ( Options::starColorMode() == 1 ) { //Red stars
-        ColorMap.insert( "O", QColor::fromRgb( 255,   0,   0 ) );
-        ColorMap.insert( "B", QColor::fromRgb( 255,   0,   0 ) );
-        ColorMap.insert( "A", QColor::fromRgb( 255,   0,   0 ) );
-        ColorMap.insert( "F", QColor::fromRgb( 255,   0,   0 ) );
-        ColorMap.insert( "G", QColor::fromRgb( 255,   0,   0 ) );
-        ColorMap.insert( "K", QColor::fromRgb( 255,   0,   0 ) );
-        ColorMap.insert( "M", QColor::fromRgb( 255,   0,   0 ) );
-    } else if ( Options::starColorMode() == 2 ) { //Black stars
-        ColorMap.insert( "O", QColor::fromRgb(   0,   0,   0 ) );
-        ColorMap.insert( "B", QColor::fromRgb(   0,   0,   0 ) );
-        ColorMap.insert( "A", QColor::fromRgb(   0,   0,   0 ) );
-        ColorMap.insert( "F", QColor::fromRgb(   0,   0,   0 ) );
-        ColorMap.insert( "G", QColor::fromRgb(   0,   0,   0 ) );
-        ColorMap.insert( "K", QColor::fromRgb(   0,   0,   0 ) );
-        ColorMap.insert( "M", QColor::fromRgb(   0,   0,   0 ) );
-    } else if ( Options::starColorMode() == 3 ) { //White stars
-        ColorMap.insert( "O", QColor::fromRgb( 255, 255, 255 ) );
-        ColorMap.insert( "B", QColor::fromRgb( 255, 255, 255 ) );
-        ColorMap.insert( "A", QColor::fromRgb( 255, 255, 255 ) );
-        ColorMap.insert( "F", QColor::fromRgb( 255, 255, 255 ) );
-        ColorMap.insert( "G", QColor::fromRgb( 255, 255, 255 ) );
-        ColorMap.insert( "K", QColor::fromRgb( 255, 255, 255 ) );
-        ColorMap.insert( "M", QColor::fromRgb( 255, 255, 255 ) );
+    switch( Options::starColorMode() ) {
+    case 1: // Red stars.
+        ColorMap.insert( 'O', QColor::fromRgb( 255,   0,   0 ) );
+        ColorMap.insert( 'B', QColor::fromRgb( 255,   0,   0 ) );
+        ColorMap.insert( 'A', QColor::fromRgb( 255,   0,   0 ) );
+        ColorMap.insert( 'F', QColor::fromRgb( 255,   0,   0 ) );
+        ColorMap.insert( 'G', QColor::fromRgb( 255,   0,   0 ) );
+        ColorMap.insert( 'K', QColor::fromRgb( 255,   0,   0 ) );
+        ColorMap.insert( 'M', QColor::fromRgb( 255,   0,   0 ) );
+        break;
+    case 2: // Black stars.
+        ColorMap.insert( 'O', QColor::fromRgb(   0,   0,   0 ) );
+        ColorMap.insert( 'B', QColor::fromRgb(   0,   0,   0 ) );
+        ColorMap.insert( 'A', QColor::fromRgb(   0,   0,   0 ) );
+        ColorMap.insert( 'F', QColor::fromRgb(   0,   0,   0 ) );
+        ColorMap.insert( 'G', QColor::fromRgb(   0,   0,   0 ) );
+        ColorMap.insert( 'K', QColor::fromRgb(   0,   0,   0 ) );
+        ColorMap.insert( 'M', QColor::fromRgb(   0,   0,   0 ) );
+        break;
+    case 3: // White stars
+        ColorMap.insert( 'O', QColor::fromRgb( 255, 255, 255 ) );
+        ColorMap.insert( 'B', QColor::fromRgb( 255, 255, 255 ) );
+        ColorMap.insert( 'A', QColor::fromRgb( 255, 255, 255 ) );
+        ColorMap.insert( 'F', QColor::fromRgb( 255, 255, 255 ) );
+        ColorMap.insert( 'G', QColor::fromRgb( 255, 255, 255 ) );
+        ColorMap.insert( 'K', QColor::fromRgb( 255, 255, 255 ) );
+        ColorMap.insert( 'M', QColor::fromRgb( 255, 255, 255 ) );
+    case 0:  // Real color
+    default: // And use real color for everything else
+        ColorMap.insert( 'O', QColor::fromRgb(   0,   0, 255 ) );
+        ColorMap.insert( 'B', QColor::fromRgb(   0, 200, 255 ) );
+        ColorMap.insert( 'A', QColor::fromRgb(   0, 255, 255 ) );
+        ColorMap.insert( 'F', QColor::fromRgb( 200, 255, 100 ) );
+        ColorMap.insert( 'G', QColor::fromRgb( 255, 255,   0 ) );
+        ColorMap.insert( 'K', QColor::fromRgb( 255, 100,   0 ) );
+        ColorMap.insert( 'M', QColor::fromRgb( 255,   0,   0 ) );
     }
 
-    foreach ( const QString &color, ColorMap.keys() ) {
-        QString imKey = color+"15";
-        QPixmap BigImage( static_cast<int>(15*scale), static_cast<int>(15*scale) ); 
+    foreach( char color, ColorMap.keys() ) {
+        QPixmap BigImage( 15, 15 );
         BigImage.fill( Qt::transparent );
 
         QPainter p;
@@ -294,8 +322,13 @@
             starColor.getHsvF(&h, &s, &v, &a);
             for (int i = 0; i < 8; i++ ) {
                 for (int j = 0; j < 8; j++ ) {
-                    qreal dist = sqrt( pow( i-7., 2. ) + pow( j-7., 2. ) )/7.;
-                    starColor.setHsvF(h, qMin( qreal(1), dist < (10-starColorIntensity)/10.?0:dist ), v, qMax( qreal(0), dist < (10-starColorIntensity)/20.?1:1-dist ) );
+                    qreal x = i - 7;
+                    qreal y = j - 7;
+                    qreal dist = sqrt( x*x + y*y ) / 7.0;
+                    starColor.setHsvF(h,
+                                      qMin( qreal(1), dist < (10-starColorIntensity)/10.0 ? 0 : dist ),
+                                      v,
+                                      qMax( qreal(0), dist < (10-starColorIntensity)/20.0 ? 1 : 1-dist ) );
                     p.setPen( starColor );
                     p.drawPoint( i, j );
                     p.drawPoint( 14-i, j );
@@ -305,16 +338,18 @@
             }
         } else {
             p.setRenderHint(QPainter::Antialiasing, true );
-            p.setPen( QPen(ColorMap[color], 2.0*scale ) );
+            p.setPen( QPen(ColorMap[color], 2.0 ) );
             p.setBrush( p.pen().color() );
-            p.drawEllipse( QRectF( 2*scale, 2*scale, 10*scale, 10*scale ) );
+            p.drawEllipse( QRectF( 2, 2, 10, 10 ) );
         }
         p.end();
-        StarImage.insert( imKey, BigImage );
 
-        for ( int size = 14; size > 0; size-- ) {
-            imKey = color+QString("%1").arg(size);
-            StarImage.insert( imKey, BigImage.scaled( size*scale, size*scale, Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
+        // Cahce array slice 
+        QPixmap** pmap = imageCache[ harvardToIndex(color) ];
+        for( int size = 1; size < nStarSizes; size++ ) {
+            if( !pmap[size] )
+                pmap[size] = new QPixmap();
+            *pmap[size] = BigImage.scaled( size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
         }
     }
 }
@@ -545,17 +580,6 @@
     return QString();
 }
 
-QColor StarObject::color() const {
-    return ColorMap[QString(QChar(SpType[0]))];
-}
-
-bool StarObject::isSpecType( char c ) {
-    if( c == 'W' || c == 'O' || c == 'B' || c == 'A' || c == 'F' || c == 'G' || c == 'K' || c == 'M' || c == 'R' || c == 'N' || c == 'S' )
-        return true;
-    else
-        return false;
-}
-
 void StarObject::draw( QPainter &psky, float x, float y, float size,
                        bool /*useRealColors*/, int /*scIntensity*/, bool /*showMultiple*/ ) {
 
@@ -563,10 +587,10 @@
     if ( isize >= 14 ) {
         isize = 14;
     }
-    QString imKey = ( isSpecType( SpType[0] )  ? SpType[0] : ( isSpecType( SpType[1] ) ? SpType[1] : 'A' ) ) + QString("%1").arg(isize);
-    float offset = 0.5*StarImage[imKey].width();
-    psky.drawPixmap( QPointF(x-offset, y-offset), StarImage[imKey] );
-
+    QPixmap* im = imageCache[ harvardToIndex(SpType[0]) ][isize];
+    float offset = 0.5 * im->width();
+    psky.drawPixmap( QPointF(x-offset, y-offset), *im );
+    
     // DEBUG Edit. To check Proper Motion Corrections. Uncomment all related blocks for testing.
     /*
     if( !testStar )
--- trunk/KDE/kdeedu/kstars/kstars/skyobjects/starobject.h #1044020:1044021
@@ -143,10 +143,6 @@
         *If star is unnamed return "star" otherwise return the longname
         */
     inline virtual QString longname( void ) const { return hasLongName() ? LongName : starString; }
-    /**
-        *@return QColor corresponding to the star's Spectral Type
-        */
-    QColor color( void ) const;
 
     /**
         *Returns entire spectral type string
@@ -246,28 +242,6 @@
         */
     inline bool isVariable() const { return Variability; }
 
-    /**@return true if the passed character is a valid spectral class
-     */
-    bool isSpecType( char c );
-
-    //Not using VRange, VPeriod currently (to save memory)
-    ///**@short set the range in brightness covered by the star's variability
-    //  *@param r the range of brightness, in magnitudes
-    //  */
-    //  void setVRange( double r ) { VRange = r; }
-    //
-    ///**@return the range in brightness covered by the star's variability, in magnitudes
-    //  */
-    //  double vrange() const { return VRange; }
-    //
-    ///**@short set the period of the star's brightness variation, in days.
-    //  */
-    //  void setVPeriod( double p ) { VPeriod = p; }
-    //
-    ///**@return the period of the star's brightness variation, in days.
-    //  */
-    //  double vperiod() const { return VPeriod; }
-
     void draw( QPainter &psky, float x, float y, float size,
                bool useRealColors, int scIntensity, bool drawMultiple=true );
 
@@ -302,9 +276,6 @@
     quint64 updateNumID;
 
 protected:
-    static QMap<QString, QColor> ColorMap;
-    static QHash<QString, QPixmap> StarImage;
-
     // DEBUG EDIT. For testing proper motion, uncomment this, and related blocks
     // See starobject.cpp for further info.
     //    static QVector<SkyPoint *> Trail;


More information about the Kstars-devel mailing list