From a036319196b55c4001cb3ec5adbc8a8c2c5db927 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Thu, 20 Mar 2025 19:03:33 +0000 Subject: [PATCH] LazMapViewer: Add methods DeleteSelectedPoints, ConvertSelectedPointsToMapArea and ConvertSelectedPointsToMapTrack to TMarkerSelectAndDragPlugin git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9690 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../MarkerSelectAndDrag_Demo.lpi | 6 +- .../markerselectdrag_demo/main.lfm | 41 +++- .../markerselectdrag_demo/main.pas | 50 +++++ .../plugins/markers/mvmarkerplugins.pas | 199 +++++++++++++++++- 4 files changed, 279 insertions(+), 17 deletions(-) diff --git a/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/MarkerSelectAndDrag_Demo.lpi b/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/MarkerSelectAndDrag_Demo.lpi index 5b8cbb10b..c5d7062b7 100644 --- a/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/MarkerSelectAndDrag_Demo.lpi +++ b/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/MarkerSelectAndDrag_Demo.lpi @@ -59,12 +59,8 @@ + - - - - - diff --git a/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.lfm b/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.lfm index 97ac12303..f43f0b090 100644 --- a/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.lfm +++ b/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.lfm @@ -14,7 +14,6 @@ object MainForm: TMainForm Top = 0 Width = 653 Align = alClient - Cyclic = True DownloadEngine = MapView.BuiltInDLE DrawingEngine = MapView.BuiltInDE Layers = <> @@ -153,6 +152,46 @@ object MainForm: TMainForm TabOrder = 2 OnChange = cbMultiSelectChange end + object Button1: TButton + AnchorSideLeft.Control = rgClickMode + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = rgClickMode + Left = 520 + Height = 25 + Top = 8 + Width = 109 + AutoSize = True + BorderSpacing.Left = 8 + Caption = 'Delete selection' + TabOrder = 3 + OnClick = Button1Click + end + object Button2: TButton + AnchorSideLeft.Control = Button1 + AnchorSideTop.Control = Button1 + AnchorSideTop.Side = asrBottom + Left = 520 + Height = 25 + Top = 33 + Width = 111 + AutoSize = True + Caption = 'Convert to track' + TabOrder = 4 + OnClick = Button2Click + end + object Button3: TButton + AnchorSideLeft.Control = Button1 + AnchorSideTop.Control = Button2 + AnchorSideTop.Side = asrBottom + Left = 520 + Height = 25 + Top = 58 + Width = 107 + AutoSize = True + Caption = 'Convert to area' + TabOrder = 5 + OnClick = Button3Click + end end object PluginManager: TMvPluginManager Left = 401 diff --git a/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.pas b/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.pas index dc7cafc12..ac936d630 100644 --- a/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.pas +++ b/components/lazmapviewer/examples/plugin_demos/markerselectdrag_demo/main.pas @@ -15,6 +15,9 @@ type TMainForm = class(TForm) Bevel1: TBevel; + Button1: TButton; + Button2: TButton; + Button3: TButton; cgPointTypes: TCheckGroup; cbMultiSelect: TCheckBox; Label1: TLabel; @@ -24,6 +27,9 @@ type MapView: TMapView; PluginManager: TMvPluginManager; rgClickMode: TRadioGroup; + procedure Button1Click(Sender: TObject); + procedure Button2Click(Sender: TObject); + procedure Button3Click(Sender: TObject); procedure cgPointTypesItemClick(Sender: TObject; Index: integer); procedure cbMultiSelectChange(Sender: TObject); procedure FormCreate(Sender: TObject); @@ -111,6 +117,24 @@ procedure TMainForm.FormCreate(Sender: TObject); TMapTrackPoint(track.Points.Add).RealPoint := APoints[i]; end; + procedure AddMapArea(const APoints: TRealPointArray); + var + layer: TMapLayer; + area: TMapArea; + i: Integer; + begin + if MapView.Layers.Count = 0 then + layer := MapView.Layers.Add as TMapLayer + else + layer := MapView.Layers[0]; + area := layer.Areas.Add as TMapArea; + area.Caption := 'Test area'; + area.FillColor := clBlue; + area.Opacity := 0.5; + for i := 0 to High(APoints) do + TMapAreaPoint(area.Points.Add).RealPoint := APoints[i]; + end; + var i: Integer; begin @@ -125,6 +149,8 @@ begin AddGPSTrack([RealPoint(-20,20), RealPoint(20, 0), RealPoint(-20,-20)]); AddMapTrack([RealPoint(20,20), RealPoint(-20,0), RealPoint(20,-20)]); + AddMapArea ([RealPoint(60, -45), RealPoint(70, -48), RealPoint(64, -35)]); + Plugin := TMarkerSelectAndDragPlugin.Create(PluginManager); for i := 0 to cgPointTypes.Items.Count-1 do @@ -148,6 +174,30 @@ begin Plugin.PointTypes := pointTypes; end; +procedure TMainForm.Button1Click(Sender: TObject); +begin + Plugin.DeleteSelectedPoints(MapView); +end; + +procedure TMainForm.Button2Click(Sender: TObject); +begin + with Plugin.ConvertSelectedPointsToMapTrack(MapView, MapView.Layers[0]) do + begin + LineColor := clGreen; + LineWidth := 1.0; + end; +end; + +procedure TMainForm.Button3Click(Sender: TObject); +begin + with Plugin.ConvertSelectedPointsToMapArea(MapView, MapView.Layers[0]) do + begin + FillColor := clBlack; + LineColor := clBlack; + Opacity := 0.5; + end; +end; + procedure TMainForm.cbMultiSelectChange(Sender: TObject); begin Plugin.MultiSelect := cbMultiSelect.Checked; diff --git a/components/lazmapviewer/source/addons/plugins/markers/mvmarkerplugins.pas b/components/lazmapviewer/source/addons/plugins/markers/mvmarkerplugins.pas index 63908fd81..39e94374d 100644 --- a/components/lazmapviewer/source/addons/plugins/markers/mvmarkerplugins.pas +++ b/components/lazmapviewer/source/addons/plugins/markers/mvmarkerplugins.pas @@ -107,11 +107,12 @@ type FSelection: TGPSPointList; FOrigSelection: array of TRealPoint; // Selection before dragging starts FOnDrawPoint: TMarkerDrawPointEvent; - FOnSelect: TNotifyEvent; + FOnSelectionChange: TNotifyEvent; procedure SetMultiSelect(AValue: Boolean); protected procedure AddToSelection(AMapView: TMapView; APoint: TGPSPoint); - procedure DoSelect(AMapView: TMapView); + procedure DeleteFromList(AMapView: TMapView; APoint: TGPSPoint); + procedure DoSelectionChange(AMapView: TMapView); procedure DragStart(AMapView: TMapView); procedure DragTo(AMapView: TMapView; X, Y: Integer); procedure DragEnd(AMapView: TMapView); @@ -131,13 +132,16 @@ type public constructor Create(AOwner: TComponent); override; destructor Destroy; override; + function ConvertSelectedPointsToMapArea(AMapView: TMapView; ALayer: TMapLayer): TMapArea; + function ConvertSelectedPointsToMapTrack(AMapView: TMapView; ALayer: TMapLayer): TMapTrack; + procedure DeleteSelectedPoints(AMapView: TMapView); property Selection: TGPSPointList read FSelection; published property ClickMode: TMarkerClickMode read FClickMode write FClickMode default mcmAddToSelection; property DragCursor: TCursor read FDragCursor write FDragCursor default crSizeAll; property MultiSelect: Boolean read FMultiSelect write SetMultiSelect default false; property OnDrawPoint: TMarkerDrawPointEvent read FOnDrawPoint write FOnDrawPoint; - property OnSelect: TNotifyEvent read FOnSelect write FOnSelect; + property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange; end; @@ -354,6 +358,29 @@ end; { TMarkerSelectAndDragPlugin } +type + TMarkerData = record + Lat, Lon: Double; + Elevation: Double; + DateTime: TDateTime; + end; + +function GPSPointToMarkerData(P: TGPSPoint): TMarkerData; +begin + Result.Lat := P.Lat; + Result.Lon := P.Lon; + Result.Elevation := P.Elevation; + Result.DateTime := P.DateTime; +end; + +procedure MarkerDataToGPSPoint(M: TMarkerData; P: TGPSPoint); +begin + P.Lat := M.Lat; + P.Lon := M.Lon; + P.Elevation := M.Elevation; + P.DateTime := M.DateTime; +end; + constructor TMarkerSelectAndDragPlugin.Create(AOwner: TComponent); begin inherited; @@ -384,7 +411,51 @@ begin FSelection.Clear; FSelection.Add(APoint); end; - DoSelect(AMapView); + DoSelectionChange(AMapView); +end; + +function TMarkerSelectAndDragPlugin.ConvertSelectedPointsToMapArea( + AMapView: TMapView; ALayer: TMapLayer): TMapArea; +var + M: TMarkerData; + P: TMapPoint; +begin + if FSelection.Count < 2 then + raise EMvPluginException.Create('Selection must contain at least 3 points'); + + Result := ALayer.Areas.Add as TMapArea; + while FSelection.Count > 0 do + begin + M := GPSPointToMarkerData(FSelection[0]); + DeleteFromList(AMapView, FSelection[0]); + FSelection.Delete(0); + P := Result.Points.Add as TMapPoint; + MarkerDataToGPSPoint(M, TGPSPoint(P.GPSObj)); + end; + Update; + DoSelectionChange(AMapView); +end; + +function TMarkerSelectAndDragPlugin.ConvertSelectedPointsToMapTrack( + AMapView: TMapView; ALayer: TMapLayer): TMapTrack; +var + M: TMarkerData; + P: TMapPoint; +begin + if FSelection.Count < 2 then + raise EMvPluginException.Create('Selection must contain at least 2 points'); + + Result := ALayer.Tracks.Add as TMapTrack; + while FSelection.Count > 0 do + begin + M := GPSPointToMarkerData(FSelection[0]); + DeleteFromList(AMapView, FSelection[0]); + FSelection.Delete(0); + P := Result.Points.Add as TMapPoint; + MarkerDataToGPSPoint(M, TGPSPoint(P.GPSObj)); + end; + Update; + DoSelectionChange(AMapView); end; procedure TMarkerSelectAndDragPlugin.AfterDrawObjects(AMapView: TMapView; @@ -394,10 +465,22 @@ begin DrawSelection(AMapView); end; -procedure TMarkerSelectAndDragPlugin.DoSelect(AMapView: TMapView); +procedure TMarkerSelectAndDragPlugin.DeleteSelectedPoints(AMapView: TMapView); +var + i: Integer; begin - if Assigned(FOnSelect) then - FOnSelect(AMapView); + for i := FSelection.Count-1 downto 0 do + begin + DeleteFromList(AMapView, FSelection[i]); + FSelection.Delete(i); + end; + Update; +end; + +procedure TMarkerSelectAndDragPlugin.DoSelectionChange(AMapView: TMapView); +begin + if Assigned(FOnSelectionChange) then + FOnSelectionChange(AMapView); end; procedure TMarkerSelectAndDragPlugin.DragStart(AMapView: TMapView); @@ -406,7 +489,7 @@ var begin AMapView.Cursor := DragCursor; FDragging := true; - // Save original selection point coordinates in case it must be restored later. + // Save original selection point coordinates in case they must be restored later. SetLength(FOrigSelection, FSelection.Count); for i := 0 to High(FOrigSelection) do FOrigSelection[i] := FSelection[i].RealPoint; @@ -467,7 +550,7 @@ begin DE.PenColor := clRed; DE.PenStyle := psSolid; DE.PenWidth := 2; - DE.BrushColor := clWhite; + DE.BrushColor := clBlack; DE.BrushStyle := bsSolid; markerSize := AMapView.Scale96ToFont(MARKER_SIZE); for i := 0 to FSelection.Count - 1 do @@ -476,7 +559,7 @@ begin begin // The last point is marked as being "focused" DE.PenWidth := 3; - DE.BrushColor := clBlack; + DE.BrushColor := clLime; inc(markerSize, 1); end; P := AMapView.LatLonToScreen(FSelection[i].RealPoint); @@ -559,6 +642,100 @@ begin DragEnd(AMapView); end; +{ Searches for the given point in all the point lists of the mapviewer + (GPSItems, Layers, Tracks, Areas, POIs). If found, the point is removed + from the list and destroyed. } +procedure TMarkerSelectAndDragPlugin.DeleteFromList(AMapView: TMapView; + APoint: TGPSPoint); +var + i, j, k: Integer; + gpsLayer: TGPSObjectList; + gpsPolyline: TGPSPolyLine; + item: TGPSObj; + p: TMapPoint; + mapLayer: TMapLayer; + mapTrack: TMapTrack; + mapArea: TMapArea; + + function IsSamePoint(AItem: TGPSObj): Boolean; + begin + Result := (AItem is TGPSPoint) and TGPSPoint(AItem).RealPoint.Equal(APoint.RealPoint); + end; + +begin + // Check the 10 layers of GPSItems + for i := 0 to 9 do + begin + gpsLayer := AMapView.GPSLayer[i]; + for j := 0 to gpsLayer.Count-1 do + begin + item := gpsLayer[j]; + if IsSamePoint(item) then + begin + gpsLayer.Delete(item); + exit; + end; + if (item is TGPSPolyline) then + begin + gpsPolyLine := TGPSPolyLine(item); + for k := 0 to gpsPolyLine.Points.Count-1 do + begin + item := gpsPolyLine.Points[k]; + if IsSamePoint(item) then + begin + gpsPolyLine.Points.Delete(k); + exit; + end; + end; + end; + end; + end; + + // Check the map layers + for i := 0 to AMapView.Layers.Count-1 do + begin + mapLayer := AMapView.Layers[i]; + // Points of interest? + for j := 0 to mapLayer.PointsOfInterest.Count-1 do + begin + p := mapLayer.PointsOfInterest[j]; + if IsSamePoint(p.GPSObj) then + begin + mapLayer.PointsOfInterest.Delete(j); + exit; + end; + end; + // Tracks? + for j := 0 to mapLayer.Tracks.Count-1 do + begin + mapTrack := mapLayer.Tracks[j]; + for k := 0 to mapTrack.Points.Count-1 do + begin + p := mapTrack.Points[k]; + if IsSamePoint(p.GPSObj) then + begin + mapTrack.Points.Delete(k); + exit; + end; + end; + end; + // Areas? + for j := 0 to mapLayer.Areas.Count-1 do + begin + mapArea := mapLayer.Areas[j]; + for k := 0 to mapArea.Points.Count-1 do + begin + p := mapArea.Points[k]; + if IsSamePoint(p.GPSObj) then + begin + mapArea.Points.Delete(k); + exit; + end; + end; + end; + end; +end; + procedure TMarkerSelectAndDragPlugin.SetMultiSelect(AValue: Boolean); begin if FMultiSelect = AValue then exit; @@ -584,7 +761,7 @@ begin FSelection.Add(APoint); end else FSelection.Delete(idx); - DoSelect(AMapView); + DoSelectionChange(AMapView); end;