-
Notifications
You must be signed in to change notification settings - Fork 88
/
Copy pathSceneDrawHelper.cs
264 lines (249 loc) · 7.97 KB
/
SceneDrawHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using System;
using System.Linq;
using System.Threading.Tasks;
using Esri.ArcGISRuntime.UI.Controls;
#if NETFX_CORE
using Windows.UI;
#else
using System.Windows.Media;
#endif
namespace SceneEditingDemo.Helpers
{
/// <summary>
/// Utility class that provides helper methods for drawing geometries on the <see cref="SceneView"/>.
/// <see cref="SceneEditHelper"/> class provides simplified interface for creating and editing geometries.
/// </summary>
public class SceneDrawHelper
{
#region Default draw symbols
//Symbol used by DrawPointAsync while moving the mouse
private static MarkerSymbol DefaultMarkerSymbol = new SimpleMarkerSymbol() { Color = System.Drawing.Color.Blue };
//Symbol used by DrawPolylineAsync
private static LineSymbol DefaultLineSymbol = new SimpleLineSymbol()
{
Width = 2,
Color = System.Drawing.Color.FromArgb(150, 0, 0, 255)
};
//Symbol used by DrawPolygonAsync
private static FillSymbol DefaultFillSymbol = new SimpleFillSymbol()
{
Outline = new SimpleLineSymbol() { Width = 2, Color = System.Drawing.Color.Black },
Color = System.Drawing.Color.FromArgb(100, 0, 0, 255)
};
//Line Symbol used to show line between last added vertex and current mouse location
private static LineSymbol DefaultLineMoveSymbol = new SimpleLineSymbol()
{
Width = 5,
Color = System.Drawing.Color.FromArgb(100, 127, 127, 127),
Style = SimpleLineSymbolStyle.Dot
};
#endregion Default draw symbols
#region public draw operations
public static async Task<MapPoint> DrawPointAsync(SceneView sceneView, System.Threading.CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<MapPoint>();
var sketchlayer = CreateSketchLayer(sceneView);
sketchlayer.Opacity = .5;
Graphic pointGraphic = null;
Action cleanupEvents = SetUpHandlers(sceneView,
(p) => //On mouse move move graphic around
{
if (p != null)
{
if (pointGraphic == null)
{
pointGraphic = new Graphic(p, DefaultMarkerSymbol);
sketchlayer.Graphics.Add(pointGraphic);
}
else pointGraphic.Geometry = p;
}
},
(p) => //View tapped - completes task and returns point
{
tcs.SetResult(p);
}
, null);
Action cleanup = () =>
{
cleanupEvents();
sceneView.GraphicsOverlays.Remove(sketchlayer);
};
cancellationToken.Register(() => tcs.SetCanceled());
MapPoint result = null;
try
{
result = await tcs.Task;
}
finally
{
cleanup();
}
return result;
}
public static async Task<Polyline> DrawPolylineAsync(SceneView sceneView, System.Threading.CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<Polyline>();
PolylineBuilder polylineBuilder = new PolylineBuilder(sceneView.SpatialReference);
polylineBuilder.AddPart(new MapPoint[] { });
var sketchlayer = CreateSketchLayer(sceneView);
Graphic lineGraphic = new Graphic() { Symbol = DefaultLineSymbol };
Graphic lineMoveGraphic = new Graphic() { Symbol = DefaultLineMoveSymbol };
sketchlayer.Graphics.AddRange(new Graphic[] { lineGraphic, lineMoveGraphic });
Action cleanupEvents = SetUpHandlers(sceneView,
(p) => //On mouse move, move completion line around
{
if (p != null && polylineBuilder.Parts.Count > 0 && polylineBuilder.Parts[0].Count > 0)
{
lineMoveGraphic.Geometry = new Polyline(new MapPoint[] { polylineBuilder.Parts[0].Last().EndPoint, p });
}
},
(p) => //On tap add a vertex
{
if (p != null)
{
polylineBuilder.AddPoint(p);
if (polylineBuilder.Parts.Count > 0 && polylineBuilder.Parts[0].Count >= 1)
lineGraphic.Geometry = polylineBuilder.ToGeometry();
}
},
(p) => //View tapped - completes task and returns point
{
tcs.SetResult(polylineBuilder.ToGeometry());
});
Action cleanup = () =>
{
cleanupEvents();
sceneView.GraphicsOverlays.Remove(sketchlayer);
};
cancellationToken.Register(() => tcs.SetCanceled());
Polyline result = null;
try
{
result = await tcs.Task;
}
finally
{
cleanup();
}
return result;
}
public static async Task<Polygon> DrawPolygonAsync(SceneView sceneView, System.Threading.CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<Polygon>();
PolygonBuilder polygonBuilder = new PolygonBuilder(sceneView.SpatialReference);
polygonBuilder.AddPart(new MapPoint[] { });
var sketchlayer = CreateSketchLayer(sceneView);
Graphic polygonGraphic = new Graphic() { Symbol = DefaultFillSymbol };
Graphic lineMoveGraphic = new Graphic() { Symbol = DefaultLineMoveSymbol };
sketchlayer.Graphics.AddRange(new Graphic[] { polygonGraphic, lineMoveGraphic });
Action cleanupEvents = SetUpHandlers(sceneView,
(p) => //On mouse move move completion line around
{
if (p != null && polygonBuilder.Parts.Count > 0 && polygonBuilder.Parts[0].Count > 0)
{
lineMoveGraphic.Geometry = new Polyline(new MapPoint[]
{
polygonBuilder.Parts[0].Last().EndPoint,
p,
polygonBuilder.Parts[0].First().StartPoint
});
}
},
(p) => //On tap add a vertex
{
if (p != null)
{
polygonBuilder.AddPoint(p);
if (polygonBuilder.Parts.Count > 0 && polygonBuilder.Parts[0].Count > 0)
{
polygonGraphic.Geometry = polygonBuilder.ToGeometry();
lineMoveGraphic.Geometry = null;
}
}
},
(p) => //View tapped - completes task and returns point
{
tcs.SetResult(polygonBuilder.ToGeometry());
});
Action cleanup = () =>
{
cleanupEvents();
sceneView.GraphicsOverlays.Remove(sketchlayer);
};
cancellationToken.Register(() => tcs.SetCanceled());
Polygon result = null;
try
{
result = await tcs.Task;
}
finally
{
cleanup();
}
return result;
}
#endregion public draw operations
#region Private utility methods
/// <summary>
/// Helper for adding mouse events
/// </summary>
/// <param name="view">The view to listen for events on.</param>
/// <param name="onMove">Action when the mouse moves.</param>
/// <param name="onTapped">Action when the view is tapped.</param>
/// <param name="onDoubleTapped">Action when the view is double tapped.</param>
/// <returns>An Action that cleans up all the event handlers.</returns>
private static Action SetUpHandlers(SceneView view, Action<MapPoint> onMove, Action<MapPoint> onTapped, Action<MapPoint> onDoubleTapped)
{
#if NETFX_CORE
Windows.UI.Xaml.Input.PointerEventHandler movehandler = null;
#else
System.Windows.Input.MouseEventHandler movehandler = null;
#endif
if (onMove != null)
{
#if NETFX_CORE
movehandler = (s, e) => onMove(view.ScreenToBaseSurface(e.GetCurrentPoint(view).Position));
view.PointerMoved += movehandler;
#else
movehandler = (s, e) => onMove(view.ScreenToBaseSurface(e.GetPosition(view)));
view.MouseMove += movehandler;
#endif
}
EventHandler<GeoViewInputEventArgs> tappedHandler = null;
if (onTapped != null)
{
tappedHandler = (s, e) => onTapped(e.Location);
view.GeoViewTapped += tappedHandler;
}
EventHandler<GeoViewInputEventArgs> doubletappedHandler = null;
if (onDoubleTapped != null)
{
doubletappedHandler = (s, e) => { e.Handled = true; onDoubleTapped(e.Location); };
view.GeoViewDoubleTapped += doubletappedHandler;
}
Action cleanup = () =>
{
if (movehandler != null)
#if NETFX_CORE
view.PointerMoved -= movehandler;
#else
view.MouseMove -= movehandler;
#endif
if (tappedHandler != null) view.GeoViewTapped -= tappedHandler;
if (doubletappedHandler != null) view.GeoViewDoubleTapped -= doubletappedHandler;
};
return cleanup;
}
private static GraphicsOverlay CreateSketchLayer(GeoView scene)
{
GraphicsOverlay go = new GraphicsOverlay();
scene.GraphicsOverlays.Add(go);
return go;
}
#endregion Private utility methods
}
}