{******************************************************************************} {* SAS.Planet (SAS.Планета) *} {* Copyright (C) 2007-2012, SAS.Planet development team. *} {* This program is free software: you can redistribute it and/or modify *} {* it under the terms of the GNU General Public License as published by *} {* the Free Software Foundation, either version 3 of the License, or *} {* (at your option) any later version. *} {* *} {* This program is distributed in the hope that it will be useful, *} {* but WITHOUT ANY WARRANTY; without even the implied warranty of *} {* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} {* GNU General Public License for more details. *} {* *} {* You should have received a copy of the GNU General Public License *} {* along with this program. If not, see . *} {* *} {* http://sasgis.ru *} {* az@sasgis.ru *} {******************************************************************************} unit u_LocalCoordConverterFactorySimpe; interface uses Types, t_GeoTypes, i_CoordConverter, i_CoordConverterFactory, i_LocalCoordConverter, i_LocalCoordConverterFactorySimpe; type TLocalCoordConverterFactorySimpe = class(TInterfacedObject, ILocalCoordConverterFactorySimpe) private FProjectionFactory: IProjectionInfoFactory; private function CreateConverter( const ALocalRect: TRect; const AZoom: Byte; const AGeoConverter: ICoordConverter; const AMapScale: TDoublePoint; const ALocalTopLeftAtMap: TDoublePoint ): ILocalCoordConverter; function CreateConverterNoScale( const ALocalRect: TRect; const AZoom: Byte; const AGeoConverter: ICoordConverter; const ALocalTopLeftAtMap: TPoint ): ILocalCoordConverter; function CreateForTile( const ATile: TPoint; const AZoom: Byte; const AGeoConverter: ICoordConverter ): ILocalCoordConverter; function CreateBySourceWithStableTileRect( const ASource: ILocalCoordConverter ): ILocalCoordConverter; function CreateBySourceWithStableTileRectAndOtherGeo( const ASource: ILocalCoordConverter; const AGeoConverter: ICoordConverter ): ILocalCoordConverter; public constructor Create( const AProjectionFactory: IProjectionInfoFactory ); end; implementation uses u_LocalCoordConverter; { TLocalCoordConverterFactorySimpe } constructor TLocalCoordConverterFactorySimpe.Create( const AProjectionFactory: IProjectionInfoFactory ); begin inherited Create; FProjectionFactory := AProjectionFactory; end; function TLocalCoordConverterFactorySimpe.CreateBySourceWithStableTileRect( const ASource: ILocalCoordConverter ): ILocalCoordConverter; var VZoom: Byte; VSourcePixelRect: TRect; VConverter: ICoordConverter; VTileRect: TRect; VResultPixelRect: TRect; VTileSize: TPoint; VSize: TPoint; VCenter: TPoint; begin VConverter := ASource.GetGeoConverter; VZoom := ASource.GetZoom; VSourcePixelRect := ASource.GetRectInMapPixel; {Половина размера по осям} VSize := Point( (VSourcePixelRect.Right - VSourcePixelRect.Left) div 2, (VSourcePixelRect.Bottom - VSourcePixelRect.Top) div 2 ); {Сначала подсчитаем координаты центра в пикселях} VCenter := Point(VSourcePixelRect.Left + VSize.X, VSourcePixelRect.Top + VSize.Y); {И переведём его в координаты центрального тайла} VCenter := VConverter.PixelPos2TilePos(VCenter, VZoom); {Получим размеры центрального тайла} VTileRect := VConverter.TilePos2PixelRect(VCenter, VZoom); VTileSize := Point(VTileRect.Right - VTileRect.Left, VTileRect.Bottom - VTileRect.Top); {Потом вычислим нужный размер в тайлах} VSize.X := (VSize.X - 1) div VTileSize.X + 1; VSize.Y := (VSize.Y - 1) div VTileSize.Y + 1; {И раздвинем границы от центрального тайла} VResultPixelRect := VConverter.TileRect2PixelRect( Rect( VCenter.X - VSize.X, VCenter.Y - VSize.Y, VCenter.X + VSize.X + 1, VCenter.Y + VSize.Y + 1 ), VZoom ); {Дальше ничего не трогал} if EqualRect(VSourcePixelRect, VResultPixelRect) then begin Result := ASource; end else begin Result := TLocalCoordConverterNoScale.Create( Rect( 0, 0, VResultPixelRect.Right - VResultPixelRect.Left, VResultPixelRect.Bottom - VResultPixelRect.Top ), ASource.ProjectionInfo, VResultPixelRect.TopLeft ); end; end; function TLocalCoordConverterFactorySimpe.CreateBySourceWithStableTileRectAndOtherGeo( const ASource: ILocalCoordConverter; const AGeoConverter: ICoordConverter ): ILocalCoordConverter; var VZoom: Byte; VSourcePixelRect: TRect; VSourceLonLatRect: TDoubleRect; VConverter: ICoordConverter; VTileRect: TRect; VResultPixelRect: TRect; VViewSize: TPoint; VMovedTile: TPoint; VMovedPixelRect: TRect; VMovedTileRect: TRect; begin VConverter := ASource.GetGeoConverter; VZoom := ASource.GetZoom; VSourcePixelRect := ASource.GetRectInMapPixel; VConverter.CheckPixelRect(VSourcePixelRect, VZoom); VSourceLonLatRect := VConverter.PixelRect2LonLatRect(VSourcePixelRect, VZoom); AGeoConverter.CheckZoom(VZoom); AGeoConverter.CheckLonLatRect(VSourceLonLatRect); VSourcePixelRect := AGeoConverter.LonLatRect2PixelRect(VSourceLonLatRect, VZoom); VViewSize.X := VSourcePixelRect.Right - VSourcePixelRect.Left; VViewSize.Y := VSourcePixelRect.Bottom - VSourcePixelRect.Top; AGeoConverter.CheckPixelRect(VSourcePixelRect, VZoom); VTileRect := AGeoConverter.PixelRect2TileRect(VSourcePixelRect, VZoom); VMovedTile := VTileRect.TopLeft; Inc(VMovedTile.X); Inc(VMovedTile.Y); AGeoConverter.CheckTilePosStrict(VMovedTile, VZoom, False); VMovedPixelRect.TopLeft := AGeoConverter.TilePos2PixelPos(VMovedTile, VZoom); VMovedPixelRect.Right := VMovedPixelRect.Left + VViewSize.X; VMovedPixelRect.Bottom := VMovedPixelRect.Top + VViewSize.Y; AGeoConverter.CheckPixelRect(VMovedPixelRect, VZoom); VMovedTileRect := AGeoConverter.PixelRect2TileRect(VMovedPixelRect, VZoom); VTileRect.Right := VMovedTileRect.Right; VTileRect.Bottom := VMovedTileRect.Bottom; VResultPixelRect := AGeoConverter.TileRect2PixelRect(VTileRect, VZoom); Result := TLocalCoordConverterNoScale.Create( Rect(0, 0, VResultPixelRect.Right - VResultPixelRect.Left, VResultPixelRect.Bottom - VResultPixelRect.Top), FProjectionFactory.GetByConverterAndZoom(AGeoConverter, VZoom), VResultPixelRect.TopLeft ); end; function TLocalCoordConverterFactorySimpe.CreateConverter( const ALocalRect: TRect; const AZoom: Byte; const AGeoConverter: ICoordConverter; const AMapScale, ALocalTopLeftAtMap: TDoublePoint ): ILocalCoordConverter; begin Result := TLocalCoordConverter.Create( ALocalRect, FProjectionFactory.GetByConverterAndZoom(AGeoConverter, AZoom), AMapScale, ALocalTopLeftAtMap ); end; function TLocalCoordConverterFactorySimpe.CreateConverterNoScale( const ALocalRect: TRect; const AZoom: Byte; const AGeoConverter: ICoordConverter; const ALocalTopLeftAtMap: TPoint ): ILocalCoordConverter; begin Result := TLocalCoordConverterNoScale.Create( ALocalRect, FProjectionFactory.GetByConverterAndZoom(AGeoConverter, AZoom), ALocalTopLeftAtMap ); end; function TLocalCoordConverterFactorySimpe.CreateForTile( const ATile: TPoint; const AZoom: Byte; const AGeoConverter: ICoordConverter ): ILocalCoordConverter; var VPixelRect: TRect; VBitmapTileRect: TRect; begin VPixelRect := AGeoConverter.TilePos2PixelRect(ATile, AZoom); VBitmapTileRect.Left := 0; VBitmapTileRect.Top := 0; VBitmapTileRect.Right := VPixelRect.Right - VPixelRect.Left; VBitmapTileRect.Bottom := VPixelRect.Bottom - VPixelRect.Top; Result := TLocalCoordConverterNoScale.Create( VBitmapTileRect, FProjectionFactory.GetByConverterAndZoom(AGeoConverter, AZoom), VPixelRect.TopLeft ); end; end.