Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Location / Tizen.Location / LocationBoundary.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20
21 namespace Tizen.Location
22 {
23     /// <summary>
24     /// Abstract class which provides functions related to geographic bounds information.
25     /// </summary>
26     /// <since_tizen>3</since_tizen>
27     public abstract class LocationBoundary : IDisposable
28     {
29         internal IntPtr handle;
30         private bool _disposed = false;
31
32         /// <summary>
33         /// Gets the location boundary type.
34         /// </summary>
35         /// <since_tizen>3</since_tizen>
36         public BoundaryType BoundaryType{ get; internal set; }
37
38         internal LocationBoundary() { }
39         /// <summary>
40         /// The destructor of LocationBoundary class.
41         /// </summary>
42         /// <since_tizen>3</since_tizen>
43         ~LocationBoundary()
44         {
45             Log.Info(Globals.LogTag, "The destructor of LocationBoundary class");
46             Dispose(false);
47         }
48
49         internal IntPtr GetHandle()
50         {
51             return handle;
52         }
53
54         /// <summary>
55         /// Checks if the boundary contains the specified geographical coordinates.
56         /// </summary>
57         /// <since_tizen>3</since_tizen>
58         /// <param name="coordinate"> The coordinate which needs to be checked.</param>
59         /// <returns>Returns a boolean value indicating whether or not the specified coordinate lies in the geographical area.</returns>
60         public bool BoundaryContainsCoordinates(Coordinate coordinate)
61         {
62             Log.Info(Globals.LogTag, "Checking if coordinates are contained within boundary");
63             return Interop.LocationBoundary.IsValidCoordinates(handle, coordinate);
64         }
65
66         /// <summary>
67         /// The overidden Dispose method of the IDisposable class.
68         /// </summary>
69         /// <since_tizen>3</since_tizen>
70         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
71         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
72         public void Dispose()
73         {
74             Log.Info(Globals.LogTag, "Dispose");
75             Dispose(true);
76             GC.SuppressFinalize(this);
77         }
78
79         protected virtual void Dispose(bool disposing)
80         {
81             Log.Info(Globals.LogTag, "Dispose");
82             if (_disposed)
83                 return;
84
85             if (disposing)
86                 DestroyHandle();
87
88             _disposed = true;
89         }
90
91         private void DestroyHandle()
92         {
93             Log.Info(Globals.LogTag, "DestroyBoundaryHandle");
94             int ret = Interop.LocationBoundary.DestroyBoundary(handle);
95             if (((LocationError)ret != LocationError.None))
96             {
97                 Log.Error(Globals.LogTag, "Error in DestroyBoundary handle" + (LocationError)ret);
98                 throw LocationErrorFactory.ThrowLocationException(ret);
99             }
100         }
101     }
102
103     /// <summary>
104     /// Class representing a rectangular location boundary.
105     /// Inherits the Abstract LocationBoundary class.
106     /// </summary>
107     /// <since_tizen>3</since_tizen>
108     public class RectangleBoundary : LocationBoundary
109     {
110         /// <summary>
111         /// Constructor of the Rectangle boundary class.
112         /// </summary>
113         /// <since_tizen>3</since_tizen>
114         /// <param name="topLeft"> The coordinate which constitute the top left handside of the rectangular boundary.</param>
115         /// <param name="bottomRight"> The coordinate which constitute the bottom right handside of the rectangular boundary.</param>
116         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
117         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
118         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
119         public RectangleBoundary(Coordinate topLeft, Coordinate bottomRight)
120         {
121             Log.Info(Globals.LogTag, "Calling RectangleBoundary constructor");
122             BoundaryType = BoundaryType.Rectangle;
123             IntPtr boundsHandle;
124             int ret = Interop.LocationBoundary.CreateRectangularBoundary(topLeft, bottomRight, out boundsHandle);
125             if ((LocationBoundError)ret != LocationBoundError.None)
126             {
127                 Log.Error(Globals.LogTag, "Error Creating Rectangular Boundary," + (LocationBoundError)ret);
128                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
129             }
130             handle = boundsHandle;
131         }
132
133         /// <summary>
134         /// Gets the Top Left handside coordinate of a rectangular boundary.
135         /// </summary>
136         /// <since_tizen>3</since_tizen>
137         public Coordinate TopLeft
138         {
139             get
140             {
141                 Log.Info(Globals.LogTag, "Calling to get CoordinateItem TopLeft");
142                 return GetRectangleCoordinate("TopLeft");
143             }
144         }
145
146         /// <summary>
147         /// Gets the Bottom Right handside coordinate of a rectangular boundary.
148         /// </summary>
149         /// <since_tizen>3</since_tizen>
150         public Coordinate BottomRight
151         {
152             get
153             {
154                 Log.Info(Globals.LogTag, "Calling to get CoordinateItem BottomRight");
155                 return GetRectangleCoordinate("BottomRight");
156             }
157         }
158
159         private Coordinate GetRectangleCoordinate(string tag)
160         {
161             Coordinate topLeft;
162             Coordinate bottomRight;
163
164             Interop.LocationBoundary.GetRectangleCoordinates(handle, out topLeft, out bottomRight);
165
166             if (tag.Equals("TopLeft"))
167             {
168                 return topLeft;
169             }
170             else
171             {
172                 return bottomRight;
173             }
174         }
175     }
176
177     /// <summary>
178     /// Class representing a circular location boundary.
179     /// Inherits the Abstract LocationBoundary class.
180     /// </summary>
181     /// <since_tizen>3</since_tizen>
182     public class CircleBoundary : LocationBoundary
183     {
184         /// <summary>
185         /// Constructor of the Circular boundary class.
186         /// </summary>
187         /// <since_tizen>3</since_tizen>
188         /// <param name="coordinate"> The coordinates which constitute the center of the circular boundary.</param>
189         /// <param name="radius"> The radius value of the circular boundary.</param>
190         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
191         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
192         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
193         public CircleBoundary(Coordinate coordinate, double radius)
194         {
195             Log.Info(Globals.LogTag, "Calling CircleBoundary constructor");
196             BoundaryType = BoundaryType.Circle;
197             IntPtr boundsHandle;
198             int ret = Interop.LocationBoundary.CreateCircleBoundary(coordinate, radius, out boundsHandle);
199             if ((LocationBoundError)ret != LocationBoundError.None)
200             {
201                 Log.Error(Globals.LogTag, "Error Creating Circular Boundary," + (LocationBoundError)ret);
202                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
203             }
204             handle = boundsHandle;
205         }
206
207         /// <summary>
208         /// Gets the coordinate of the center of a circular boundary.
209         /// </summary>
210         /// <since_tizen>3</since_tizen>
211         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
212         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
213         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
214         public Coordinate Center
215         {
216             get
217             {
218                 return GetCircleCenter();
219             }
220         }
221
222         /// <summary>
223         /// Gets the radius of a circular boundary.
224         /// </summary>
225         /// <since_tizen>3</since_tizen>
226         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
227         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
228         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
229         public double Radius
230         {
231             get
232             {
233                 return GetRadius();
234             }
235         }
236
237         private Coordinate GetCircleCenter()
238         {
239             Log.Info(Globals.LogTag, "Calling to get CoordinateItem Center");
240             Coordinate center;
241             double radius;
242             int ret = Interop.LocationBoundary.GetCircleCoordinates(handle, out center, out radius);
243             if ((LocationBoundError)ret != LocationBoundError.None)
244             {
245                 Log.Error(Globals.LogTag, "Error Get Circle Center," + (LocationBoundError)ret);
246                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
247             }
248             return center;
249         }
250
251         private double GetRadius()
252         {
253             Coordinate center;
254             double radius = 0;
255             int ret = Interop.LocationBoundary.GetCircleCoordinates(handle, out center, out radius);
256             if ((LocationBoundError)ret != LocationBoundError.None)
257             {
258                 Log.Error(Globals.LogTag, "Error Get Radius," + (LocationBoundError)ret);
259                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
260             }
261             return radius;
262         }
263     }
264
265     /// <summary>
266     /// Class representing a polygonal location boundary.
267     /// Inherits the Abstract LocationBoundary class.
268     /// </summary>
269     /// <since_tizen>3</since_tizen>
270     public class PolygonBoundary : LocationBoundary
271     {
272         /// <summary>
273         /// Constructor of the polygon boundary class.
274         /// </summary>
275         /// <since_tizen>3</since_tizen>
276         /// <param name="coordinates"> The coordinates which constitute the polgonal boundary.</param>
277         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
278         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
279         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
280         public PolygonBoundary(IList<Coordinate> coordinates)
281         {
282             Log.Info(Globals.LogTag, "Calling PolygonBoundary Constructor");
283             if (coordinates == null)
284             {
285                 Log.Error(Globals.LogTag, "coordingtes list is null");
286                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
287             }
288
289             BoundaryType = BoundaryType.Polygon;
290             IntPtr listPointer = Marshal.AllocHGlobal(Marshal.SizeOf(coordinates[0]) * coordinates.Count);
291             IntPtr boundsHandle;
292             for (int i = 0; i < coordinates.Count; i++)
293             {
294                 Marshal.StructureToPtr(coordinates[i], listPointer + i * Marshal.SizeOf(coordinates[0]), false);
295             }
296             int ret = Interop.LocationBoundary.CreatePolygonBoundary(listPointer, coordinates.Count, out boundsHandle);
297             if ((LocationBoundError)ret != LocationBoundError.None)
298             {
299                 Log.Error(Globals.LogTag, "Error Creating Polygon Boundary," + (LocationBoundError)ret);
300                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
301             }
302             handle = boundsHandle;
303         }
304
305         /// <summary>
306         /// Gets the list of coordinates which constitute a polygonal boundary
307         /// </summary>
308         /// <since_tizen>3</since_tizen>
309         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
310         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
311         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
312         public IList<Coordinate> Coordinates
313         {
314             get
315             {
316                 return GetCoordinates();
317             }
318         }
319
320         private IList<Coordinate> GetCoordinates()
321         {
322             Log.Info(Globals.LogTag, "Calling to get Polygon coordinates");
323             List<Coordinate> coordinateList = new List<Coordinate>();
324             Interop.LocationBoundary.PolygonCoordinatesCallback callback = (Coordinate coordinate, IntPtr userData) =>
325             {
326                 Coordinate item;
327                 item.Latitude = coordinate.Latitude;
328                 item.Longitude = coordinate.Longitude;
329                 coordinateList.Add(item);
330                 return true;
331             };
332
333             int ret = Interop.LocationBoundary.GetForEachPolygonCoordinates(handle, callback, IntPtr.Zero);
334             if ((LocationBoundError)ret != LocationBoundError.None)
335             {
336                 Log.Error(Globals.LogTag, "Error Get foreach Boundary," + (LocationBoundError)ret);
337                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
338             }
339             return coordinateList;
340         }
341     }
342
343     /// <summary>
344     /// The structure which represents the  co-ordinates of a geographical location.
345     /// </summary>
346     /// <since_tizen>3</since_tizen>
347     [StructLayout(LayoutKind.Sequential)]
348     public struct Coordinate
349     {
350         /// <summary>
351         /// Latitude component of the co-ordinate.
352         /// Should have a value between [-90.0 ~ 90.0] (degrees).
353         /// </summary>
354         /// <since_tizen>3</since_tizen>
355         public double Latitude;
356
357         /// <summary>
358         /// Longitude component of the co-ordinate.
359         /// Should have a value between [-180.0 ~ 180.0] (degrees).
360         /// </summary>
361         /// <since_tizen>3</since_tizen>
362         public double Longitude;
363     }
364 }