Fix that points of the polygon are not delivered to C API when created
[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     public abstract class LocationBoundary : IDisposable
27     {
28         internal IntPtr handle;
29         private bool _disposed = false;
30
31         /// <summary>
32         /// Gets the location boundary type.
33         /// </summary>
34         public BoundaryType BoundaryType{ get; internal set; }
35
36         /// <summary>
37         /// The destructor of LocationBoundary class.
38         /// </summary>
39         ~LocationBoundary()
40         {
41             Log.Info(Globals.LogTag, "The destructor of LocationBoundary class");
42             Dispose(false);
43         }
44
45         internal IntPtr GetHandle()
46         {
47             return handle;
48         }
49
50         /// <summary>
51         /// Checks if the boundary contains the specified geographical coordinates.
52         /// </summary>
53         /// <param name="coordinate"> The coordinate which needs to be checked.</param>
54         /// <returns>Returns a boolean value indicating whether or not the specified coordinate lies in the geographical area.</returns>
55         public bool BoundaryContainsCoordinates(Coordinate coordinate)
56         {
57             Log.Info(Globals.LogTag, "Checking if coordinates are contained within boundary");
58             return Interop.LocationBoundary.IsValidCoordinates(handle, coordinate);
59         }
60
61         /// <summary>
62         /// The overidden Dispose method of the IDisposable class.
63         /// </summary>
64         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
65         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
66         public void Dispose()
67         {
68             Log.Info(Globals.LogTag, "Dispose");
69             Dispose(true);
70             GC.SuppressFinalize(this);
71         }
72
73         protected virtual void Dispose(bool disposing)
74         {
75             Log.Info(Globals.LogTag, "Dispose");
76             if (_disposed)
77                 return;
78
79             if (disposing)
80                 DestroyHandle();
81
82             _disposed = true;
83         }
84
85         private void DestroyHandle()
86         {
87             Log.Info(Globals.LogTag, "DestroyBoundaryHandle");
88             int ret = Interop.LocationBoundary.DestroyBoundary(handle);
89             if (((LocationError)ret != LocationError.None))
90             {
91                 Log.Error(Globals.LogTag, "Error in DestroyBoundary handle" + (LocationError)ret);
92                 throw LocationErrorFactory.ThrowLocationException(ret);
93             }
94         }
95     }
96
97     /// <summary>
98     /// Class representing a rectangular location boundary.
99     /// Inherits the Abstract LocationBoundary class.
100     /// </summary>
101     public class RectangleBoundary : LocationBoundary
102     {
103         /// <summary>
104         /// Constructor of the Rectangle boundary class.
105         /// </summary>
106         /// <param name="topLeft"> The coordinate which constitute the top left handside of the rectangular boundary.</param>
107         /// <param name="bottomRight"> The coordinate which constitute the bottom right handside of the rectangular boundary.</param>
108         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
109         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
110         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
111         public RectangleBoundary(Coordinate topLeft, Coordinate bottomRight)
112         {
113             Log.Info(Globals.LogTag, "Calling RectangleBoundary constructor");
114             BoundaryType = BoundaryType.Rectangle;
115             IntPtr boundsHandle;
116             int ret = Interop.LocationBoundary.CreateRectangularBoundary(topLeft, bottomRight, out boundsHandle);
117             if ((LocationBoundError)ret != LocationBoundError.None)
118             {
119                 Log.Error(Globals.LogTag, "Error Creating Rectangular Boundary," + (LocationBoundError)ret);
120                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
121             }
122             handle = boundsHandle;
123         }
124
125         /// <summary>
126         /// Gets the Top Left handside coordinate of a rectangular boundary.
127         /// </summary>
128         public Coordinate TopLeft
129         {
130             get
131             {
132                 Log.Info(Globals.LogTag, "Calling to get CoordinateItem TopLeft");
133                 return GetRectangleCoordinate("TopLeft");
134             }
135         }
136
137         /// <summary>
138         /// Gets the Bottom Right handside coordinate of a rectangular boundary.
139         /// </summary>
140         public Coordinate BottomRight
141         {
142             get
143             {
144                 Log.Info(Globals.LogTag, "Calling to get CoordinateItem BottomRight");
145                 return GetRectangleCoordinate("BottomRight");
146             }
147         }
148
149         private Coordinate GetRectangleCoordinate(string tag)
150         {
151             Coordinate topLeft;
152             Coordinate bottomRight;
153
154             Interop.LocationBoundary.GetRectangleCoordinates(handle, out topLeft, out bottomRight);
155
156             if (tag.Equals("TopLeft"))
157             {
158                 return topLeft;
159             }
160             else
161             {
162                 return bottomRight;
163             }
164         }
165     }
166
167     /// <summary>
168     /// Class representing a circular location boundary.
169     /// Inherits the Abstract LocationBoundary class.
170     /// </summary>
171     public class CircleBoundary : LocationBoundary
172     {
173         /// <summary>
174         /// Constructor of the Circular boundary class.
175         /// </summary>
176         /// <param name="coordinate"> The coordinates which constitute the center of the circular boundary.</param>
177         /// <param name="radius"> The radius value of the circular boundary.</param>
178         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
179         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
180         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
181         public CircleBoundary(Coordinate coordinate, double radius)
182         {
183             Log.Info(Globals.LogTag, "Calling CircleBoundary constructor");
184             BoundaryType = BoundaryType.Circle;
185             IntPtr boundsHandle;
186             int ret = Interop.LocationBoundary.CreateCircleBoundary(coordinate, radius, out boundsHandle);
187             if ((LocationBoundError)ret != LocationBoundError.None)
188             {
189                 Log.Error(Globals.LogTag, "Error Creating Circular Boundary," + (LocationBoundError)ret);
190                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
191             }
192             handle = boundsHandle;
193         }
194
195         /// <summary>
196         /// Gets the coordinate of the center of a circular boundary.
197         /// </summary>
198         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
199         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
200         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
201         public Coordinate Center
202         {
203             get
204             {
205                 return GetCircleCenter();
206             }
207         }
208
209         /// <summary>
210         /// Gets the radius of a circular boundary.
211         /// </summary>
212         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
213         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
214         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
215         public double Radius
216         {
217             get
218             {
219                 return GetRadius();
220             }
221         }
222
223         private Coordinate GetCircleCenter()
224         {
225             Log.Info(Globals.LogTag, "Calling to get CoordinateItem Center");
226             Coordinate center;
227             double radius;
228             int ret = Interop.LocationBoundary.GetCircleCoordinates(handle, out center, out radius);
229             if ((LocationBoundError)ret != LocationBoundError.None)
230             {
231                 Log.Error(Globals.LogTag, "Error Get Circle Center," + (LocationBoundError)ret);
232                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
233             }
234             return center;
235         }
236
237         private double GetRadius()
238         {
239             Coordinate center;
240             double radius = 0;
241             int ret = Interop.LocationBoundary.GetCircleCoordinates(handle, out center, out radius);
242             if ((LocationBoundError)ret != LocationBoundError.None)
243             {
244                 Log.Error(Globals.LogTag, "Error Get Radius," + (LocationBoundError)ret);
245                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
246             }
247             return radius;
248         }
249     }
250
251     /// <summary>
252     /// Class representing a polygonal location boundary.
253     /// Inherits the Abstract LocationBoundary class.
254     /// </summary>
255     public class PolygonBoundary : LocationBoundary
256     {
257         /// <summary>
258         /// Constructor of the polygon boundary class.
259         /// </summary>
260         /// <param name="coordinates"> The coordinates which constitute the polgonal boundary.</param>
261         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
262         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
263         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
264         public PolygonBoundary(IList<Coordinate> coordinates)
265         {
266             Log.Info(Globals.LogTag, "Calling PolygonBoundary Constructor");
267             BoundaryType = BoundaryType.Polygon;
268             IntPtr listPointer = Marshal.AllocHGlobal(Marshal.SizeOf(coordinates[0]) * coordinates.Count);
269             IntPtr boundsHandle;
270             for (int i = 0; i < coordinates.Count; i++)
271             {
272                 Marshal.StructureToPtr(coordinates[i], listPointer + i * Marshal.SizeOf(coordinates[0]), false);
273             }
274             int ret = Interop.LocationBoundary.CreatePolygonBoundary(listPointer, coordinates.Count, out boundsHandle);
275             if ((LocationBoundError)ret != LocationBoundError.None)
276             {
277                 Log.Error(Globals.LogTag, "Error Creating Polygon Boundary," + (LocationBoundError)ret);
278                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
279             }
280             handle = boundsHandle;
281         }
282
283         /// <summary>
284         /// Gets the list of coordinates which constitute a polygonal boundary
285         /// </summary>
286         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
287         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
288         /// <exception cref="NotSupportedException">Thrown when the location is not supported</exception>
289         public IList<Coordinate> Coordinates
290         {
291             get
292             {
293                 return GetCoordinates();
294             }
295         }
296
297         private IList<Coordinate> GetCoordinates()
298         {
299             Log.Info(Globals.LogTag, "Calling to get Polygon coordinates");
300             List<Coordinate> coordinateList = new List<Coordinate>();
301             Interop.LocationBoundary.PolygonCoordinatesCallback callback = (Coordinate coordinate, IntPtr userData) =>
302             {
303                 Coordinate item;
304                 item.Latitude = coordinate.Latitude;
305                 item.Longitude = coordinate.Longitude;
306                 coordinateList.Add(item);
307                 return true;
308             };
309
310             int ret = Interop.LocationBoundary.GetForEachPolygonCoordinates(handle, callback, IntPtr.Zero);
311             if ((LocationBoundError)ret != LocationBoundError.None)
312             {
313                 Log.Error(Globals.LogTag, "Error Get foreach Boundary," + (LocationBoundError)ret);
314                 throw LocationErrorFactory.ThrowLocationBoundaryException(ret);
315             }
316             return coordinateList;
317         }
318     }
319
320     /// <summary>
321     /// The structure which represents the  co-ordinates of a geographical location.
322     /// </summary>
323     [StructLayout(LayoutKind.Sequential)]
324     public struct Coordinate
325     {
326         /// <summary>
327         /// Latitude component of the co-ordinate.
328         /// Should have a value between [-90.0 ~ 90.0] (degrees).
329         /// </summary>
330         public double Latitude;
331
332         /// <summary>
333         /// Longitude component of the co-ordinate.
334         /// Should have a value between [-180.0 ~ 180.0] (degrees).
335         /// </summary>
336         public double Longitude;
337     }
338 }