Release 4.0.0-preview1-00279
[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     /// The LocationBoundary class is an abstract class that provides functions related to the 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 the 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         /// <summary>
80         /// Dispose.
81         /// </summary>
82         protected virtual void Dispose(bool disposing)
83         {
84             Log.Info(Globals.LogTag, "Dispose");
85             if (_disposed)
86                 return;
87
88             if (disposing)
89                 DestroyHandle();
90
91             _disposed = true;
92         }
93
94         private void DestroyHandle()
95         {
96             Log.Info(Globals.LogTag, "DestroyBoundaryHandle");
97             int ret = Interop.LocationBoundary.DestroyBoundary(handle);
98             if (((LocationError)ret != LocationError.None))
99             {
100                 Log.Error(Globals.LogTag, "Error in DestroyBoundary handle" + (LocationError)ret);
101                 throw LocationErrorFactory.ThrowLocationException(ret);
102             }
103         }
104     }
105
106     /// <summary>
107     /// This class represents a rectangular location boundary.
108     /// Inherits the Abstract LocationBoundary class.
109     /// </summary>
110     /// <since_tizen> 3 </since_tizen>
111     public class RectangleBoundary : LocationBoundary
112     {
113         /// <summary>
114         /// The constructor of the Rectangle boundary class.
115         /// </summary>
116         /// <since_tizen> 3 </since_tizen>
117         /// <param name="topLeft"> The coordinate which constitutes the top-left handside of the rectangular boundary.</param>
118         /// <param name="bottomRight"> The coordinate which constitutes the bottom-right handside of the rectangular boundary.</param>
119         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
120         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
121         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
122         public RectangleBoundary(Coordinate topLeft, Coordinate bottomRight)
123         {
124             Log.Info(Globals.LogTag, "Calling RectangleBoundary constructor");
125             BoundaryType = BoundaryType.Rectangle;
126             IntPtr boundsHandle;
127             int ret = Interop.LocationBoundary.CreateRectangularBoundary(topLeft, bottomRight, out boundsHandle);
128             if ((LocationBoundError)ret != LocationBoundError.None)
129             {
130                 Log.Error(Globals.LogTag, "Error Creating Rectangular Boundary," + (LocationBoundError)ret);
131                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
132             }
133             handle = boundsHandle;
134         }
135
136         /// <summary>
137         /// Gets the top-left handside coordinate of a rectangular boundary.
138         /// </summary>
139         /// <since_tizen> 3 </since_tizen>
140         public Coordinate TopLeft
141         {
142             get
143             {
144                 Log.Info(Globals.LogTag, "Calling to get CoordinateItem TopLeft");
145                 return GetRectangleCoordinate("TopLeft");
146             }
147         }
148
149         /// <summary>
150         /// Gets the bottom-right handside coordinate of a rectangular boundary.
151         /// </summary>
152         /// <since_tizen> 3 </since_tizen>
153         public Coordinate BottomRight
154         {
155             get
156             {
157                 Log.Info(Globals.LogTag, "Calling to get CoordinateItem BottomRight");
158                 return GetRectangleCoordinate("BottomRight");
159             }
160         }
161
162         private Coordinate GetRectangleCoordinate(string tag)
163         {
164             Coordinate topLeft;
165             Coordinate bottomRight;
166
167             Interop.LocationBoundary.GetRectangleCoordinates(handle, out topLeft, out bottomRight);
168
169             if (tag.Equals("TopLeft"))
170             {
171                 return topLeft;
172             }
173             else
174             {
175                 return bottomRight;
176             }
177         }
178     }
179
180     /// <summary>
181     /// This class represents a circular location boundary.
182     /// Inherits the Abstract LocationBoundary class.
183     /// </summary>
184     /// <since_tizen> 3 </since_tizen>
185     public class CircleBoundary : LocationBoundary
186     {
187         /// <summary>
188         /// The constructor of the Circular boundary class.
189         /// </summary>
190         /// <since_tizen> 3 </since_tizen>
191         /// <param name="coordinate"> The coordinates which constitute the center of the circular boundary.</param>
192         /// <param name="radius"> The radius value of the circular boundary.</param>
193         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
194         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
195         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
196         public CircleBoundary(Coordinate coordinate, double radius)
197         {
198             Log.Info(Globals.LogTag, "Calling CircleBoundary constructor");
199             BoundaryType = BoundaryType.Circle;
200             IntPtr boundsHandle;
201             int ret = Interop.LocationBoundary.CreateCircleBoundary(coordinate, radius, out boundsHandle);
202             if ((LocationBoundError)ret != LocationBoundError.None)
203             {
204                 Log.Error(Globals.LogTag, "Error Creating Circular Boundary," + (LocationBoundError)ret);
205                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
206             }
207             handle = boundsHandle;
208         }
209
210         /// <summary>
211         /// Gets the coordinate of the center of a circular boundary.
212         /// </summary>
213         /// <since_tizen> 3 </since_tizen>
214         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
215         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
216         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
217         public Coordinate Center
218         {
219             get
220             {
221                 return GetCircleCenter();
222             }
223         }
224
225         /// <summary>
226         /// Gets the radius of a circular boundary.
227         /// </summary>
228         /// <since_tizen> 3 </since_tizen>
229         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
230         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
231         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
232         public double Radius
233         {
234             get
235             {
236                 return GetRadius();
237             }
238         }
239
240         private Coordinate GetCircleCenter()
241         {
242             Log.Info(Globals.LogTag, "Calling to get CoordinateItem Center");
243             Coordinate center;
244             double radius;
245             int ret = Interop.LocationBoundary.GetCircleCoordinates(handle, out center, out radius);
246             if ((LocationBoundError)ret != LocationBoundError.None)
247             {
248                 Log.Error(Globals.LogTag, "Error Get Circle Center," + (LocationBoundError)ret);
249                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
250             }
251             return center;
252         }
253
254         private double GetRadius()
255         {
256             Coordinate center;
257             double radius = 0;
258             int ret = Interop.LocationBoundary.GetCircleCoordinates(handle, out center, out radius);
259             if ((LocationBoundError)ret != LocationBoundError.None)
260             {
261                 Log.Error(Globals.LogTag, "Error Get Radius," + (LocationBoundError)ret);
262                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
263             }
264             return radius;
265         }
266     }
267
268     /// <summary>
269     /// This class represents a polygonal location boundary.
270     /// Inherits the Abstract LocationBoundary class.
271     /// </summary>
272     /// <since_tizen> 3 </since_tizen>
273     public class PolygonBoundary : LocationBoundary
274     {
275         /// <summary>
276         /// The constructor of the Polygon Boundary class.
277         /// </summary>
278         /// <since_tizen> 3 </since_tizen>
279         /// <param name="coordinates"> The coordinates which constitute the polgonal boundary.</param>
280         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
281         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
282         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
283         public PolygonBoundary(IList<Coordinate> coordinates)
284         {
285             Log.Info(Globals.LogTag, "Calling PolygonBoundary Constructor");
286             if (coordinates == null)
287             {
288                 Log.Error(Globals.LogTag, "coordingtes list is null");
289                 throw LocationErrorFactory.ThrowLocationException((int)LocationError.InvalidParameter);
290             }
291
292             BoundaryType = BoundaryType.Polygon;
293             IntPtr listPointer = Marshal.AllocHGlobal(Marshal.SizeOf(coordinates[0]) * coordinates.Count);
294             IntPtr boundsHandle;
295             for (int i = 0; i < coordinates.Count; i++)
296             {
297                 Marshal.StructureToPtr(coordinates[i], listPointer + i * Marshal.SizeOf(coordinates[0]), false);
298             }
299             int ret = Interop.LocationBoundary.CreatePolygonBoundary(listPointer, coordinates.Count, out boundsHandle);
300             if ((LocationBoundError)ret != LocationBoundError.None)
301             {
302                 Log.Error(Globals.LogTag, "Error Creating Polygon Boundary," + (LocationBoundError)ret);
303                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
304             }
305             handle = boundsHandle;
306         }
307
308         /// <summary>
309         /// Gets the list of coordinates which constitute a polygonal boundary.
310         /// </summary>
311         /// <since_tizen> 3 </since_tizen>
312         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state.</exception>
313         /// <exception cref="ArgumentException">Thrown when an invalid argument is used.</exception>
314         /// <exception cref="NotSupportedException">Thrown when the location is not supported.</exception>
315         public IList<Coordinate> Coordinates
316         {
317             get
318             {
319                 return GetCoordinates();
320             }
321         }
322
323         private IList<Coordinate> GetCoordinates()
324         {
325             Log.Info(Globals.LogTag, "Calling to get Polygon coordinates");
326             List<Coordinate> coordinateList = new List<Coordinate>();
327             Interop.LocationBoundary.PolygonCoordinatesCallback callback = (Coordinate coordinate, IntPtr userData) =>
328             {
329                 Coordinate item;
330                 item.Latitude = coordinate.Latitude;
331                 item.Longitude = coordinate.Longitude;
332                 coordinateList.Add(item);
333                 return true;
334             };
335
336             int ret = Interop.LocationBoundary.GetForEachPolygonCoordinates(handle, callback, IntPtr.Zero);
337             if ((LocationBoundError)ret != LocationBoundError.None)
338             {
339                 Log.Error(Globals.LogTag, "Error Get foreach Boundary," + (LocationBoundError)ret);
340                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
341             }
342             return coordinateList;
343         }
344     }
345
346     /// <summary>
347     /// This structure represents the coordinates of a geographical location.
348     /// </summary>
349     /// <since_tizen> 3 </since_tizen>
350     [StructLayout(LayoutKind.Sequential)]
351     public struct Coordinate
352     {
353         /// <summary>
354         /// Latitude component of the coordinate.
355         /// Should have a value between [-90.0 ~ 90.0] (degrees).
356         /// </summary>
357         /// <since_tizen> 3 </since_tizen>
358         public double Latitude;
359
360         /// <summary>
361         /// Longitude component of the coordinate.
362         /// Should have a value between [-180.0 ~ 180.0] (degrees).
363         /// </summary>
364         /// <since_tizen> 3 </since_tizen>
365         public double Longitude;
366     }
367 }