Try #3. Can someone take a look at this please? Please? Please, please, please?!
============================================================ 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; } If we do decide to use and set cx and cy, then we would also need to add code to the end of SGBucket::SGBucket(const long int bindex) to initialize cx and xy: // Calculate the center of the bucket. double span = sg_bucket_span(lat); cx = lon + (x * span) + (span / 2.0); cy = lat + (y * SG_BUCKET_SPAN) + SG_HALF_BUCKET_SPAN; (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, if your scenery crosses +/-180, then 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 ------------------------------------------------------------------------------ _______________________________________________ Flightgear-devel mailing list Flightgear-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/flightgear-devel