У меня есть устаревшее приложение для просмотра карт, использующее WinForms. Оно медленное (раньше скорость была приемлемой, но появились Google Maps, Google Earth и Теперь мне разрешено делать if быстрее :)
После всех очевидных улучшений скорости (кеширование, параллельное выполнение, не отрисовка того, что не нужно отрисовывать и т.д.), мой профилировщик показывает мне, что настоящая узкая точка — это преобразования координатпри преобразовании точек из пространства карты в пространство экрана. Обычно код преобразования выглядит так:
public Point MapToScreen(PointF input)
{
// Note that North is negative!
var result = new Point(
(int)((input.X - this.currentView.X) * this.Scale),
(int)((input.Y - this.currentView.Y) * this.Scale));
return result;
}
Реальная реализация сложнее. Широта/долгота представлены целыми числами. Чтобы избежать потери точности, они умножаются на 2^20 (~ 1 миллион). Вот как представляется координата.
public struct Position
{
public const int PrecisionCompensationPower = 20;
public const int PrecisionCompensationScale = 1048576; // 2^20
public readonly int LatitudeInt; // North is negative!
public readonly int LongitudeInt;
}
Важно, что возможные коэффициенты масштабирования также явно привязаны к степени 2. Это позволяет нам заменить умножение битовым сдвигом.Таким образом, реальный алгоритм выглядит так:
public Point MapToScreen(Position input)
{
Point result = new Point();
result.X = (input.LongitudeInt - this.UpperLeftPosition.LongitudeInt) >>
(Position.PrecisionCompensationPower - this.ZoomLevel);
result.Y = (input.LatitudeInt - this.UpperLeftPosition.LatitudeInt) >>
(Position.PrecisionCompensationPower - this.ZoomLevel);
return result;
}
(UpperLeftPosition представляет левый верхний угол экрана в пространстве карты.) Теперь я думаю о том, чтобы перенести эти вычисления на GPU. Может ли кто-нибудь показать мне пример, как это сделать?
Мы используем .NET4.0, но желательно, чтобы код работал и в Windows XP. Кроме того, библиотеки под GPL мы не можем использовать.