diff --git a/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpi b/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpi index 07a235cbd..34255f293 100644 --- a/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpi +++ b/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpi @@ -44,6 +44,7 @@ + diff --git a/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpr b/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpr index 595f1298f..6a08ae9fa 100644 --- a/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpr +++ b/components/lazmapviewer/examples/restricted_zoom_pan/RestrictedZoomPan_Demo.lpr @@ -17,7 +17,7 @@ uses begin RequireDerivedFormResource := True; - Application.Scaled := True; + Application.Scaled:=True; Application.{%H-}MainFormOnTaskbar := True; Application.Initialize; Application.CreateForm(TForm1, Form1); diff --git a/components/lazmapviewer/examples/restricted_zoom_pan/main.lfm b/components/lazmapviewer/examples/restricted_zoom_pan/main.lfm index 2f6be6eea..7d85dfbd6 100644 --- a/components/lazmapviewer/examples/restricted_zoom_pan/main.lfm +++ b/components/lazmapviewer/examples/restricted_zoom_pan/main.lfm @@ -10,11 +10,13 @@ object Form1: TForm1 OnCreate = FormCreate object MapView1: TMapView Left = 0 - Height = 538 - Top = 42 + Height = 511 + Top = 69 Width = 686 Active = True Align = alClient + Cyclic = True + DebugTiles = True DownloadEngine = MapView1.BuiltInDLE DrawingEngine = MapView1.BuiltInDE Layers = <> @@ -42,23 +44,60 @@ object Form1: TForm1 end object Panel1: TPanel Left = 0 - Height = 42 + Height = 69 Top = 0 Width = 686 Align = alTop AutoSize = True BevelOuter = bvNone - ClientHeight = 42 + ClientHeight = 69 ClientWidth = 686 TabOrder = 2 object Label1: TLabel - Left = 6 + AnchorSideLeft.Control = rgCenter + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Panel1 + AnchorSideTop.Side = asrCenter + Left = 190 Height = 30 - Top = 6 - Width = 674 - Align = alTop + Top = 19 + Width = 237 + BorderSpacing.Left = 12 BorderSpacing.Around = 6 Caption = 'London cannot be moved out of the window'#13#10'Only zoom levels > 8 allowed.' end + object rgCenter: TRadioGroup + AnchorSideLeft.Control = Panel1 + AnchorSideTop.Control = Panel1 + AnchorSideTop.Side = asrCenter + AnchorSideRight.Side = asrBottom + Left = 12 + Height = 45 + Top = 12 + Width = 160 + AutoFill = True + AutoSize = True + BorderSpacing.Around = 12 + Caption = 'Center' + ChildSizing.LeftRightSpacing = 12 + ChildSizing.TopBottomSpacing = 3 + ChildSizing.HorizontalSpacing = 12 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 2 + ClientHeight = 25 + ClientWidth = 156 + Columns = 2 + ItemIndex = 0 + Items.Strings = ( + 'London' + 'Dateline' + ) + TabOrder = 0 + OnClick = rgCenterClick + end end end diff --git a/components/lazmapviewer/examples/restricted_zoom_pan/main.pas b/components/lazmapviewer/examples/restricted_zoom_pan/main.pas index 53384375f..b25473632 100644 --- a/components/lazmapviewer/examples/restricted_zoom_pan/main.pas +++ b/components/lazmapviewer/examples/restricted_zoom_pan/main.pas @@ -9,16 +9,22 @@ uses Dialogs, mvMapViewer, mvTypes, mvGeoMath; type + + { TForm1 } + TForm1 = class(TForm) Label1: TLabel; MapView1: TMapView; Panel1: TPanel; + rgCenter: TRadioGroup; StatusBar1: TStatusBar; procedure FormCreate(Sender: TObject); procedure MapView1Change(Sender: TObject); + procedure rgCenterClick(Sender: TObject); private FInitialArea: TRealArea; - procedure MapCenterMoving(Sender: TObject; NewCenter: TRealPoint; var Allow: Boolean); + FMinZoom: Integer; + procedure MapCenterMoving(Sender: TObject; var NewCenter: TRealPoint; var Allow: Boolean); procedure MapZoomChanging(Sender: TObject; NewZoom: Integer; var Allow: Boolean); public @@ -32,18 +38,10 @@ implementation {$R *.lfm} -const - MIN_ZOOM = 8; - procedure TForm1.FormCreate(Sender: TObject); begin - MapView1.MapCenter.Longitude := -0.15; // London - MapView1.MapCenter.Latitude := 51.5; - MapView1.Zoom := MIN_ZOOM; - MapView1.OnZoomChanging := @MapZoomChanging; - MapView1.OnCenterMoving := @MapCenterMoving; + rgCenterClick(nil); MapView1Change(nil); - FInitialArea := MapView1.GetVisibleArea; end; procedure TForm1.MapView1Change(Sender: TObject); @@ -53,15 +51,42 @@ begin Statusbar1.Panels[2].Text := 'Zoom ' + IntToStr(MapView1.Zoom); end; -procedure TForm1.MapCenterMoving(Sender: TObject; NewCenter: TRealPoint; +procedure TForm1.rgCenterClick(Sender: TObject); +const + INFO = '%s cannot be moved out of the window.'#13'Only zoom levels > %d allowed.'; +begin + MapView1.OnZoomChanging := nil; + MapView1.OnCenterMoving := nil; + case rgCenter.ItemIndex of + 0: begin // London + MapView1.MapCenter.Longitude := -DMSToDeg(0, 7, 54.6); + MapView1.MapCenter.Latitude := DMSToDeg(51, 30, 31.2); + FMinZoom := 8; + Label1.Caption := Format(INFO, ['London', FMinZoom]); + end; + 1: begin // somewhere in Siberia near dateline + MapView1.MapCenter.Longitude := 178; + MapView1.MapCenter.Latitude := 64.7; + FMinZoom := 6; + Label1.Caption := Format(INFO, ['Center', FMinZoom]); + end; + end; + MapView1.Zoom := FMinZoom; + FInitialArea := MapView1.GetVisibleArea; + MapView1.OnZoomChanging := @MapZoomChanging; + MapView1.OnCenterMoving := @MapCenterMoving; +end; + +procedure TForm1.MapCenterMoving(Sender: TObject; var NewCenter: TRealPoint; var Allow: Boolean); begin - Allow := FInitialArea.ContainsPoint(NewCenter); + if not FInitialArea.ContainsPoint(NewCenter) then + FInitialArea.MakeAreaPoint(NewCenter); end; procedure TForm1.MapZoomChanging(Sender: TObject; NewZoom: Integer; var Allow: Boolean); begin - Allow := NewZoom >= MIN_ZOOM; + Allow := NewZoom >= FMinZoom; end; end. diff --git a/components/lazmapviewer/source/mvengine.pas b/components/lazmapviewer/source/mvengine.pas index 8041ed7fc..1618de60d 100644 --- a/components/lazmapviewer/source/mvengine.pas +++ b/components/lazmapviewer/source/mvengine.pas @@ -34,7 +34,7 @@ type TTileDownloadedEvent = procedure (const TileId: TTileId) of object; - TCenterMovingEvent = procedure (Sender: TObject; NewCenter: TRealPoint; var Allow: Boolean) of object; + TCenterMovingEvent = procedure (Sender: TObject; var NewCenter: TRealPoint; var Allow: Boolean) of object; TZoomChangingEvent = procedure (Sender: TObject; NewZoom: Integer; var Allow: Boolean) of object; TTileIdArray = Array of TTileId; @@ -134,7 +134,7 @@ type Procedure DrawTile(const TileId: TTileId; X,Y: integer; TileImg: TPictureCacheItem); Procedure DoDrag(Sender: TDragObj); Procedure DoEndDrag(Sender: TDragObj); - Function DoCenterMoving(ANewPoint: TRealPoint): Boolean; + Function DoCenterMoving(var ANewPoint: TRealPoint): Boolean; Function DoZoomChanging(ANewZoom: Integer): Boolean; public @@ -476,7 +476,7 @@ begin FInDrag := False; end; -function TMapViewerEngine.DoCenterMoving(ANewPoint: TRealPoint): Boolean; +function TMapViewerEngine.DoCenterMoving(var ANewPoint: TRealPoint): Boolean; begin Result := true; if Assigned(FOnCenterMoving) then diff --git a/components/lazmapviewer/source/mvtypes.pas b/components/lazmapviewer/source/mvtypes.pas index 8c7bb45df..e613c49f8 100644 --- a/components/lazmapviewer/source/mvtypes.pas +++ b/components/lazmapviewer/source/mvtypes.pas @@ -61,6 +61,7 @@ Type function Equal(Area: TRealArea): Boolean; function Intersection(const Area: TRealArea): TRealArea; function Intersects(const Area: TRealArea): boolean; + procedure MakeAreaPoint(var APoint: TRealPoint); function Union(const Area: TRealArea): TRealArea; end; @@ -87,7 +88,6 @@ begin Result := (x > x1) or (x < x2); end; - { Checks whether the line segment between A1 and A2 intersects the line segment between B1 and B2. It is assumed that A1 < A2 and B1 < B2. } function LinearIntersects(A1, A2, B1, B2: Extended): Boolean; @@ -238,6 +238,28 @@ begin end; end; +{ Makes sure that x is between Left and Right (geometrically) where Right is + allowed to be smaller than Left. } +procedure RestrictToRange(var x: Double; Left, Right: Double); +begin + // Normal order + if Left < Right then + begin + if x < Left then + x := Left + else + if x > Right then + x := Right; + end else + begin + // Reverse order + if (x > 0) and (x < Left) then + x := Left + else + if (x < 0) and (x > Right) then + x := Right; + end; +end; { TRealPoint } @@ -339,6 +361,13 @@ begin CyclicIntersects(TopLeft.Lon, BottomRight.Lon, Area.TopLeft.Lon, Area.BottomRight.Lon); end; +{ Makes sure that the point cannot leave the area. } +procedure TRealArea.MakeAreaPoint(var APoint: TRealPoint); +begin + RestrictToRange(APoint.Lat, BottomRight.Lat, TopLeft.Lat); + RestrictToRange(APoint.Lon, TopLeft.Lon, BottomRight.Lon); +end; + { Calculates the union with the other area. When the date line is crossed the right longitude becomes smaller than the left longitude! } function TRealArea.Union(const Area: TRealArea): TRealArea;