SGBucket::set_bucket(double dlon, double dlat) has some bugs,
especially evident at high latitudes.  For example, try this test,
which consists of 3 closely-spaced points:

    SGBucket b1(-179.5, 87.5);
    printf("b1: lon = %d, lat = %d\n", b1.get_chunk_lon(), b1.get_chunk_lat());
    SGBucket b2(-179.0, 87.5);
    printf("b2: lon = %d, lat = %d\n", b2.get_chunk_lon(), b2.get_chunk_lat());
    SGBucket b3(-178.5, 87.5);
    printf("b3: lon = %d, lat = %d\n", b3.get_chunk_lon(), b3.get_chunk_lat());

The output will be:

b1: lon = -180, lat = 87
b2: lon = -176, lat = 87
b3: lon = -180, lat = 87

Both b1 and b3 are correctly placed in the same chunk.  However, b2,
which is in-between, is placed in a different chunk!

I've checked the code for set_bucket(), but I don't really understand
it.  I wrote a replacement, given below.  I've done many tests; where
they disagreed, my routine has been correct.  This is not proof of
course, and I encourage people to check it for errors.  In any case,
it is clear that we need to fix the current set_bucket().

Note that my routine differs in two other ways from the current
set_bucket():

(1) It sets cx and cy (the centre of the bucket).  

    Right now these member variables are unused in SGBucket.  Setting
    them in set_bucket() seems like a good thing to do, because it's
    easy to do there, and we can then change get_center_lon() and
    get_center_lat() to much simpler routines:

    inline double get_center_lon() const { return cx; }
    inline double get_center_lat() const { return cy; }

(2) It never lets a bucket cross the line of +/-180 degrees longitude.

    Dealing with the +/-180 degree line is tricky.  Unless you are
    very very careful, it'll get you.  For example, lon + 1.0 is not
    always greater than lon (179.5 + 1.0 = -179.5).  A quick check
    through the Terragear code indicates that, for example,
    BuildTiles/Main/main.cxx makes this mistake in
    actual_load_landcover() (I haven't run a test to confirm this, so
    don't kill me if I'm wrong).

    In any case, it's much better to never cross +/-180, which ensures
    that you never have to be careful in the first place.

    This makes my set_bucket() differ from the current set_bucket()
    for the last two "rows" at the poles, when the bucket span is 8
    degrees and 360 degrees, so tile naming will change in those
    areas.  This will cause temporary disruption, but I think it will
    be minimal, since people rarely fly there.

Now the routine:

void set_bucket(double dlon, double dlat)
{
    double span = sg_bucket_span(dlat);
    
    // Note: the span always divides into 360.0, but not 180.0 (ie,
    // when the span is 8.0).
    double diff = fmod(dlon + 180.0, span);

    // Calculate the lat, lon of the chunk.
    lon = floor(dlon - diff);
    lat = floor(dlat);

    // Get our subdivision in the chunk.
    x = 0;
    if (span < 1.0) {
        x = floor((dlon - lon) / span);
    }
    y = floor((dlat - lat) / SG_BUCKET_SPAN);

    // Calculate the center of the bucket.
    cx = lon + (x * span) + (span / 2.0);
    cy = lat + (y * SG_BUCKET_SPAN) + SG_HALF_BUCKET_SPAN;
}

I should also add that the documentation for get_corner() says that it
returns the *center* of the bucket, which is wrong.  It might be a
good idea to explain what the 'num' parameter is really supposed to
do.  Here's what I think it does:

    num == 0 -> return SW corner
    num == 1 -> return SE corner
    num == 2 -> return NE corner
    num == 3 -> return NW corner

-- 
Brian Schack
19 Xǔchāng Street 2F    phone:  2381 4727
Taipei 100              fax:    2381 2145
TAIWAN                  


------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to