Re: high precision conversion troubles
In article <9948556f-6370-41ab-a8ff-
2e8a15b2328d@q11g2000yqi.googlegroups.com>, ron.eggler@gmail.com
says...
Hi There,
I need to do some calculations with GPS coordinates and i get all
weird values and i can't see where i'm going wrong.
My code:
[code]
// calculate the average xy coordinates out of the
polygon's corner points
double CinXAvg =((((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(0).x +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(1).x +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(2).x +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(3).x)*10000000)/4;
double CinYAvg =((((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(0).y +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(1).y +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(2).y +
((sphericalpolygon *) curApproach-
getCheckInPolygon())->getCornerPoints()->at(3).y)*10000000)/4;
//save the average value in a hash table so we can later
go ahead and find the outest polygons
xy AvgCIN(static_cast<double>(CinXAvg/10000000),
static_cast<double>(CinYAvg/10000000));
I hope you don't mind my being blunt, but this is hard to read, and
so ugly I'd rather not. I'd write it something like this:
std::vector<xy> const &xys =
*((sphericalpolygon *) curApproach->getCheckInPolygon())->
getCornerPoints();
Without seeing the rest of the code, it's hard to say for sure, but
nothing you said or shown indicates that the cast should be necessary
-- I'd look hard at trying to eliminate it.
With that in place, the averaging code reduces to something like
this:
double CinXAvg = (xys[0].x + xys[1].x + xys[2].x + xys[3].x)*0.25;
double CinYAvg = (xys[0].y + xys[1].y + xys[2].y + xys[3].y)*0.25;
The multiplication, and later division by 10,000,000 were not
accomplishing much of anything, and certainly not what you seemed to
think, so at least for now I've simply eliminated them. If you want
to round the numbers to some specified precision, I'd write a small
function for exactly that purpose:
round(CinXAvg, 7);
round(CinYAvg, 7);
AvgHashTable[AvgHashTable.size()]=AvgCIN;
You only ever seem to add to the end of the "hash table" (which you
later show is a map, NOT a hash table at all). Given that you only
add to its end, and the keys are contiguous integers starting from
zero, an std::vector appears to be what you really want:
std::vector<xy> means;
means.push_back(xy(CinXAvg, CinYAvg));
}
for (int i=0; i < AvgHashTable.size(); i++) {
if (i==0) {
TopLeft.x=AvgHashTable[i].x;
TopLeft.y=AvgHashTable[i].y;
BottomRight.x=AvgHashTable[i].x;
BottomRight.y=AvgHashTable[i].y;
}
else {
if (AvgHashTable[i].x < TopLeft.x)
TopLeft.x=AvgHashTable[i].x;
if (AvgHashTable[i].y < TopLeft.y)
TopLeft.y=AvgHashTable[i].y;
if (AvgHashTable[i].x > BottomRight.x)
BottomRight.x=AvgHashTable[i].x;
if (AvgHashTable[i].y > BottomRight.y)
BottomRight.y=AvgHashTable[i].y;
}
}
Here, I'd move the special case out of the loop, and use std::min and
std::max:
xy TopLeft = means[0];
xy BottomRight = means[0];
for (int i=1; i<means.size(); ++i) {
TopLeft.x = std::min(TopLeft.x, means[i].x);
TopLeft.y = std::min(TopLeft.y, means[i].y);
BottomRight.x = std::max(BottomRight.x, means[i].x);
BottomRight.y = std::max(BottomRight.y, means[i].y);
}
This may be part of the source of your problem. At least in the usual
scheme of things, larger Y coordinates correspond to "up" and smaller
Y coordinates to "down". Assuming that's the case here, your TopLeft
is really the at the bottom left, and your BottomRight is really the
top right.
[ ... ]
I multiply it
by 10,000,000 in order to get rid of the digits pst the decimal point.
How do you figure that multiplying a floating point number is going
to truncate numbers after the decimal point? As I said above, I'd
skip the rounding for now, but when/if you decide you really need it,
write a function specifically for that purpose, and test it
thoroughly to get a reasonable idea that it at least stands some
chance of doing what you want.
Then after the division by 4 i get two decimal places back....
What makes you think it's going to be rounded to two decimal places?
I see nothing that would seem to do any such rounding or truncating.
then i add the numbers to a map in order to be able to easily access
them. type xy is a class with two double variables, x and y. This is
how my globals are declared:
map<int, xy>AvgHashTable;
"HashTable" strikes me as a lousy name. First of all, std::map isn't
implemented as a hash table, so it's misleading, and second, even if
it was a hash table, that would be an irrelevant implementation
detail anyway.
Worse than that, as noted above, you seem to be using it purely as a
slow, bulky replacement for a vector anyway. You'd be better off
using a vector and being done with it.
Now my source values are all in the format with 7 decimal numbers.
And in the end I have in TopLeft.x 49.213812599999997 and in
BottomRight.x I got 49.281173000000003... The y values look good
for both... any ideas why these numbers look so awkwardly?
It's hard to say more with certainty. Your problem could stem from
either the defective attempt at rounding, or the confusion between
top and bottom, or there could be something else involved entirely
(as noted above, the cast is suspicious at best).
--
Later,
Jerry.