void GeoDataLineStringPrivate::toPoleCorrected( const GeoDataLineString& q, GeoDataLineString& poleCorrected ) { poleCorrected.setTessellationFlags( q.tessellationFlags() ); GeoDataCoordinates previousCoords; GeoDataCoordinates currentCoords; if ( q.isClosed() ) { if ( !( m_vector.first().isPole() ) && ( m_vector.last().isPole() ) ) { qreal firstLongitude = ( m_vector.first() ).longitude(); GeoDataCoordinates modifiedCoords( m_vector.last() ); modifiedCoords.setLongitude( firstLongitude ); poleCorrected << modifiedCoords; } } QVector<GeoDataCoordinates>::const_iterator itCoords = m_vector.constBegin(); QVector<GeoDataCoordinates>::const_iterator itEnd = m_vector.constEnd(); for( ; itCoords != itEnd; ++itCoords ) { currentCoords = *itCoords; if ( itCoords == m_vector.constBegin() ) { previousCoords = currentCoords; } if ( currentCoords.isPole() ) { if ( previousCoords.isPole() ) { continue; } else { qreal previousLongitude = previousCoords.longitude(); GeoDataCoordinates currentModifiedCoords( currentCoords ); currentModifiedCoords.setLongitude( previousLongitude ); poleCorrected << currentModifiedCoords; } } else { if ( previousCoords.isPole() ) { qreal currentLongitude = currentCoords.longitude(); GeoDataCoordinates previousModifiedCoords( previousCoords ); previousModifiedCoords.setLongitude( currentLongitude ); poleCorrected << previousModifiedCoords; poleCorrected << currentCoords; } else { // No poles at all. Nothing special to handle poleCorrected << currentCoords; } } previousCoords = currentCoords; } if ( q.isClosed() ) { if ( ( m_vector.first().isPole() ) && !( m_vector.last().isPole() ) ) { qreal lastLongitude = ( m_vector.last() ).longitude(); GeoDataCoordinates modifiedCoords( m_vector.first() ); modifiedCoords.setLongitude( lastLongitude ); poleCorrected << modifiedCoords; } } }
int CylindricalProjectionPrivate::processTessellation( const GeoDataCoordinates &previousCoords, const GeoDataCoordinates ¤tCoords, int tessellatedNodes, QVector<QPolygonF*> &polygons, const ViewportParams *viewport, TessellationFlags f, int mirrorCount, qreal repeatDistance) const { const bool clampToGround = f.testFlag( FollowGround ); const bool followLatitudeCircle = f.testFlag( RespectLatitudeCircle ) && previousCoords.latitude() == currentCoords.latitude(); // Calculate steps for tessellation: lonDiff and altDiff qreal lonDiff = 0.0; if ( followLatitudeCircle ) { const int previousSign = previousCoords.longitude() > 0 ? 1 : -1; const int currentSign = currentCoords.longitude() > 0 ? 1 : -1; lonDiff = currentCoords.longitude() - previousCoords.longitude(); if ( previousSign != currentSign && fabs(previousCoords.longitude()) + fabs(currentCoords.longitude()) > M_PI ) { if ( previousSign > currentSign ) { // going eastwards -> lonDiff += 2 * M_PI ; } else { // going westwards -> lonDiff -= 2 * M_PI; } } if ( fabs( lonDiff ) == 2 * M_PI ) { return mirrorCount; } } const qreal altDiff = currentCoords.altitude() - previousCoords.altitude(); // Create the tessellation nodes. GeoDataCoordinates previousTessellatedCoords = previousCoords; for ( int i = 1; i <= tessellatedNodes; ++i ) { const qreal t = (qreal)(i) / (qreal)( tessellatedNodes + 1 ); // interpolate the altitude, too const qreal altitude = clampToGround ? 0 : altDiff * t + previousCoords.altitude(); qreal lon = 0.0; qreal lat = 0.0; if ( followLatitudeCircle ) { // To tessellate along latitude circles use the // linear interpolation of the longitude. lon = lonDiff * t + previousCoords.longitude(); lat = previousTessellatedCoords.latitude(); } else { // To tessellate along great circles use the // normalized linear interpolation ("NLERP") for latitude and longitude. const Quaternion itpos = Quaternion::nlerp( previousCoords.quaternion(), currentCoords.quaternion(), t ); itpos. getSpherical( lon, lat ); } const GeoDataCoordinates currentTessellatedCoords( lon, lat, altitude ); Q_Q(const CylindricalProjection); qreal bx, by; q->screenCoordinates( currentTessellatedCoords, viewport, bx, by ); mirrorCount = crossDateLine( previousTessellatedCoords, currentTessellatedCoords, bx, by, polygons, mirrorCount, repeatDistance ); previousTessellatedCoords = currentTessellatedCoords; } // For the clampToGround case add the "current" coordinate after adding all other nodes. GeoDataCoordinates currentModifiedCoords( currentCoords ); if ( clampToGround ) { currentModifiedCoords.setAltitude( 0.0 ); } Q_Q(const CylindricalProjection); qreal bx, by; q->screenCoordinates( currentModifiedCoords, viewport, bx, by ); mirrorCount = crossDateLine( previousTessellatedCoords, currentModifiedCoords, bx, by, polygons, mirrorCount, repeatDistance ); return mirrorCount; }