1 #pragma once
2 /**
3  * \file NETGeographicLib/LambertConformalConic.h
4  * \brief Header for NETGeographicLib::LambertConformalConic class
5  *
6  * NETGeographicLib is copyright (c) Scott Heiman (2013)
7  * GeographicLib is Copyright (c) Charles Karney (2010-2012)
8  * <charles@karney.com> and licensed under the MIT/X11 License.
9  * For more information, see
10  * https://geographiclib.sourceforge.io/
11  **********************************************************************/
12 
13 namespace NETGeographicLib
14 {
15   /**
16    * \brief .NET wrapper for GeographicLib::LambertConformalConic.
17    *
18    * This class allows .NET applications to access GeographicLib::LambertConformalConic.
19    *
20    * Implementation taken from the report,
21    * - J. P. Snyder,
22    *   <a href="http://pubs.er.usgs.gov/usgspubs/pp/pp1395"> Map Projections: A
23    *   Working Manual</a>, USGS Professional Paper 1395 (1987),
24    *   pp. 107--109.
25    *
26    * This is a implementation of the equations in Snyder except that divided
27    * differences have been used to transform the expressions into ones which
28    * may be evaluated accurately and that Newton's method is used to invert the
29    * projection.  In this implementation, the projection correctly becomes the
30    * Mercator projection or the polar stereographic projection when the
31    * standard latitude is the equator or a pole.  The accuracy of the
32    * projections is about 10 nm (10 nanometers).
33    *
34    * The ellipsoid parameters, the standard parallels, and the scale on the
35    * standard parallels are set in the constructor.  Internally, the case with
36    * two standard parallels is converted into a single standard parallel, the
37    * latitude of tangency (also the latitude of minimum scale), with a scale
38    * specified on this parallel.  This latitude is also used as the latitude of
39    * origin which is returned by LambertConformalConic::OriginLatitude.  The
40    * scale on the latitude of origin is given by
41    * LambertConformalConic::CentralScale.  The case with two distinct standard
42    * parallels where one is a pole is singular and is disallowed.  The central
43    * meridian (which is a trivial shift of the longitude) is specified as the
44    * \e lon0 argument of the LambertConformalConic::Forward and
45    * LambertConformalConic::Reverse functions.  There is no provision in this
46    * class for specifying a false easting or false northing or a different
47    * latitude of origin.  However these are can be simply included by the
48    * calling function.  For example the Pennsylvania South state coordinate
49    * system (<a href="http://www.spatialreference.org/ref/epsg/3364/">
50    * EPSG:3364</a>) is obtained by:
51    * C# Example:
52    * \include example-LambertConformalConic.cs
53    * Managed C++ Example:
54    * \include example-LambertConformalConic.cpp
55    * Visual Basic Example:
56    * \include example-LambertConformalConic.vb
57    *
58    * <B>INTERFACE DIFFERENCES:</B><BR>
59    * A default constructor has been provided that assumes a Mercator
60    * projection.
61    *
62    * The EquatorialRadius, Flattening, OriginLatitude, and CentralScale
63    * functions are implemented as properties.
64    **********************************************************************/
65     public ref class LambertConformalConic
66     {
67         private:
68         // Pointer to the unmanaged GeographicLib::LambertConformalConic.
69         GeographicLib::LambertConformalConic* m_pLambertConformalConic;
70 
71         // the finalizer frres the unmanaged memory when the object is destroyed.
72         !LambertConformalConic(void);
73     public:
74 
75         /**
76          * Constructor with a single standard parallel.
77          *
78          * @param[in] a equatorial radius of ellipsoid (meters).
79          * @param[in] f flattening of ellipsoid.  Setting \e f = 0 gives a sphere.
80          *   Negative \e f gives a prolate ellipsoid.
81          * @param[in] stdlat standard parallel (degrees), the circle of tangency.
82          * @param[in] k0 scale on the standard parallel.
83          * @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k0 is
84          *   not positive.
85          * @exception GeographicErr if \e stdlat is not in [&minus;90&deg;,
86          *   90&deg;].
87          **********************************************************************/
88         LambertConformalConic(double a, double f, double stdlat, double k0);
89 
90         /**
91          * Constructor with two standard parallels.
92          *
93          * @param[in] a equatorial radius of ellipsoid (meters).
94          * @param[in] f flattening of ellipsoid.  Setting \e f = 0 gives a sphere.
95          *   Negative \e f gives a prolate ellipsoid.
96          * @param[in] stdlat1 first standard parallel (degrees).
97          * @param[in] stdlat2 second standard parallel (degrees).
98          * @param[in] k1 scale on the standard parallels.
99          * @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k1 is
100          *   not positive.
101          * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
102          *   [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e
103          *   stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
104          **********************************************************************/
105         LambertConformalConic(double a, double f, double stdlat1, double stdlat2, double k1);
106 
107         /**
108          * Constructor with two standard parallels specified by sines and cosines.
109          *
110          * @param[in] a equatorial radius of ellipsoid (meters).
111          * @param[in] f flattening of ellipsoid.  Setting \e f = 0 gives a sphere.
112          *   Negative \e f gives a prolate ellipsoid.
113          * @param[in] sinlat1 sine of first standard parallel.
114          * @param[in] coslat1 cosine of first standard parallel.
115          * @param[in] sinlat2 sine of second standard parallel.
116          * @param[in] coslat2 cosine of second standard parallel.
117          * @param[in] k1 scale on the standard parallels.
118          * @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k1 is
119          *   not positive.
120          * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
121          *   [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e
122          *   stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
123          *
124          * This allows parallels close to the poles to be specified accurately.
125          * This routine computes the latitude of origin and the scale at this
126          * latitude.  In the case where \e lat1 and \e lat2 are different, the
127          * errors in this routines are as follows: if \e dlat = abs(\e lat2 &minus;
128          * \e lat1) &le; 160&deg; and max(abs(\e lat1), abs(\e lat2)) &le; 90
129          * &minus; min(0.0002, 2.2 &times; 10<sup>&minus;6</sup>(180 &minus; \e
130          * dlat), 6 &times 10<sup>&minus;8</sup> <i>dlat</i><sup>2</sup>) (in
131          * degrees), then the error in the latitude of origin is less than 4.5
132          * &times; 10<sup>&minus;14</sup>d and the relative error in the scale is
133          * less than 7 &times; 10<sup>&minus;15</sup>.
134          **********************************************************************/
135         LambertConformalConic(double a, double f,
136                               double sinlat1, double coslat1,
137                               double sinlat2, double coslat2,
138                               double k1);
139 
140         /**
141          * The default constructor assumes a Mercator projection.
142          **********************************************************************/
143         LambertConformalConic();
144 
145         /**
146          * The destructor calls the finalizer.
147          **********************************************************************/
~LambertConformalConic()148         ~LambertConformalConic()
149         { this->!LambertConformalConic(); }
150 
151         /**
152          * Set the scale for the projection.
153          *
154          * @param[in] lat (degrees).
155          * @param[in] k scale at latitude \e lat (default 1).
156          * @exception GeographicErr \e k is not positive.
157          * @exception GeographicErr if \e lat is not in [&minus;90&deg;,
158          *   90&deg;].
159          **********************************************************************/
160         void SetScale(double lat, double k);
161 
162         /**
163          * Forward projection, from geographic to Lambert conformal conic.
164          *
165          * @param[in] lon0 central meridian longitude (degrees).
166          * @param[in] lat latitude of point (degrees).
167          * @param[in] lon longitude of point (degrees).
168          * @param[out] x easting of point (meters).
169          * @param[out] y northing of point (meters).
170          * @param[out] gamma meridian convergence at point (degrees).
171          * @param[out] k scale of projection at point.
172          *
173          * The latitude origin is given by
174          * LambertConformalConic::LatitudeOrigin().  No false easting or
175          * northing is added and \e lat should be in the range [&minus;90&deg;,
176          * 90&deg;].  The error in the projection is less than about 10 nm (10
177          * nanometers), true distance, and the errors in the meridian
178          * convergence and scale are consistent with this.  The values of \e x
179          * and \e y returned for points which project to infinity (i.e., one or
180          * both of the poles) will be large but finite.
181          **********************************************************************/
182         void Forward(double lon0, double lat, double lon,
183                      [System::Runtime::InteropServices::Out] double% x,
184                      [System::Runtime::InteropServices::Out] double% y,
185                      [System::Runtime::InteropServices::Out] double% gamma,
186                      [System::Runtime::InteropServices::Out] double% k);
187 
188         /**
189          * Reverse projection, from Lambert conformal conic to geographic.
190          *
191          * @param[in] lon0 central meridian longitude (degrees).
192          * @param[in] x easting of point (meters).
193          * @param[in] y northing of point (meters).
194          * @param[out] lat latitude of point (degrees).
195          * @param[out] lon longitude of point (degrees).
196          * @param[out] gamma meridian convergence at point (degrees).
197          * @param[out] k scale of projection at point.
198          *
199          * The latitude origin is given by
200          * LambertConformalConic::LatitudeOrigin().  No false easting or
201          * northing is added.  The value of \e lon returned is in the range
202          * [&minus;180&deg;, 180&deg;).  The error in the projection is less
203          * than about 10 nm (10 nanometers), true distance, and the errors in
204          * the meridian convergence and scale are consistent with this.
205          **********************************************************************/
206         void Reverse(double lon0, double x, double y,
207                      [System::Runtime::InteropServices::Out] double% lat,
208                      [System::Runtime::InteropServices::Out] double% lon,
209                      [System::Runtime::InteropServices::Out] double% gamma,
210                      [System::Runtime::InteropServices::Out] double% k);
211 
212         /**
213          * LambertConformalConic::Forward without returning the convergence and
214          * scale.
215          **********************************************************************/
216         void Forward(double lon0, double lat, double lon,
217                      [System::Runtime::InteropServices::Out] double% x,
218                      [System::Runtime::InteropServices::Out] double% y);
219 
220         /**
221          * LambertConformalConic::Reverse without returning the convergence and
222          * scale.
223          **********************************************************************/
224         void Reverse(double lon0, double x, double y,
225                      [System::Runtime::InteropServices::Out] double% lat,
226                      [System::Runtime::InteropServices::Out] double% lon);
227 
228         /** \name Inspector functions
229          **********************************************************************/
230         ///@{
231         /**
232          * @return \e a the equatorial radius of the ellipsoid (meters).  This is
233          *   the value used in the constructor.
234          **********************************************************************/
235         property double EquatorialRadius { double get(); }
236 
237         /**
238          * @return \e f the flattening of the ellipsoid.  This is the
239          *   value used in the constructor.
240          **********************************************************************/
241         property double Flattening { double get(); }
242 
243         /**
244          * @return latitude of the origin for the projection (degrees).
245          *
246          * This is the latitude of minimum scale and equals the \e stdlat in the
247          * 1-parallel constructor and lies between \e stdlat1 and \e stdlat2 in the
248          * 2-parallel constructors.
249          **********************************************************************/
250         property double OriginLatitude { double get(); }
251 
252         /**
253          * @return central scale for the projection.  This is the scale on the
254          *   latitude of origin.
255          **********************************************************************/
256         property double CentralScale { double get(); }
257         ///@}
258     };
259 } //namespace NETGeographicLib
260