<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      <NAME>     <<EMAIL>>"
//


#include "GlobeScanlineTextureMapper.h"

#include <cmath>

#include <QtCore/QDebug>

#include "GeoDataPoint.h"
#include "GeoPolygon.h"
#include "MarbleDirs.h"
#include "TextureTile.h"
#include "TileLoader.h"


// Defining INTERLACE will make sure that for two subsequent scanlines
// every second scanline will be a deep copy of the first scanline.
// This results in a more coarse resolution and in a speedup for the 
// texture mapping of approx. 25%.

// #define INTERLACE

GlobeScanlineTextureMapper::GlobeScanlineTextureMapper( TileLoader *tileLoader, QObject * parent  ) 
    : AbstractScanlineTextureMapper( tileLoader, parent )
{
    m_interpolate  = false;
    m_nBest = 0;

    m_n = 0;
    m_nInverse = 0.0;

    m_x = 0;
    m_y = 0;

    m_qr = 0.0; 
    m_qx = 0.0;
    m_qy = 0.0;
    m_qz = 0.0;

    m_interlaced = false;
}


GlobeScanlineTextureMapper::~GlobeScanlineTextureMapper()
{
}


void GlobeScanlineTextureMapper::resizeMap(int width, int height)
{
    AbstractScanlineTextureMapper::resizeMap( width, height );

    // Find the optimal interpolation interval m_n for the 
    // current image canvas width
    m_nBest = 2;

    int  nEvalMin = m_imageWidth - 1;
    for ( int it = 1; it < 48; ++it ) {
        int nEval = ( m_imageWidth - 1 ) / it + ( m_imageWidth - 1 ) % it;
        if ( nEval < nEvalMin ) {
            nEvalMin = nEval;
            m_nBest = it; 
        }
    }
    // qDebug() << QString( "Optimized n = %1, remainder: %2" )
    //.arg(m_nBest).arg( ( m_imageWidth ) % m_nBest );
}


void GlobeScanlineTextureMapper::mapTexture( ViewParams *viewParams )
{
    QImage* canvasImage = viewParams->m_canvasImage;
    const int radius = viewParams->m_radius;

    // Scanline based algorithm to texture map a sphere

    // Initialize needed variables:
    double  lon = 0.0;
    double  lat = 0.0;

    const double  inverseRadius = 1.0 / (double)(radius);

    m_tilePosX = 65535;
    m_tilePosY = 65535;
    m_toTileCoordinatesLon = (double)(m_tileLoader->globalWidth( m_tileLevel ) 
                             / 2 - m_tilePosX);
    m_toTileCoordinatesLat = (double)(m_tileLoader->globalHeight( m_tileLevel ) 
                             / 2 - m_tilePosY);

    // Reset backend
    m_tileLoader->resetTilehash();
    selectTileLevel(radius);

    // Evaluate the degree of interpolation
    m_n    = ( m_imageRadius < radius * radius ) ? m_nBest : 8;
    m_nInverse = 1.0 / (double)(m_n);

    // Calculate north pole position to decrease pole distortion later on
    Quaternion  northPole = GeoDataPoint( 0.0, (double)( M_PI * 0.5 ) ).quaternion();

    northPole.rotateAroundAxis( viewParams->m_planetAxis );

    // Calculate axis matrix to represent the planet's rotation.
    matrix  planetAxisMatrix;
    viewParams->m_planetAxis.toMatrix( planetAxisMatrix );

    int skip = ( m_interlaced == true ) ? 1 : 0;

    // Calculate the actual y-range of the map on the screen 
    const int yTop = ( ( m_imageHeight / 2 - radius < 0 )
                       ? 0 : m_imageHeight / 2 - radius );
    const int yBottom = ( (yTop == 0)
                          ? m_imageHeight - skip
                          : yTop + radius + radius - skip );

    for ( m_y = yTop; m_y < yBottom ; ++m_y ) {

        // Evaluate coordinates for the 3D position vector of the current pixel
        m_qy = inverseRadius * (double)( m_imageHeight / 2 - m_y );
        m_qr = 1.0 - m_qy * m_qy;

        // rx is the radius component in x direction
        int rx = (int)sqrt( (double)( radius * radius 
                      - ( ( m_y - m_imageHeight / 2 )
                      * ( m_y - m_imageHeight / 2 ) ) ) );

        // Calculate the actual x-range of the map within the current scanline
        const int xLeft  = ( ( m_imageWidth / 2 - rx > 0 )
                             ? m_imageWidth / 2 - rx : 0 ); 
        const int xRight = ( ( m_imageWidth / 2 - rx > 0 )
                             ? xLeft + rx + rx : canvasImage -> width() );

        m_scanLine = (QRgb*)( canvasImage->scanLine( m_y ) ) + xLeft;

        int  xIpLeft  = 1;
        int  xIpRight = m_n * (int)( xRight / m_n - 1) + 1; 

        if ( m_imageWidth / 2 - rx > 0 ) {
            xIpLeft  = m_n * (int)( xLeft  / m_n + 1 );
            xIpRight = m_n * (int)( xRight / m_n - 1 );
        }

        // Decrease pole distortion due to linear approximation ( y-axis )
        bool crossingPoleArea = false;
        int northPoleY = m_imageHeight / 2 + (int)( radius * northPole.v[Q_Y] );<commit_msg>- Explanation for tokoe<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2007      <NAME>     <<EMAIL>>"
//


#include "GlobeScanlineTextureMapper.h"

#include <cmath>

#include <QtCore/QDebug>

#include "GeoDataPoint.h"
#include "GeoPolygon.h"
#include "MarbleDirs.h"
#include "TextureTile.h"
#include "TileLoader.h"


// Defining INTERLACE will make sure that for two subsequent scanlines
// every second scanline will be a deep copy of the first scanline.
// This results in a more coarse resolution and in a speedup for the 
// texture mapping of approx. 25%.

// #define INTERLACE

GlobeScanlineTextureMapper::GlobeScanlineTextureMapper( TileLoader *tileLoader, QObject * parent  ) 
    : AbstractScanlineTextureMapper( tileLoader, parent )
{
    m_interpolate  = false;
    m_nBest = 0;

    m_n = 0;
    m_nInverse = 0.0;

    m_x = 0;
    m_y = 0;

    m_qr = 0.0; 
    m_qx = 0.0;
    m_qy = 0.0;
    m_qz = 0.0;

    m_interlaced = false;
}


GlobeScanlineTextureMapper::~GlobeScanlineTextureMapper()
{
}


void GlobeScanlineTextureMapper::resizeMap(int width, int height)
{
    AbstractScanlineTextureMapper::resizeMap( width, height );

    // Find the optimal interpolation interval m_n for the 
    // current image canvas width
    m_nBest = 2;

    int  nEvalMin = m_imageWidth - 1;
    for ( int it = 1; it < 48; ++it ) {
        int nEval = ( m_imageWidth - 1 ) / it + ( m_imageWidth - 1 ) % it;
        if ( nEval < nEvalMin ) {
            nEvalMin = nEval;
            m_nBest = it; 
        }
    }
    // qDebug() << QString( "Optimized n = %1, remainder: %2" )
    //.arg(m_nBest).arg( ( m_imageWidth ) % m_nBest );
}


void GlobeScanlineTextureMapper::mapTexture( ViewParams *viewParams )
{
    QImage* canvasImage = viewParams->m_canvasImage;
    const int radius = viewParams->m_radius;

    // Scanline based algorithm to texture map a sphere

    // Initialize needed variables:
    double  lon = 0.0;
    double  lat = 0.0;

    const double  inverseRadius = 1.0 / (double)(radius);

    m_tilePosX = 65535;
    m_tilePosY = 65535;
    m_toTileCoordinatesLon = (double)(m_tileLoader->globalWidth( m_tileLevel ) 
                             / 2 - m_tilePosX);
    m_toTileCoordinatesLat = (double)(m_tileLoader->globalHeight( m_tileLevel ) 
                             / 2 - m_tilePosY);

    // Reset backend
    m_tileLoader->resetTilehash();
    selectTileLevel(radius);

    // Evaluate the degree of interpolation
    m_n    = ( m_imageRadius < radius * radius ) ? m_nBest : 8;
    m_nInverse = 1.0 / (double)(m_n);

    // Calculate north pole position to decrease pole distortion later on
    Quaternion  northPole = GeoDataPoint( 0.0, (double)( M_PI * 0.5 ) ).quaternion();

    northPole.rotateAroundAxis( viewParams->m_planetAxis );

    // Calculate axis matrix to represent the planet's rotation.
    matrix  planetAxisMatrix;
    viewParams->m_planetAxis.toMatrix( planetAxisMatrix );

    int skip = ( m_interlaced == true ) ? 1 : 0;

    // Calculate the actual y-range of the map on the screen 
    const int yTop = ( ( m_imageHeight / 2 - radius < 0 )
                       ? 0 : m_imageHeight / 2 - radius );
    const int yBottom = ( (yTop == 0)
                          ? m_imageHeight - skip
                          : yTop + radius + radius - skip );

    for ( m_y = yTop; m_y < yBottom ; ++m_y ) {

        // Evaluate coordinates for the 3D position vector of the current pixel
        m_qy = inverseRadius * (double)( m_imageHeight / 2 - m_y );
        m_qr = 1.0 - m_qy * m_qy;

        // rx is the radius component in x direction
        int rx = (int)sqrt( (double)( radius * radius 
                      - ( ( m_y - m_imageHeight / 2 )
                      * ( m_y - m_imageHeight / 2 ) ) ) );

        // Calculate the actual x-range of the map within the current scanline.
        // 
        // If the circular border of the earth disk is still visible then xLeft
        // equals the scanline position of the most left pixel that gets covered
        // by the earth disk. In terms of math this equals the half image width minus 
        // the radius component on the current scanline in x direction ("rx").
        //
        // If the zoom factor is high enough then the whole screen gets covered
        // by the earth and the border of the earth disk isn't visible anymore.
        // In that situation xLeft equals zero.
        // For xRight the situation is similar.

        const int xLeft  = ( ( m_imageWidth / 2 - rx > 0 )
                             ? m_imageWidth / 2 - rx : 0 ); 
        const int xRight = ( ( m_imageWidth / 2 - rx > 0 )
                             ? xLeft + rx + rx : canvasImage -> width() );

        m_scanLine = (QRgb*)( canvasImage->scanLine( m_y ) ) + xLeft;

        int  xIpLeft  = 1;
        int  xIpRight = m_n * (int)( xRight / m_n - 1) + 1; 

        if ( m_imageWidth / 2 - rx > 0 ) {
            xIpLeft  = m_n * (int)( xLeft  / m_n + 1 );
            xIpRight = m_n * (int)( xRight / m_n - 1 );
        }

        // Decrease pole distortion due to linear approximation ( y-axis )
        bool crossingPoleArea = false;
        int northPoleY = m_imageHeight / 2 + (int)( radius * northPole.v[Q_Y] );
{'fraction_non_alphanumeric': 0.10428487575816865, 'fraction_numerical': 0.01584817061240462, 'mean_word_length': 2.1120243531202436, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7305707', 'n_tokens_mistral': 3474, 'n_tokens_neox': 3210, 'n_words': 1004}