Exemple #1
0
double Projector::findPA( SkyObject *o, float x, float y ) const
{
    //Find position angle of North using a test point displaced to the north
    //displace by 100/zoomFactor radians (so distance is always 100 pixels)
    //this is 5730/zoomFactor degrees
    KStarsData *data = KStarsData::Instance();
    double newDec = o->dec().Degrees() + 5730.0/m_vp.zoomFactor;
    if ( newDec > 90.0 )
        newDec = 90.0;
    SkyPoint test( o->ra().Hours(), newDec );
    if ( m_vp.useAltAz )
        test.EquatorialToHorizontal( data->lst(), data->geo()->lat() );
    Vector2f t = toScreenVec( &test );
    float dx = t.x() - x;
    float dy = y - t.y(); //backwards because QWidget Y-axis increases to the bottom
    float north;
    if ( dy ) {
        north = atan2f( dx, dy )*180.0/dms::PI;
    } else {
        north = (dx > 0.0 ? -90.0 : 90.0);
    }

    return ( north + o->pa() );
}
Exemple #2
0
QPointF Projector::toScreen(const SkyPoint* o, bool oRefract, bool* onVisibleHemisphere) const
{
    return KSUtils::vecToPoint( toScreenVec(o, oRefract, onVisibleHemisphere) );
}
Exemple #3
0
QVector< Vector2f > Projector::groundPoly(SkyPoint* labelpoint, bool *drawLabel) const
{
    KStarsData *data = KStarsData::Instance();
    QVector<Vector2f> ground;

    static const QString horizonLabel = i18n("Horizon");
    float marginLeft, marginRight, marginTop, marginBot;
    SkyLabeler::Instance()->getMargins( horizonLabel, &marginLeft, &marginRight,
                                        &marginTop, &marginBot );

    //daz is 1/2 the width of the sky in degrees
    double daz = 90.;
    if ( m_vp.useAltAz ) {
        daz = 0.5*m_vp.width*57.3/m_vp.zoomFactor; //center to edge, in degrees
        if ( type() == SkyMap::Orthographic ) {
            daz = daz * 1.4;
        }
        daz = qMin(90.0, daz);
    }

    double faz = m_vp.focus->az().Degrees();
    double az1 = faz -daz;
    double az2 = faz +daz;

    bool allGround = true;
    bool allSky = true;

    double inc = 1.0;
    //Add points along horizon
    for(double az = az1; az <= az2 + inc; az += inc) {
        SkyPoint p = pointAt(az,data);
        bool visible = false;
        Vector2f o = toScreenVec(&p, false, &visible);
        if( visible ) {
            ground.append( o );
            //Set the label point if this point is onscreen
            if ( labelpoint && o.x() < marginRight && o.y() > marginTop && o.y() < marginBot )
                *labelpoint = p;

            if ( o.y() > 0. ) allGround = false;
            if ( o.y() < m_vp.height ) allSky = false;
        }
    }

    if( allSky ) {
        if( drawLabel)
            *drawLabel = false;
        return QVector<Vector2f>();
    }

    if( allGround ) {
        ground.clear();
        ground.append( Vector2f( -10., -10. ) );
        ground.append( Vector2f( m_vp.width +10., -10. ) );
        ground.append( Vector2f( m_vp.width +10., m_vp.height +10. ) );
        ground.append( Vector2f( -10., m_vp.height +10. ) );
        if( drawLabel)
            *drawLabel = false;
        return ground;
    }

    //In Gnomonic projection, or if sufficiently zoomed in, we can complete
    //the ground polygon by simply adding offscreen points
    //FIXME: not just gnomonic
    if ( daz < 25.0 || type() == SkyMap::Gnomonic ) {
        ground.append( Vector2f( m_vp.width + 10.f, ground.last().y() ) );
        ground.append( Vector2f( m_vp.width + 10.f, m_vp.height + 10.f ) );
        ground.append( Vector2f( -10.f, m_vp.height + 10.f ) );
        ground.append( Vector2f( -10.f, ground.first().y() ) );
    } else {
        double r = m_vp.zoomFactor*radius();
        double t1 = atan2( -1.*(ground.last().y() - 0.5*m_vp.height), ground.last().x() - 0.5*m_vp.width )/dms::DegToRad;
        double t2 = t1 - 180.;
        for ( double t=t1; t >= t2; t -= inc ) {  //step along circumference
            dms a( t );
            double sa(0.), ca(0.);
            a.SinCos( sa, ca );
            ground.append( Vector2f( 0.5*m_vp.width + r*ca, 0.5*m_vp.height - r*sa) );
        }
    }

    if( drawLabel)
        *drawLabel = true;
    return ground;
}
Exemple #4
0
Vector2f Projector::clipLineVec( SkyPoint *p1, SkyPoint *p2 ) const
{
    /* ASSUMES p1 was not clipped but p2 was.
     * Return the QPoint that barely clips in the line twixt p1 and p2.
     */
    //TODO: iteration = ceil( 0.5*log2( w^2 + h^2) )??
    //      also possibly rewrite this
    //     --hdevalence
    int iteration = 15;          // For "perfect" clipping:
    // 2^interations should be >= max pixels/line
    bool isVisible = true;       // so we start at midpoint
    SkyPoint mid;
    Vector2f oMid;
    double x, y, z, dx, dy, dz, ra, dec;
    int newx, newy, oldx, oldy;
    oldx = oldy = -10000;        // any old value that is not the first omid

    toXYZ( p1, &x, &y, &z );
    // -jbb printf("\np1: %6.4f %6.4f %6.4f\n", x, y, z);

    toXYZ( p2, &dx, &dy, &dz );

    // -jbb printf("p2: %6.4f %6.4f %6.4f\n", dx, dy, dz);
    dx -= x;
    dy -= y;
    dz -= z;
    // Successive approximation to point on line that just clips.
    while(iteration-- > 0) {
        dx *= .5;
        dy *= .5;
        dz *= .5;
        if ( ! isVisible ) {              // move back toward visible p1
            x -= dx;
            y -= dy;
            z -= dz;
        }
        else {                        // move out toward clipped p2
            x += dx;
            y += dy;
            z += dz;
        }

        // -jbb printf("  : %6.4f %6.4f %6.4f\n", x, y, z);
        // [x, y, z] => [ra, dec]
        ra = atan2( y, x );
        dec = asin( z / sqrt(x*x + y*y + z*z) );

        mid = SkyPoint( ra * 12. / dms::PI, dec * 180. / dms::PI );
        mid.EquatorialToHorizontal( m_data->lst(), m_data->geo()->lat() );

        oMid = toScreenVec( &mid, false, &isVisible );
        //AND the result with checkVisibility to clip things going below horizon
        isVisible &= checkVisibility(&mid);
        newx = (int) oMid.x();
        newy = (int) oMid.y();

        // -jbb printf("new x/y: %4d %4d", newx, newy);
        if ( (oldx == newx) && (oldy == newy) ) {
            break;
        }
        oldx = newx;
        oldy = newy;
    }
    return  oMid;
}
QVector< Vector2f > EquirectangularProjector::groundPoly(SkyPoint* labelpoint, bool* drawLabel) const
{    
    float x0 = m_vp.width/2.;
    float y0 = m_vp.width/2.;
    if( m_vp.useAltAz ) {
        float dX = m_vp.zoomFactor*M_PI;
        float dY = m_vp.zoomFactor*M_PI;
        SkyPoint belowFocus;
        belowFocus.setAz( m_vp.focus->az().Degrees() );
        belowFocus.setAlt( 0.0 );

        Vector2f obf = toScreenVec( &belowFocus, false );

        //If the horizon is off the bottom edge of the screen,
        //we can return immediately
        if ( obf.y() > m_vp.height ) {
            if( drawLabel )
                *drawLabel = false;
            return QVector<Vector2f>();
        }

        //We can also return if the horizon is off the top edge,
        //as long as the ground poly is not being drawn
        if ( obf.y() < 0. && m_vp.fillGround == false ) {
            if( drawLabel )
                *drawLabel = false;
            return QVector<Vector2f>();
        }

        QVector<Vector2f> ground;
        //Construct the ground polygon, which is a simple rectangle in this case
        ground << Vector2f( x0 - dX, obf.y() )
               << Vector2f( x0 + dX, obf.y() )
               << Vector2f( x0 + dX, y0 + dY )
               << Vector2f( x0 - dX, y0 + dY );

        if( labelpoint ) {
            QPointF pLabel( x0 -dX -50., obf.y() );
            KStarsData *data = KStarsData::Instance();
            *labelpoint = fromScreen(pLabel, data->lst(), data->geo()->lat());
        }
        if( drawLabel )
            *drawLabel = true;

        return ground;
    } else {
        float dX = m_vp.zoomFactor*M_PI/2;
        float dY = m_vp.zoomFactor*M_PI/2;
        QVector<Vector2f> ground;

        static const QString horizonLabel = i18n("Horizon");
        float marginLeft, marginRight, marginTop, marginBot;
        SkyLabeler::Instance()->getMargins( horizonLabel, &marginLeft, &marginRight,
                                            &marginTop, &marginBot );
        double daz = 90.;
        double faz = m_vp.focus->az().Degrees();
        double az1 = faz -daz;
        double az2 = faz +daz;

        bool allGround = true;
        bool allSky = true;

        double inc = 1.0;
        //Add points along horizon
        for(double az = az1; az <= az2 + inc; az += inc) {
            SkyPoint p = pointAt(az);
            bool visible = false;
            Vector2f o = toScreenVec(&p, false, &visible);
            if( visible ) {
                ground.append( o );
                //Set the label point if this point is onscreen
                if ( labelpoint && o.x() < marginRight && o.y() > marginTop && o.y() < marginBot )
                    *labelpoint = p;

                if ( o.y() > 0. ) allGround = false;
                if ( o.y() < m_vp.height ) allSky = false;
            }
        }

        if( allSky ) {
            if( drawLabel)
                *drawLabel = false;
            return QVector<Vector2f>();
        }

        if( allGround ) {
            ground.clear();
            ground.append( Vector2f( x0 - dX, y0 - dY ) );
            ground.append( Vector2f( x0 + dX, y0 - dY ) );
            ground.append( Vector2f( x0 + dX, y0 + dY ) );
            ground.append( Vector2f( x0 - dX, y0 + dY ) );
            if( drawLabel)
                *drawLabel = false;
            return ground;
        }

        if( labelpoint ) {
            QPointF pLabel( x0 -dX -50., ground.last().y() );
            KStarsData *data = KStarsData::Instance();
            *labelpoint = fromScreen(pLabel, data->lst(), data->geo()->lat());
        }
        if( drawLabel )
            *drawLabel = true;

        //Now add points along the ground
        ground.append( Vector2f( x0 + dX, ground.last().y() ) );
        ground.append( Vector2f( x0 + dX, y0 + dY ) );
        ground.append( Vector2f( x0 - dX, y0 + dY ) );
        ground.append( Vector2f( x0 - dX, ground.first().y() ) );
        return ground;
    }
}