143 کامیت‌ها

مولف SHA1 پیام تاریخ
Sven Czarnian
e19e50b027 update to the current interface version 2021-12-29 09:37:23 +01:00
Sven Czarnian
c5d5e332c8 fix compiler issues 2021-12-26 10:59:22 +01:00
Sven Czarnian
7411955ede fix a typo 2021-12-26 10:44:05 +01:00
Sven Czarnian
1873c68ab0 use the server's IAFs to check if we have a new inbound and over which IAF 2021-12-26 10:43:15 +01:00
Sven Czarnian
0a586f88c3 remove double lock 2021-12-26 09:29:50 +01:00
Sven Czarnian
06271fde5b code formatting 2021-12-26 09:29:37 +01:00
Sven Czarnian
4e635514f1 initialize the complete inbound after the creation 2021-12-23 17:50:35 +01:00
Sven Czarnian
d24c1ee1ce add a flag to indicate if the filter needs to be reset 2021-12-23 17:50:21 +01:00
Sven Czarnian
f54711f490 add a missing initialization 2021-12-23 17:50:08 +01:00
Sven Czarnian
031c9faa97 add a low pass filter to keep the TTL more stable 2021-12-23 17:49:56 +01:00
Sven Czarnian
d7c41d1941 give the controller the information he needs and that he can configure the tags 2021-12-23 09:58:31 +01:00
Sven Czarnian
ec9e9e285b predict the planned waypoint if a heading is given 2021-12-20 11:08:07 +01:00
Sven Czarnian
2795011021 check if the PTA exists 2021-12-19 13:06:19 +01:00
Sven Czarnian
c3a75bb900 add a menu to force set runways 2021-12-19 12:23:23 +01:00
Sven Czarnian
c14698bc39 fix the WTC message 2021-12-17 13:32:30 +01:00
Sven Czarnian
4f84e9a051 remove the debug message 2021-12-17 13:05:38 +01:00
Sven Czarnian
861232d09d update the IAF distance estimation to provide better results 2021-12-16 16:02:35 +01:00
Sven Czarnian
791c9c2605 do not filter based on distances 2021-12-16 16:02:08 +01:00
Sven Czarnian
4da604af99 add a function to project the IAF on the current path to have a virtual IAF 2021-12-16 16:01:49 +01:00
Sven Czarnian
ffb944fd6d add the remaining distance 2021-12-16 16:01:05 +01:00
Sven Czarnian
7238d6b92e use the correct return values 2021-12-16 16:00:44 +01:00
Sven Czarnian
1570b9c7f1 make the matcher public 2021-12-16 16:00:31 +01:00
Sven Czarnian
85600fcd57 add Eigen as a dependency 2021-12-16 16:00:12 +01:00
Sven Czarnian
27b422d806 add Eigen as a dependency 2021-12-16 15:59:56 +01:00
Sven Czarnian
a08ac9b244 fix compiler issues 2021-12-15 16:55:07 +01:00
Sven Czarnian
dbb3d6d557 fix the issues with the predicted path to planned path matching 2021-12-15 16:53:55 +01:00
Sven Czarnian
88c40575ff do not delete the airports 2021-12-15 13:25:04 +01:00
Sven Czarnian
de25092e3b fix sweatbox issues 2021-12-15 13:24:55 +01:00
Sven Czarnian
c94847b607 allow more tag entries to customize the views 2021-12-15 13:24:42 +01:00
Sven Czarnian
e108d3de57 fix some issues with the path prediction and add some addional information 2021-12-15 13:23:33 +01:00
Sven Czarnian
f053ead918 send the new sequence after every update 2021-12-09 12:29:38 +01:00
Sven Czarnian
ef91a3badd cleanup internal structures as soon as the controller is disconnected 2021-12-09 12:29:24 +01:00
Sven Czarnian
b88d2aabda set the airport 2021-12-09 10:27:40 +01:00
Sven Czarnian
076109be41 fix a return value bug 2021-12-09 10:27:30 +01:00
Sven Czarnian
0fc113cd2d use the standard color and a * to indicate if a plan is fixed or not 2021-12-02 19:07:03 +01:00
Sven Czarnian
c6159144bb indicate if the reload was successful 2021-12-02 19:06:23 +01:00
Sven Czarnian
6152c40dca fix compiler issues 2021-12-02 19:06:13 +01:00
Sven Czarnian
95493674e8 add the ignore for used parameters 2021-12-02 19:06:03 +01:00
Sven Czarnian
ae0442b560 add a menu 2021-12-02 19:05:34 +01:00
Sven Czarnian
41a9fd20d5 fix code analysis findings 2021-11-30 08:50:28 +01:00
Sven Czarnian
e4ea8f46c8 ignore the sweatbox and playbacks to use only real VATSIM data 2021-11-29 21:00:37 +01:00
Sven Czarnian
055cf900fb fix some changes and add a low pass filter to avoid fast ETA changes 2021-11-29 19:21:29 +01:00
Sven Czarnian
d89e8fef4c remove a debug message 2021-11-29 19:20:41 +01:00
Sven Czarnian
684ca40c1c fix a typo in the scaling 2021-11-25 22:51:25 +01:00
Sven Czarnian
eb521fca8b update the inbound queue lock 2021-11-25 22:28:32 +01:00
Sven Czarnian
1936b3649b use one second resolution 2021-11-25 22:27:34 +01:00
Sven Czarnian
8390cd5309 define the inbound and predict the flight path 2021-11-25 22:27:03 +01:00
Sven Czarnian
1594be8dc1 adapt to avoid blocking calls 2021-11-25 22:26:26 +01:00
Sven Czarnian
f2f68708ac register the function and the tag 2021-11-25 22:26:11 +01:00
Sven Czarnian
9146446924 change the API 2021-11-25 22:25:51 +01:00
Sven Czarnian
874cc7871d add getter for the arrival waypoints 2021-11-25 22:25:11 +01:00
Sven Czarnian
2240978b01 define the arrival waypoint 2021-11-22 16:18:47 +01:00
Sven Czarnian
155a035a9c define the wind data 2021-11-22 16:18:29 +01:00
Sven Czarnian
319e5b2952 build the geographic coordinates 2021-11-22 16:18:16 +01:00
Sven Czarnian
92bf63bf45 add the helper 2021-11-22 16:17:35 +01:00
Sven Czarnian
969f448bf4 define the geographic library 2021-11-22 16:17:20 +01:00
Sven Czarnian
9f80ce1631 add the helper for the UTC time and mach checks 2021-11-22 16:17:07 +01:00
Sven Czarnian
09e29afe7b add GeographicLib 2021-11-22 16:16:36 +01:00
Sven Czarnian
b1b6b5c790 do not send empty lists 2021-11-21 08:54:22 +01:00
Sven Czarnian
ce23f956ed code formatting 2021-11-21 08:54:11 +01:00
Sven Czarnian
b309e86ec6 change the configuration to handle the new ZMQ-REQ-REP-protocol and the RestAPI-Update protocol 2021-11-21 08:53:58 +01:00
Sven Czarnian
0acb45dd27 force a reload 2021-11-20 09:29:01 +01:00
Sven Czarnian
1bb9813a7a allow to add flights as forced for AMAN to include them, if the neighboring controller is not using AMAN 2021-11-20 09:28:36 +01:00
Sven Czarnian
2cc7c401e8 add the stands of GrPlugin and TST 2021-11-18 16:02:52 +01:00
Sven Czarnian
689c2326c2 use only one backend and adapt to the new communication structure
avoid empty messages
2021-11-18 16:02:41 +01:00
Sven Czarnian
a65aa445fa compare the backend's version with the plugin's version 2021-11-18 15:55:37 +01:00
Sven Czarnian
25c1519bb8 update to the current version 2021-11-18 15:53:57 +01:00
Sven Czarnian
a23de5ee67 add required libraries 2021-11-18 15:53:34 +01:00
Sven Czarnian
1a58301d4f send the reports every ten seconds 2021-11-13 23:03:34 +01:00
Sven Czarnian
d3551c9857 fix a compiler warning 2021-11-13 23:03:08 +01:00
Sven Czarnian
a8f2dba40e use the new interface to create the reports 2021-11-13 23:02:55 +01:00
Sven Czarnian
2b4840d2af fix a bug in the dynamics 2021-11-13 23:01:30 +01:00
Sven Czarnian
a3ef28ae39 rename the sequence receiver 2021-11-13 23:01:12 +01:00
Sven Czarnian
8b1292c95a rename the files and use the new interface to communicate with the backend 2021-11-13 22:59:04 +01:00
Sven Czarnian
50bb565229 build the new protocol files 2021-11-13 22:56:34 +01:00
Sven Czarnian
ab89237a4c extend the format 2021-10-11 21:56:13 +02:00
Sven Czarnian
02830454e7 fix the code to find the correct arrival route 2021-10-11 09:47:01 +02:00
Sven Czarnian
9f6f7c60d0 add the seconds to the report time 2021-10-11 09:46:47 +02:00
Sven Czarnian
9ce9503e7b update the submodule revision 2021-10-10 21:32:40 +02:00
Sven Czarnian
f4cef56164 calculate the required values 2021-10-10 21:32:29 +02:00
Sven Czarnian
818135e294 fix compiler warnings 2021-10-10 21:32:15 +02:00
Sven Czarnian
a934767ffb add the reported timestamp 2021-10-10 21:32:05 +02:00
Sven Czarnian
70a41bfc0e change the interface 2021-10-10 20:52:37 +02:00
Sven Czarnian
e0ab3ac68e fix compiler warnings 2021-10-10 20:52:20 +02:00
Sven Czarnian
7d69203486 updated protobuf to 3.18.1 2021-10-10 20:51:05 +02:00
Sven Czarnian
ea460b1aaf fix path errors 2021-10-10 20:50:20 +02:00
Sven Czarnian
8230538325 introduce the receiver of the scheduling information 2021-08-19 08:48:08 +02:00
Sven Czarnian
559ab86d60 remove unused headers 2021-08-19 08:47:50 +02:00
Sven Czarnian
2cf49c00fc introduce the aircraft scheduler to receive new messages from the backend
threading-concepts are used to avoid unnecessary main thread action
2021-08-19 08:47:39 +02:00
Sven Czarnian
c6677761dd check if the reporter is initialized 2021-08-19 08:21:53 +02:00
Sven Czarnian
eb05256df7 remove temporary filter 2021-08-19 08:21:29 +02:00
Sven Czarnian
221d00c23a add missing documentation 2021-08-19 08:21:20 +02:00
Sven Czarnian
b453d4d8e2 add a function to check if a block is initialized 2021-08-19 08:21:08 +02:00
Sven Czarnian
0fa3559fc4 add missing documentation 2021-08-19 08:20:54 +02:00
Sven Czarnian
9e15b72c54 convert the message in the reporter 2021-08-19 08:20:20 +02:00
Sven Czarnian
d06ec49b2e fix a deadlock or sporadic crash during shutdown 2021-08-19 08:01:22 +02:00
Sven Czarnian
25c6a1fa86 send aircraft reports 2021-08-17 17:31:28 +02:00
Sven Czarnian
7f4f967d83 build all new components 2021-08-17 17:31:08 +02:00
Sven Czarnian
8e36b094a5 introduce the aircraft reporter 2021-08-17 17:30:49 +02:00
Sven Czarnian
b1ab52d717 update the configuration 2021-08-17 17:30:10 +02:00
Sven Czarnian
627361035c define a context for all components 2021-08-17 17:25:59 +02:00
Sven Czarnian
c03b75fc89 update the interface 2021-08-17 17:25:46 +02:00
Sven Czarnian
804213317c add dependent libraries 2021-08-16 16:46:50 +02:00
Sven Czarnian
5a5825e1e4 fix imported target issues 2021-08-16 08:15:19 +02:00
Sven Czarnian
87ba0be57d extend the configuration 2021-08-16 08:08:41 +02:00
Sven Czarnian
db3d3bf48d update the communication version 2021-08-16 07:59:52 +02:00
Sven Czarnian
7b94e22121 add some more filters 2021-08-14 15:30:38 +02:00
Sven Czarnian
ed8fe7ef9a update the submodule 2021-08-14 15:16:01 +02:00
Sven Czarnian
d94e85b748 start with the interpretation of the position updates of aircrafts 2021-08-14 15:03:21 +02:00
Sven Czarnian
24f2ab45e3 generate and build the protobuf files and link against protobuf 2021-08-14 15:02:59 +02:00
Sven Czarnian
93c02cac91 add some spacings 2021-08-14 15:02:21 +02:00
Sven Czarnian
c350298fb5 update the submodule hash 2021-08-14 15:01:58 +02:00
Sven Czarnian
57a4aae223 add aman-com as a submodule 2021-08-14 14:52:48 +02:00
Sven Czarnian
8a3c2d3cb8 prepare the receive aircraft position updates 2021-08-14 10:37:08 +02:00
Sven Czarnian
c7ab3bd551 introduce the radar screen to receive aircraft information 2021-08-14 10:36:43 +02:00
Sven Czarnian
5da73b0b52 Merge branch 'feature/configuration' into 'develop'
Feature/configuration

See merge request nav/aman-es!2
2021-08-11 06:31:08 +00:00
Sven Czarnian
f188b85dcd load the configuration files 2021-08-11 08:29:38 +02:00
Sven Czarnian
fad3ca0de1 add a log message and find the path of the DLL to load the configurations later 2021-08-11 08:29:14 +02:00
Sven Czarnian
ac022f55fc add the configuration to the plugin 2021-08-11 08:27:51 +02:00
Sven Czarnian
272fb3aab0 add the communication file format 2021-08-10 08:42:53 +02:00
Sven Czarnian
3c4acffbb9 define the configuration to handle communication settings 2021-08-10 08:42:36 +02:00
Sven Czarnian
81edcdcea2 add a parser to read the UID per user 2021-08-10 08:42:00 +02:00
Sven Czarnian
163786698c define the base class to define different file formats 2021-08-10 08:40:53 +02:00
Sven Czarnian
5543d28bbf add GSL as a dependency 2021-08-10 08:39:45 +02:00
Sven Czarnian
4de1e2fc43 add an helper class to process strings 2021-08-10 08:39:34 +02:00
Sven Czarnian
557c781fa6 add GSL as a development dependency 2021-08-10 08:38:48 +02:00
Sven Czarnian
2a0dad3c7b update comments 2021-08-10 08:09:39 +02:00
Sven Czarnian
d594fd3252 remove symbols 2021-08-10 07:56:50 +02:00
Sven Czarnian
f0db197d7d remove GDI+ 2021-08-10 07:56:41 +02:00
Sven Czarnian
9696a66aab rename the namespace 2021-08-10 07:56:31 +02:00
Sven Czarnian
c7cf982671 remove unused variables 2021-08-10 07:20:14 +02:00
Sven Czarnian
a043314902 build the plugin 2021-08-09 22:28:49 +02:00
Sven Czarnian
40fa70186b add a missing include directory 2021-08-09 22:28:39 +02:00
Sven Czarnian
7addd2ab43 configure the build files 2021-08-09 22:28:26 +02:00
Sven Czarnian
328420c185 build the plugin 2021-08-09 22:28:09 +02:00
Sven Czarnian
18d285031c introduce the plugin definition 2021-08-09 22:28:00 +02:00
Sven Czarnian
0035c97c20 introduce resource files 2021-08-09 22:27:42 +02:00
Sven Czarnian
52870429a6 add missing templates for the automated file generation 2021-08-09 22:27:27 +02:00
Sven Czarnian
6caf47886a define the root-cmake-script 2021-08-09 22:07:28 +02:00
Sven Czarnian
27857b0369 introduce some required cmake scripts 2021-08-09 22:07:14 +02:00
Sven Czarnian
4cde0f9baf add external dependencies in a pre-built way to avoid incompatibilities 2021-08-09 22:07:00 +02:00
Sven Czarnian
5f702016ad add the license of the project 2021-08-09 22:06:03 +02:00
Sven Czarnian
539987868c update the documentation 2021-08-09 22:05:52 +02:00
801فایلهای تغییر یافته به همراه278507 افزوده شده و 1 حذف شده

4
.gitmodules فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,4 @@
[submodule "src/com/protobuf"]
path = src/com/protobuf
url = git@git.vatsim-germany.org:nav/aman-com.git
branch = feature/protobuf

67
CMakeLists.txt Normal file
مشاهده پرونده

@@ -0,0 +1,67 @@
# Author:
# Sven Czarnian <devel@svcz.de>
# Copyright:
# 2021 Sven Czarnian
# License:
# GPLv3
# Brief:
# Creates the AMAN-EuroScope solution
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
# define the project information
PROJECT(ArrivalMANager LANGUAGES CXX VERSION "0.1.0")
# define the language parameters
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
# adapt compiler flags based on used compiler
IF (MSVC)
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
ELSE ()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
ENDIF ()
IF (NOT CMAKE_CXX_FLAGS MATCHES "/MP")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
ENDIF ()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /sdl /permissive- /DNOMINMAX")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /sdl /permissive- /DNOMINMAX")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFESTUAC:NO")
ADD_DEFINITIONS(/D_USRDLL /D_CRT_SECURE_NO_WARNINGS)
ENDIF ()
CONFIGURE_FILE(
${CMAKE_SOURCE_DIR}/version.h.in
${CMAKE_BINARY_DIR}/include/version.h
)
CONFIGURE_FILE(
${CMAKE_SOURCE_DIR}/res/ArrivalMANager.rc.in
${CMAKE_BINARY_DIR}/ArrivalMANager.rc
)
# define include directories
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/include
${CMAKE_BINARY_DIR}/include
)
INCLUDE(cmake/3rdParty.cmake)
INCLUDE(cmake/Protobuf.cmake)
INCLUDE(cmake/FindEuroScope.cmake)
# register all cmake helper to find required modules and find 3rd-party components
SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_SOURCE_DIR}/cmake")
FIND_PACKAGE(EuroScope REQUIRED)
IF(NOT EuroScope_FOUND)
MESSAGE(FATAL_ERROR "Unablet to build without EuroScope and the EuroScope-SDK")
ENDIF()
ADD_SUBDIRECTORY(src)

674
LICENSE Normal file
مشاهده پرونده

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

مشاهده پرونده

@@ -1,2 +1,30 @@
# aman-es
# Arrival MANanager (AMAN)
## System description
AMAN is splitted up into four different components.
* aman-com defines the diffent message types
* aman-es implements an EuroScope plugin to communicate with [aman-sys](https://git.vatsim-germany.org/nav/aman-sys)
* aman-sys implements the backend system to plan an optimal arrival sequence for the different airports
* aman-web implements a web-interface to configure [aman-sys](https://git.vatsim-germany.org/nav/aman-sys) and visualize sequences
## Component description
AMAN uses [Protocol Buffers](https://developers.google.com/protocol-buffers)
for the message serialization and message definition between the EuroScope instance and the AMAN backend.
Additionally is [ZeroMQ](https://zeromq.org/) used for the communication abstraction layer.
This component extracts all relevant information out of the VATSIM network and sends the information to the server.
Additionally is a unique identifier used to verify connections to the backend.
According to data protection is the ZeroMQ-based network encryption used.
Every controller needs his own unique identifier.
# Additional libraries
* [ZeroMQ](https://github.com/zeromq) - GNU GPLv3
* [Protocol Buffers](https://github.com/protocolbuffers/protobuf) - BSD-3
# License
AMAN is released under the [GNU General Public License v3](LICENSE)

8
cmake/3rdParty.cmake Normal file
مشاهده پرونده

@@ -0,0 +1,8 @@
# Author:
# Sven Czarnian <devel@svcz.de>
# License:
# GPLv3
# Brief:
# Creates the 3rd-party targets
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/3rdPartyTargets.cmake)

100
cmake/3rdPartyTargets.cmake Normal file
مشاهده پرونده

@@ -0,0 +1,100 @@
# Author:
# Sven Czarnian <devel@svcz.de>
# License:
# GPLv3
# Brief:
# Creates the 3rd-party import targets
# include the external project library
INCLUDE(ExternalProject)
# define the import target of libcurl
ADD_LIBRARY(libcurl STATIC IMPORTED)
IF (MSVC)
SET_TARGET_PROPERTIES(libcurl PROPERTIES
IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/libcurl-d.lib"
IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/libcurl.lib"
)
TARGET_LINK_LIBRARIES(libcurl INTERFACE Ws2_32 Iphlpapi Crypt32)
TARGET_INCLUDE_DIRECTORIES(libcurl INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler")
ENDIF ()
# define the import target of GeographicLib
ADD_LIBRARY(GeographicLib STATIC IMPORTED)
IF (MSVC)
SET_TARGET_PROPERTIES(GeographicLib PROPERTIES
IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/Geographic_d.lib"
IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/Geographic.lib"
)
TARGET_INCLUDE_DIRECTORIES(GeographicLib INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler")
ENDIF ()
# define the import target of libsodium
ADD_LIBRARY(libsodium STATIC IMPORTED)
IF (MSVC)
SET_TARGET_PROPERTIES(libsodium PROPERTIES
IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/libsodiumd.lib"
IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/libsodium.lib"
)
TARGET_LINK_LIBRARIES(libsodium INTERFACE Ws2_32 Iphlpapi)
TARGET_INCLUDE_DIRECTORIES(libsodium INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler")
ENDIF ()
# define the import target of libcurl
ADD_LIBRARY(jsoncpp STATIC IMPORTED)
IF (MSVC)
SET_TARGET_PROPERTIES(jsoncpp PROPERTIES
IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/jsoncpp_d.lib"
IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/jsoncpp.lib"
)
TARGET_INCLUDE_DIRECTORIES(jsoncpp INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler")
ENDIF ()
# define the import target of libzmq
ADD_LIBRARY(libzmq STATIC IMPORTED)
ADD_DEPENDENCIES(libzmq libsodium)
IF (MSVC)
SET_TARGET_PROPERTIES(libzmq PROPERTIES
IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/libzmqd.lib"
IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/libzmq.lib"
)
TARGET_INCLUDE_DIRECTORIES(libzmq INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
TARGET_LINK_LIBRARIES(libzmq INTERFACE libsodium)
TARGET_COMPILE_OPTIONS(libzmq INTERFACE /DZMQ_STATIC)
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler")
ENDIF ()
# define the import target of cppzmq
ADD_LIBRARY(cppzmq INTERFACE)
TARGET_INCLUDE_DIRECTORIES(cppzmq INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
TARGET_LINK_LIBRARIES(cppzmq INTERFACE libzmq)
ADD_DEPENDENCIES(cppzmq libzmq)
# define the import target of GSL
ADD_LIBRARY(GSL INTERFACE)
TARGET_INCLUDE_DIRECTORIES(GSL INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
# define the import target of Eigen
ADD_LIBRARY(Eigen INTERFACE)
TARGET_INCLUDE_DIRECTORIES(Eigen INTERFACE "${CMAKE_SOURCE_DIR}/external/include/eigen3")
# define the import target of protobuf
ADD_LIBRARY(protobuf STATIC IMPORTED)
IF (MSVC)
SET_TARGET_PROPERTIES(protobuf PROPERTIES
IMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/external/lib/libprotobufd.lib"
IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/external/lib/libprotobuf.lib"
)
TARGET_INCLUDE_DIRECTORIES(protobuf INTERFACE "${CMAKE_SOURCE_DIR}/external/include")
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler")
ENDIF ()

49
cmake/FindEuroScope.cmake Normal file
مشاهده پرونده

@@ -0,0 +1,49 @@
# Author:
# Sven Czarnian <devel@svcz.de>
# License:
# LGPLv3
# Brief:
# Finds the EuroScope headers and libraries
# A target EuroScope will be created and the EuroScope_FOUND flag will be set
IF(NOT TARGET EuroScope)
IF(NOT EuroScope_DIR)
MESSAGE(FATAL_ERROR "Please set EuroScope_DIR")
SET(EuroScope_DIR "EuroScope_DIR-NOTFOUND" CACHE PATH PARENT_SCOPE)
ENDIF()
FIND_FILE(EuroScope_EXECUTABLE
NAMES
EuroScope.exe
PATHS
${EuroScope_DIR}
)
FIND_FILE(EuroScope_LIBRARY
NAMES
EuroScopePlugInDll.lib
PATHS
${EuroScope_DIR}/PlugInEnvironment
)
FIND_PATH(EuroScope_INCLUDE_DIR
NAMES
EuroScopePlugIn.h
PATHS
${EuroScope_DIR}/PlugInEnvironment
)
IF(NOT ${EuroScope_EXECUTABLE} STREQUAL "EuroScope_EXECUTABLE-NOTFOUND" AND
NOT ${EuroScope_LIBRARY} STREQUAL "EuroScope_LIBRARY-NOTFOUND" AND
NOT ${EuroScope_INCLUDE_DIR} STREQUAL "EuroScope_INCLUDE_DIR-NOTFOUND")
MESSAGE(STATUS "Found EuroScope-library:")
MESSAGE(STATUS " ${EuroScope_LIBRARY}")
MESSAGE(STATUS "Found EuroScope-headers:")
MESSAGE(STATUS " ${EuroScope_INCLUDE_DIR}")
ADD_LIBRARY(EuroScope INTERFACE IMPORTED GLOBAL)
TARGET_LINK_LIBRARIES(EuroScope INTERFACE ${EuroScope_LIBRARY})
TARGET_INCLUDE_DIRECTORIES(EuroScope INTERFACE ${EuroScope_INCLUDE_DIR})
SET(EuroScope_FOUND ON)
ENDIF()
ELSE()
MESSAGE(STATUS "EuroScope is already included.")
ENDIF()

51
cmake/Protobuf.cmake Normal file
مشاهده پرونده

@@ -0,0 +1,51 @@
# Author:
# Sven Czarnian <devel@svcz.de>
# License:
# Closed Source
# Brief:
# Defines the protobuf functions
# Brief:
# Proto-files are compiled into C++ files
# Parameters:
# PROTO_FILES - The proto-files with the message description
# SOURCE_FILES - Contains the filenames and paths of the generated files
FUNCTION(ProtobufCompile PROTO_FILES SOURCE_FILES)
SET(GENERATED_FILES "")
FOREACH (PROTO ${PROTO_FILES})
# get the relevant information to configure the protoc-run
GET_FILENAME_COMPONENT(FILENAME ${PROTO} NAME_WLE)
GET_FILENAME_COMPONENT(DIRECTORY ${PROTO} DIRECTORY)
# define the output files
SET(CPP_FILE ${CMAKE_CURRENT_BINARY_DIR}/protobuf/${FILENAME}.pb.cc)
SET(HPP_FILE ${CMAKE_CURRENT_BINARY_DIR}/protobuf/${FILENAME}.pb.h)
# create the protoc-directory
FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/protobuf)
# define the protoc-command
ADD_CUSTOM_COMMAND(
OUTPUT ${CPP_FILE} ${HPP_FILE}
DEPENDS protobuf
COMMAND ${CMAKE_SOURCE_DIR}/external/bin/protoc.exe
ARGS -I=${DIRECTORY} --cpp_out=${CMAKE_CURRENT_BINARY_DIR}/protobuf ${PROTO}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/external/bin"
COMMENT "Creating C++-sources for ${PROTO}"
)
# disable warnings
IF (MSVC)
SET_SOURCE_FILES_PROPERTIES(${CPP_FILE} PROPERTIES COMPILE_FLAGS "/wd4127 /wd5054 /wd4125 /wd4267")
SET_SOURCE_FILES_PROPERTIES(${HPP_FILE} PROPERTIES COMPILE_FLAGS "/wd4127 /wd5054 /wd4125 /wd4267")
ENDIF ()
# add the generated files
LIST(APPEND GENERATED_FILES ${CPP_FILE})
LIST(APPEND GENERATED_FILES ${HPP_FILE})
ENDFOREACH ()
# set the output variables
SET(${SOURCE_FILES} ${GENERATED_FILES} PARENT_SCOPE)
ENDFUNCTION()

دودویی (BIN)
external/bin/protoc.exe فروخته شده Normal file

فایل باینری نشان داده نشده است.

198
external/include/GeographicLib/Accumulator.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,198 @@
/**
* \file Accumulator.hpp
* \brief Header for GeographicLib::Accumulator class
*
* Copyright (c) Charles Karney (2010-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_ACCUMULATOR_HPP)
#define GEOGRAPHICLIB_ACCUMULATOR_HPP 1
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief An accumulator for sums
*
* This allows many numbers of floating point type \e T to be added together
* with twice the normal precision. Thus if \e T is double, the effective
* precision of the sum is 106 bits or about 32 decimal places.
*
* The implementation follows J. R. Shewchuk,
* <a href="https://doi.org/10.1007/PL00009321"> Adaptive Precision
* Floating-Point Arithmetic and Fast Robust Geometric Predicates</a>,
* Discrete & Computational Geometry 18(3) 305--363 (1997).
*
* Approximate timings (summing a vector<double>)
* - double: 2ns
* - Accumulator<double>: 23ns
*
* In the documentation of the member functions, \e sum stands for the value
* currently held in the accumulator.
*
* Example of use:
* \include example-Accumulator.cpp
**********************************************************************/
template<typename T = Math::real>
class GEOGRAPHICLIB_EXPORT Accumulator {
private:
// _s + _t accumulators for the sum.
T _s, _t;
// Same as Math::sum, but requires abs(u) >= abs(v). This isn't currently
// used.
static T fastsum(T u, T v, T& t) {
GEOGRAPHICLIB_VOLATILE T s = u + v;
GEOGRAPHICLIB_VOLATILE T vp = s - u;
t = v - vp;
return s;
}
void Add(T y) {
// Here's Shewchuk's solution...
T u; // hold exact sum as [s, t, u]
// Accumulate starting at least significant end
y = Math::sum(y, _t, u);
_s = Math::sum(y, _s, _t);
// Start is _s, _t decreasing and non-adjacent. Sum is now (s + t + u)
// exactly with s, t, u non-adjacent and in decreasing order (except for
// possible zeros). The following code tries to normalize the result.
// Ideally, we want _s = round(s+t+u) and _u = round(s+t+u - _s). The
// following does an approximate job (and maintains the decreasing
// non-adjacent property). Here are two "failures" using 3-bit floats:
//
// Case 1: _s is not equal to round(s+t+u) -- off by 1 ulp
// [12, -1] - 8 -> [4, 0, -1] -> [4, -1] = 3 should be [3, 0] = 3
//
// Case 2: _s+_t is not as close to s+t+u as it shold be
// [64, 5] + 4 -> [64, 8, 1] -> [64, 8] = 72 (off by 1)
// should be [80, -7] = 73 (exact)
//
// "Fixing" these problems is probably not worth the expense. The
// representation inevitably leads to small errors in the accumulated
// values. The additional errors illustrated here amount to 1 ulp of the
// less significant word during each addition to the Accumulator and an
// additional possible error of 1 ulp in the reported sum.
//
// Incidentally, the "ideal" representation described above is not
// canonical, because _s = round(_s + _t) may not be true. For example,
// with 3-bit floats:
//
// [128, 16] + 1 -> [160, -16] -- 160 = round(145).
// But [160, 0] - 16 -> [128, 16] -- 128 = round(144).
//
if (_s == 0) // This implies t == 0,
_s = u; // so result is u
else
_t += u; // otherwise just accumulate u to t.
}
T Sum(T y) const {
Accumulator a(*this);
a.Add(y);
return a._s;
}
public:
/**
* Construct from a \e T. This is not declared explicit, so that you can
* write <code>Accumulator<double> a = 5;</code>.
*
* @param[in] y set \e sum = \e y.
**********************************************************************/
Accumulator(T y = T(0)) : _s(y), _t(0) {
static_assert(!std::numeric_limits<T>::is_integer,
"Accumulator type is not floating point");
}
/**
* Set the accumulator to a number.
*
* @param[in] y set \e sum = \e y.
**********************************************************************/
Accumulator& operator=(T y) { _s = y; _t = 0; return *this; }
/**
* Return the value held in the accumulator.
*
* @return \e sum.
**********************************************************************/
T operator()() const { return _s; }
/**
* Return the result of adding a number to \e sum (but don't change \e
* sum).
*
* @param[in] y the number to be added to the sum.
* @return \e sum + \e y.
**********************************************************************/
T operator()(T y) const { return Sum(y); }
/**
* Add a number to the accumulator.
*
* @param[in] y set \e sum += \e y.
**********************************************************************/
Accumulator& operator+=(T y) { Add(y); return *this; }
/**
* Subtract a number from the accumulator.
*
* @param[in] y set \e sum -= \e y.
**********************************************************************/
Accumulator& operator-=(T y) { Add(-y); return *this; }
/**
* Multiply accumulator by an integer. To avoid loss of accuracy, use only
* integers such that \e n &times; \e T is exactly representable as a \e T
* (i.e., &plusmn; powers of two). Use \e n = &minus;1 to negate \e sum.
*
* @param[in] n set \e sum *= \e n.
**********************************************************************/
Accumulator& operator*=(int n) { _s *= n; _t *= n; return *this; }
/**
* Multiply accumulator by a number. The fma (fused multiply and add)
* instruction is used (if available) in order to maintain accuracy.
*
* @param[in] y set \e sum *= \e y.
**********************************************************************/
Accumulator& operator*=(T y) {
using std::fma;
T d = _s; _s *= y;
d = fma(y, d, -_s); // the error in the first multiplication
_t = fma(y, _t, d); // add error to the second term
return *this;
}
/**
* Reduce accumulator to the range [-y/2, y/2].
*
* @param[in] y the modulus.
**********************************************************************/
Accumulator& remainder(T y) {
using std::remainder;
_s = remainder(_s, y);
Add(0); // This renormalizes the result.
return *this;
}
/**
* Test equality of an Accumulator with a number.
**********************************************************************/
bool operator==(T y) const { return _s == y; }
/**
* Test inequality of an Accumulator with a number.
**********************************************************************/
bool operator!=(T y) const { return _s != y; }
/**
* Less operator on an Accumulator and a number.
**********************************************************************/
bool operator<(T y) const { return _s < y; }
/**
* Less or equal operator on an Accumulator and a number.
**********************************************************************/
bool operator<=(T y) const { return _s <= y; }
/**
* Greater operator on an Accumulator and a number.
**********************************************************************/
bool operator>(T y) const { return _s > y; }
/**
* Greater or equal operator on an Accumulator and a number.
**********************************************************************/
bool operator>=(T y) const { return _s >= y; }
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_ACCUMULATOR_HPP

321
external/include/GeographicLib/AlbersEqualArea.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,321 @@
/**
* \file AlbersEqualArea.hpp
* \brief Header for GeographicLib::AlbersEqualArea class
*
* Copyright (c) Charles Karney (2010-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_ALBERSEQUALAREA_HPP)
#define GEOGRAPHICLIB_ALBERSEQUALAREA_HPP 1
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Albers equal area conic projection
*
* Implementation taken from the report,
* - J. P. Snyder,
* <a href="http://pubs.er.usgs.gov/usgspubs/pp/pp1395"> Map Projections: A
* Working Manual</a>, USGS Professional Paper 1395 (1987),
* pp. 101--102.
*
* This is a implementation of the equations in Snyder except that divided
* differences will be [have been] used to transform the expressions into
* ones which may be evaluated accurately. [In this implementation, the
* projection correctly becomes the cylindrical equal area or the azimuthal
* equal area projection when the standard latitude is the equator or a
* pole.]
*
* The ellipsoid parameters, the standard parallels, and the scale on the
* standard parallels are set in the constructor. Internally, the case with
* two standard parallels is converted into a single standard parallel, the
* latitude of minimum azimuthal scale, with an azimuthal scale specified on
* this parallel. This latitude is also used as the latitude of origin which
* is returned by AlbersEqualArea::OriginLatitude. The azimuthal scale on
* the latitude of origin is given by AlbersEqualArea::CentralScale. The
* case with two standard parallels at opposite poles is singular and is
* disallowed. The central meridian (which is a trivial shift of the
* longitude) is specified as the \e lon0 argument of the
* AlbersEqualArea::Forward and AlbersEqualArea::Reverse functions.
* AlbersEqualArea::Forward and AlbersEqualArea::Reverse also return the
* meridian convergence, &gamma;, and azimuthal scale, \e k. A small square
* aligned with the cardinal directions is projected to a rectangle with
* dimensions \e k (in the E-W direction) and 1/\e k (in the N-S direction).
* The E-W sides of the rectangle are oriented &gamma; degrees
* counter-clockwise from the \e x axis. There is no provision in this class
* for specifying a false easting or false northing or a different latitude
* of origin.
*
* Example of use:
* \include example-AlbersEqualArea.cpp
*
* <a href="ConicProj.1.html">ConicProj</a> is a command-line utility
* providing access to the functionality of LambertConformalConic and
* AlbersEqualArea.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT AlbersEqualArea {
private:
typedef Math::real real;
real eps_, epsx_, epsx2_, tol_, tol0_;
real _a, _f, _fm, _e2, _e, _e2m, _qZ, _qx;
real _sign, _lat0, _k0;
real _n0, _m02, _nrho0, _k2, _txi0, _scxi0, _sxi0;
static const int numit_ = 5; // Newton iterations in Reverse
static const int numit0_ = 20; // Newton iterations in Init
static real hyp(real x) {
using std::hypot;
return hypot(real(1), x);
}
// atanh( e * x)/ e if f > 0
// atan (sqrt(-e2) * x)/sqrt(-e2) if f < 0
// x if f = 0
real atanhee(real x) const {
using std::atan; using std::abs; using std::atanh;
return _f > 0 ? atanh(_e * x)/_e : (_f < 0 ? (atan(_e * x)/_e) : x);
}
// return atanh(sqrt(x))/sqrt(x) - 1, accurate for small x
static real atanhxm1(real x);
// Divided differences
// Definition: Df(x,y) = (f(x)-f(y))/(x-y)
// See:
// W. M. Kahan and R. J. Fateman,
// Symbolic computation of divided differences,
// SIGSAM Bull. 33(3), 7-28 (1999)
// https://doi.org/10.1145/334714.334716
// http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
//
// General rules
// h(x) = f(g(x)): Dh(x,y) = Df(g(x),g(y))*Dg(x,y)
// h(x) = f(x)*g(x):
// Dh(x,y) = Df(x,y)*g(x) + Dg(x,y)*f(y)
// = Df(x,y)*g(y) + Dg(x,y)*f(x)
// = Df(x,y)*(g(x)+g(y))/2 + Dg(x,y)*(f(x)+f(y))/2
//
// sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^2))
static real Dsn(real x, real y, real sx, real sy) {
// sx = x/hyp(x)
real t = x * y;
return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) :
(x - y != 0 ? (sx - sy) / (x - y) : 1);
}
// Datanhee(x,y) = (atanee(x)-atanee(y))/(x-y)
// = atanhee((x-y)/(1-e^2*x*y))/(x-y)
real Datanhee(real x, real y) const {
real t = x - y, d = 1 - _e2 * x * y;
return t == 0 ? 1 / d :
(x*y < 0 ? atanhee(x) - atanhee(y) : atanhee(t / d)) / t;
}
// DDatanhee(x,y) = (Datanhee(1,y) - Datanhee(1,x))/(y-x)
real DDatanhee(real x, real y) const;
real DDatanhee0(real x, real y) const;
real DDatanhee1(real x, real y) const;
real DDatanhee2(real x, real y) const;
void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1);
real txif(real tphi) const;
real tphif(real txi) const;
friend class Ellipsoid; // For access to txif, tphif, etc.
public:
/**
* Constructor with a single standard parallel.
*
* @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] stdlat standard parallel (degrees), the circle of tangency.
* @param[in] k0 azimuthal scale on the standard parallel.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive.
* @exception GeographicErr if \e stdlat is not in [&minus;90&deg;,
* 90&deg;].
**********************************************************************/
AlbersEqualArea(real a, real f, real stdlat, real k0);
/**
* Constructor with two standard parallels.
*
* @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] stdlat1 first standard parallel (degrees).
* @param[in] stdlat2 second standard parallel (degrees).
* @param[in] k1 azimuthal scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if \e stdlat1 and \e stdlat2 are
* opposite poles.
**********************************************************************/
AlbersEqualArea(real a, real f, real stdlat1, real stdlat2, real k1);
/**
* Constructor with two standard parallels specified by sines and cosines.
*
* @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] sinlat1 sine of first standard parallel.
* @param[in] coslat1 cosine of first standard parallel.
* @param[in] sinlat2 sine of second standard parallel.
* @param[in] coslat2 cosine of second standard parallel.
* @param[in] k1 azimuthal scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if \e stdlat1 and \e stdlat2 are
* opposite poles.
*
* This allows parallels close to the poles to be specified accurately.
* This routine computes the latitude of origin and the azimuthal scale at
* this latitude. If \e dlat = abs(\e lat2 &minus; \e lat1) &le; 160&deg;,
* then the error in the latitude of origin is less than 4.5 &times;
* 10<sup>&minus;14</sup>d;.
**********************************************************************/
AlbersEqualArea(real a, real f,
real sinlat1, real coslat1,
real sinlat2, real coslat2,
real k1);
/**
* Set the azimuthal scale for the projection.
*
* @param[in] lat (degrees).
* @param[in] k azimuthal scale at latitude \e lat (default 1).
* @exception GeographicErr \e k is not positive.
* @exception GeographicErr if \e lat is not in (&minus;90&deg;,
* 90&deg;).
*
* This allows a "latitude of conformality" to be specified.
**********************************************************************/
void SetScale(real lat, real k = real(1));
/**
* Forward projection, from geographic to Lambert conformal conic.
*
* @param[in] lon0 central meridian longitude (degrees).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k azimuthal scale of projection at point; the radial
* scale is the 1/\e k.
*
* The latitude origin is given by AlbersEqualArea::LatitudeOrigin(). No
* false easting or northing is added and \e lat should be in the range
* [&minus;90&deg;, 90&deg;]. The values of \e x and \e y returned for
* points which project to infinity (i.e., one or both of the poles) will
* be large but finite.
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y, real& gamma, real& k) const;
/**
* Reverse projection, from Lambert conformal conic to geographic.
*
* @param[in] lon0 central meridian longitude (degrees).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k azimuthal scale of projection at point; the radial
* scale is the 1/\e k.
*
* The latitude origin is given by AlbersEqualArea::LatitudeOrigin(). No
* false easting or northing is added. The value of \e lon returned is in
* the range [&minus;180&deg;, 180&deg;]. The value of \e lat returned is
* in the range [&minus;90&deg;, 90&deg;]. If the input point is outside
* the legal projected space the nearest pole is returned.
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon, real& gamma, real& k) const;
/**
* AlbersEqualArea::Forward without returning the convergence and
* scale.
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y) const {
real gamma, k;
Forward(lon0, lat, lon, x, y, gamma, k);
}
/**
* AlbersEqualArea::Reverse without returning the convergence and
* scale.
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon) const {
real gamma, k;
Reverse(lon0, x, y, lat, lon, gamma, k);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the value used in
* the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return latitude of the origin for the projection (degrees).
*
* This is the latitude of minimum azimuthal scale and equals the \e stdlat
* in the 1-parallel constructor and lies between \e stdlat1 and \e stdlat2
* in the 2-parallel constructors.
**********************************************************************/
Math::real OriginLatitude() const { return _lat0; }
/**
* @return central scale for the projection. This is the azimuthal scale
* on the latitude of origin.
**********************************************************************/
Math::real CentralScale() const { return _k0; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e
* stdlat = 0, and \e k0 = 1. This degenerates to the cylindrical equal
* area projection.
**********************************************************************/
static const AlbersEqualArea& CylindricalEqualArea();
/**
* A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e
* stdlat = 90&deg;, and \e k0 = 1. This degenerates to the
* Lambert azimuthal equal area projection.
**********************************************************************/
static const AlbersEqualArea& AzimuthalEqualAreaNorth();
/**
* A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e
* stdlat = &minus;90&deg;, and \e k0 = 1. This degenerates to the
* Lambert azimuthal equal area projection.
**********************************************************************/
static const AlbersEqualArea& AzimuthalEqualAreaSouth();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_ALBERSEQUALAREA_HPP

145
external/include/GeographicLib/AzimuthalEquidistant.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,145 @@
/**
* \file AzimuthalEquidistant.hpp
* \brief Header for GeographicLib::AzimuthalEquidistant class
*
* Copyright (c) Charles Karney (2009-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_AZIMUTHALEQUIDISTANT_HPP)
#define GEOGRAPHICLIB_AZIMUTHALEQUIDISTANT_HPP 1
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Azimuthal equidistant projection
*
* Azimuthal equidistant projection centered at an arbitrary position on the
* ellipsoid. For a point in projected space (\e x, \e y), the geodesic
* distance from the center position is hypot(\e x, \e y) and the azimuth of
* the geodesic from the center point is atan2(\e x, \e y). The Forward and
* Reverse methods also return the azimuth \e azi of the geodesic at (\e x,
* \e y) and reciprocal scale \e rk in the azimuthal direction which,
* together with the basic properties of the projection, serve to specify
* completely the local affine transformation between geographic and
* projected coordinates.
*
* The conversions all take place using a Geodesic object (by default
* Geodesic::WGS84()). For more information on geodesics see \ref geodesic.
*
* Example of use:
* \include example-AzimuthalEquidistant.cpp
*
* <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utility
* providing access to the functionality of AzimuthalEquidistant, Gnomonic,
* and CassiniSoldner.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT AzimuthalEquidistant {
private:
typedef Math::real real;
real eps_;
Geodesic _earth;
public:
/**
* Constructor for AzimuthalEquidistant.
*
* @param[in] earth the Geodesic object to use for geodesic calculations.
* By default this uses the WGS84 ellipsoid.
**********************************************************************/
explicit AzimuthalEquidistant(const Geodesic& earth = Geodesic::WGS84());
/**
* Forward projection, from geographic to azimuthal equidistant.
*
* @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] azi azimuth of geodesic at point (degrees).
* @param[out] rk reciprocal of azimuthal scale at point.
*
* \e lat0 and \e lat should be in the range [&minus;90&deg;, 90&deg;].
* The scale of the projection is 1 in the "radial" direction, \e azi
* clockwise from true north, and is 1/\e rk in the direction perpendicular
* to this. A call to Forward followed by a call to Reverse will return
* the original (\e lat, \e lon) (to within roundoff).
**********************************************************************/
void Forward(real lat0, real lon0, real lat, real lon,
real& x, real& y, real& azi, real& rk) const;
/**
* Reverse projection, from azimuthal equidistant to geographic.
*
* @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] azi azimuth of geodesic at point (degrees).
* @param[out] rk reciprocal of azimuthal scale at point.
*
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;]. \e lat will
* be in the range [&minus;90&deg;, 90&deg;] and \e lon will be in the
* range [&minus;180&deg;, 180&deg;]. The scale of the projection is 1 in
* the "radial" direction, \e azi clockwise from true north, and is 1/\e rk
* in the direction perpendicular to this. A call to Reverse followed by a
* call to Forward will return the original (\e x, \e y) (to roundoff) only
* if the geodesic to (\e x, \e y) is a shortest path.
**********************************************************************/
void Reverse(real lat0, real lon0, real x, real y,
real& lat, real& lon, real& azi, real& rk) const;
/**
* AzimuthalEquidistant::Forward without returning the azimuth and scale.
**********************************************************************/
void Forward(real lat0, real lon0, real lat, real lon,
real& x, real& y) const {
real azi, rk;
Forward(lat0, lon0, lat, lon, x, y, azi, rk);
}
/**
* AzimuthalEquidistant::Reverse without returning the azimuth and scale.
**********************************************************************/
void Reverse(real lat0, real lon0, real x, real y,
real& lat, real& lon) const {
real azi, rk;
Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_AZIMUTHALEQUIDISTANT_HPP

210
external/include/GeographicLib/CassiniSoldner.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,210 @@
/**
* \file CassiniSoldner.hpp
* \brief Header for GeographicLib::CassiniSoldner class
*
* Copyright (c) Charles Karney (2009-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_CASSINISOLDNER_HPP)
#define GEOGRAPHICLIB_CASSINISOLDNER_HPP 1
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/GeodesicLine.hpp>
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Cassini-Soldner projection
*
* Cassini-Soldner projection centered at an arbitrary position, \e lat0, \e
* lon0, on the ellipsoid. This projection is a transverse cylindrical
* equidistant projection. The projection from (\e lat, \e lon) to easting
* and northing (\e x, \e y) is defined by geodesics as follows. Go north
* along a geodesic a distance \e y from the central point; then turn
* clockwise 90&deg; and go a distance \e x along a geodesic.
* (Although the initial heading is north, this changes to south if the pole
* is crossed.) This procedure uniquely defines the reverse projection. The
* forward projection is constructed as follows. Find the point (\e lat1, \e
* lon1) on the meridian closest to (\e lat, \e lon). Here we consider the
* full meridian so that \e lon1 may be either \e lon0 or \e lon0 +
* 180&deg;. \e x is the geodesic distance from (\e lat1, \e lon1) to
* (\e lat, \e lon), appropriately signed according to which side of the
* central meridian (\e lat, \e lon) lies. \e y is the shortest distance
* along the meridian from (\e lat0, \e lon0) to (\e lat1, \e lon1), again,
* appropriately signed according to the initial heading. [Note that, in the
* case of prolate ellipsoids, the shortest meridional path from (\e lat0, \e
* lon0) to (\e lat1, \e lon1) may not be the shortest path.] This procedure
* uniquely defines the forward projection except for a small class of points
* for which there may be two equally short routes for either leg of the
* path.
*
* Because of the properties of geodesics, the (\e x, \e y) grid is
* orthogonal. The scale in the easting direction is unity. The scale, \e
* k, in the northing direction is unity on the central meridian and
* increases away from the central meridian. The projection routines return
* \e azi, the true bearing of the easting direction, and \e rk = 1/\e k, the
* reciprocal of the scale in the northing direction.
*
* The conversions all take place using a Geodesic object (by default
* Geodesic::WGS84()). For more information on geodesics see \ref geodesic.
* The determination of (\e lat1, \e lon1) in the forward projection is by
* solving the inverse geodesic problem for (\e lat, \e lon) and its twin
* obtained by reflection in the meridional plane. The scale is found by
* determining where two neighboring geodesics intersecting the central
* meridian at \e lat1 and \e lat1 + \e dlat1 intersect and taking the ratio
* of the reduced lengths for the two geodesics between that point and,
* respectively, (\e lat1, \e lon1) and (\e lat, \e lon).
*
* Example of use:
* \include example-CassiniSoldner.cpp
*
* <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utility
* providing access to the functionality of AzimuthalEquidistant, Gnomonic,
* and CassiniSoldner.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT CassiniSoldner {
private:
typedef Math::real real;
Geodesic _earth;
GeodesicLine _meridian;
real _sbet0, _cbet0;
static const unsigned maxit_ = 10;
public:
/**
* Constructor for CassiniSoldner.
*
* @param[in] earth the Geodesic object to use for geodesic calculations.
* By default this uses the WGS84 ellipsoid.
*
* This constructor makes an "uninitialized" object. Call Reset to set the
* central latitude and longitude, prior to calling Forward and Reverse.
**********************************************************************/
explicit CassiniSoldner(const Geodesic& earth = Geodesic::WGS84());
/**
* Constructor for CassiniSoldner specifying a center point.
*
* @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] earth the Geodesic object to use for geodesic calculations.
* By default this uses the WGS84 ellipsoid.
*
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
CassiniSoldner(real lat0, real lon0,
const Geodesic& earth = Geodesic::WGS84());
/**
* Set the central point of the projection
*
* @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees).
*
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
void Reset(real lat0, real lon0);
/**
* Forward projection, from geographic to Cassini-Soldner.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] azi azimuth of easting direction at point (degrees).
* @param[out] rk reciprocal of azimuthal northing scale at point.
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;]. A call to
* Forward followed by a call to Reverse will return the original (\e lat,
* \e lon) (to within roundoff). The routine does nothing if the origin
* has not been set.
**********************************************************************/
void Forward(real lat, real lon,
real& x, real& y, real& azi, real& rk) const;
/**
* Reverse projection, from Cassini-Soldner to geographic.
*
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] azi azimuth of easting direction at point (degrees).
* @param[out] rk reciprocal of azimuthal northing scale at point.
*
* A call to Reverse followed by a call to Forward will return the original
* (\e x, \e y) (to within roundoff), provided that \e x and \e y are
* sufficiently small not to "wrap around" the earth. The routine does
* nothing if the origin has not been set.
**********************************************************************/
void Reverse(real x, real y,
real& lat, real& lon, real& azi, real& rk) const;
/**
* CassiniSoldner::Forward without returning the azimuth and scale.
**********************************************************************/
void Forward(real lat, real lon,
real& x, real& y) const {
real azi, rk;
Forward(lat, lon, x, y, azi, rk);
}
/**
* CassiniSoldner::Reverse without returning the azimuth and scale.
**********************************************************************/
void Reverse(real x, real y,
real& lat, real& lon) const {
real azi, rk;
Reverse(x, y, lat, lon, azi, rk);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _meridian.Init(); }
/**
* @return \e lat0 the latitude of origin (degrees).
**********************************************************************/
Math::real LatitudeOrigin() const
{ return _meridian.Latitude(); }
/**
* @return \e lon0 the longitude of origin (degrees).
**********************************************************************/
Math::real LongitudeOrigin() const
{ return _meridian.Longitude(); }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_CASSINISOLDNER_HPP

195
external/include/GeographicLib/CircularEngine.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,195 @@
/**
* \file CircularEngine.hpp
* \brief Header for GeographicLib::CircularEngine class
*
* Copyright (c) Charles Karney (2011-2015) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_CIRCULARENGINE_HPP)
#define GEOGRAPHICLIB_CIRCULARENGINE_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/SphericalEngine.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
/**
* \brief Spherical harmonic sums for a circle
*
* The class is a companion to SphericalEngine. If the results of a
* spherical harmonic sum are needed for several points on a circle of
* constant latitude \e lat and height \e h, then SphericalEngine::Circle can
* compute the inner sum, which is independent of longitude \e lon, and
* produce a CircularEngine object. CircularEngine::operator()() can
* then be used to perform the outer sum for particular vales of \e lon.
* This can lead to substantial improvements in computational speed for high
* degree sum (approximately by a factor of \e N / 2 where \e N is the
* maximum degree).
*
* CircularEngine is tightly linked to the internals of SphericalEngine. For
* that reason, the constructor for this class is private. Use
* SphericalHarmonic::Circle, SphericalHarmonic1::Circle, and
* SphericalHarmonic2::Circle to create instances of this class.
*
* CircularEngine stores the coefficients needed to allow the summation over
* order to be performed in 2 or 6 vectors of length \e M + 1 (depending on
* whether gradients are to be calculated). For this reason the constructor
* may throw a std::bad_alloc exception.
*
* Example of use:
* \include example-CircularEngine.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT CircularEngine {
private:
typedef Math::real real;
enum normalization {
FULL = SphericalEngine::FULL,
SCHMIDT = SphericalEngine::SCHMIDT,
};
int _M;
bool _gradp;
unsigned _norm;
real _a, _r, _u, _t;
std::vector<real> _wc, _ws, _wrc, _wrs, _wtc, _wts;
real _q, _uq, _uq2;
Math::real Value(bool gradp, real sl, real cl,
real& gradx, real& grady, real& gradz) const;
friend class SphericalEngine;
CircularEngine(int M, bool gradp, unsigned norm,
real a, real r, real u, real t)
: _M(M)
, _gradp(gradp)
, _norm(norm)
, _a(a)
, _r(r)
, _u(u)
, _t(t)
, _wc(std::vector<real>(_M + 1, 0))
, _ws(std::vector<real>(_M + 1, 0))
, _wrc(std::vector<real>(_gradp ? _M + 1 : 0, 0))
, _wrs(std::vector<real>(_gradp ? _M + 1 : 0, 0))
, _wtc(std::vector<real>(_gradp ? _M + 1 : 0, 0))
, _wts(std::vector<real>(_gradp ? _M + 1 : 0, 0))
{
_q = _a / _r;
_uq = _u * _q;
_uq2 = Math::sq(_uq);
}
void SetCoeff(int m, real wc, real ws)
{ _wc[m] = wc; _ws[m] = ws; }
void SetCoeff(int m, real wc, real ws,
real wrc, real wrs, real wtc, real wts) {
_wc[m] = wc; _ws[m] = ws;
if (_gradp) {
_wrc[m] = wrc; _wrs[m] = wrs;
_wtc[m] = wtc; _wts[m] = wts;
}
}
public:
/**
* A default constructor. CircularEngine::operator()() on the resulting
* object returns zero. The resulting object can be assigned to the result
* of SphericalHarmonic::Circle.
**********************************************************************/
CircularEngine()
: _M(-1)
, _gradp(true)
, _u(0)
, _t(1)
{}
/**
* Evaluate the sum for a particular longitude given in terms of its
* sine and cosine.
*
* @param[in] sinlon the sine of the longitude.
* @param[in] coslon the cosine of the longitude.
* @return \e V the value of the sum.
*
* The arguments must satisfy <i>sinlon</i><sup>2</sup> +
* <i>coslon</i><sup>2</sup> = 1.
**********************************************************************/
Math::real operator()(real sinlon, real coslon) const {
real dummy;
return Value(false, sinlon, coslon, dummy, dummy, dummy);
}
/**
* Evaluate the sum for a particular longitude.
*
* @param[in] lon the longitude (degrees).
* @return \e V the value of the sum.
**********************************************************************/
Math::real operator()(real lon) const {
real sinlon, coslon;
Math::sincosd(lon, sinlon, coslon);
return (*this)(sinlon, coslon);
}
/**
* Evaluate the sum and its gradient for a particular longitude given in
* terms of its sine and cosine.
*
* @param[in] sinlon the sine of the longitude.
* @param[in] coslon the cosine of the longitude.
* @param[out] gradx \e x component of the gradient.
* @param[out] grady \e y component of the gradient.
* @param[out] gradz \e z component of the gradient.
* @return \e V the value of the sum.
*
* The gradients will only be computed if the CircularEngine object was
* created with this capability (e.g., via \e gradp = true in
* SphericalHarmonic::Circle). If not, \e gradx, etc., will not be
* touched. The arguments must satisfy <i>sinlon</i><sup>2</sup> +
* <i>coslon</i><sup>2</sup> = 1.
**********************************************************************/
Math::real operator()(real sinlon, real coslon,
real& gradx, real& grady, real& gradz) const {
return Value(true, sinlon, coslon, gradx, grady, gradz);
}
/**
* Evaluate the sum and its gradient for a particular longitude.
*
* @param[in] lon the longitude (degrees).
* @param[out] gradx \e x component of the gradient.
* @param[out] grady \e y component of the gradient.
* @param[out] gradz \e z component of the gradient.
* @return \e V the value of the sum.
*
* The gradients will only be computed if the CircularEngine object was
* created with this capability (e.g., via \e gradp = true in
* SphericalHarmonic::Circle). If not, \e gradx, etc., will not be
* touched.
**********************************************************************/
Math::real operator()(real lon,
real& gradx, real& grady, real& gradz) const {
real sinlon, coslon;
Math::sincosd(lon, sinlon, coslon);
return (*this)(sinlon, coslon, gradx, grady, gradz);
}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_CIRCULARENGINE_HPP

25
external/include/GeographicLib/Config.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,25 @@
#define GEOGRAPHICLIB_VERSION_STRING "1.52"
#define GEOGRAPHICLIB_VERSION_MAJOR 1
#define GEOGRAPHICLIB_VERSION_MINOR 52
#define GEOGRAPHICLIB_VERSION_PATCH 0
#define GEOGRAPHICLIB_DATA "C:/Users/sven/Documents/Visual Studio 2019/Projects/TST/install"
// These are macros which affect the building of the library
#define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0
#define GEOGRAPHICLIB_WORDS_BIGENDIAN 0
#define GEOGRAPHICLIB_PRECISION 1
// Specify whether GeographicLib is a shared or static library. When compiling
// under Visual Studio it is necessary to specify whether GeographicLib is a
// shared library. This is done with the macro GEOGRAPHICLIB_SHARED_LIB, which
// cmake will correctly define as 0 or 1 when only one type of library is in
// the package. If both shared and static libraries are available,
// GEOGRAPHICLIB_SHARED_LIB is set to 2 which triggers a preprocessor error in
// Constants.hpp. In this case, the appropriate value (0 or 1) for
// GEOGRAPHICLIB_SHARED_LIB must be specified when compiling any program that
// includes GeographicLib headers. This is done automatically if GeographicLib
// and the user's code were built with cmake version 2.8.11 (which introduced
// the command target_compile_definitions) or later.
#if !defined(GEOGRAPHICLIB_SHARED_LIB)
#define GEOGRAPHICLIB_SHARED_LIB 0
#endif

329
external/include/GeographicLib/Constants.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,329 @@
/**
* \file Constants.hpp
* \brief Header for GeographicLib::Constants class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_CONSTANTS_HPP)
#define GEOGRAPHICLIB_CONSTANTS_HPP 1
#include <GeographicLib/Config.h>
/**
* @relates GeographicLib::Constants
* Pack the version components into a single integer. Users should not rely on
* this particular packing of the components of the version number; see the
* documentation for GEOGRAPHICLIB_VERSION, below.
**********************************************************************/
#define GEOGRAPHICLIB_VERSION_NUM(a,b,c) ((((a) * 10000 + (b)) * 100) + (c))
/**
* @relates GeographicLib::Constants
* The version of GeographicLib as a single integer, packed as MMmmmmpp where
* MM is the major version, mmmm is the minor version, and pp is the patch
* level. Users should not rely on this particular packing of the components
* of the version number. Instead they should use a test such as \code
#if GEOGRAPHICLIB_VERSION >= GEOGRAPHICLIB_VERSION_NUM(1,37,0)
...
#endif
* \endcode
**********************************************************************/
#define GEOGRAPHICLIB_VERSION \
GEOGRAPHICLIB_VERSION_NUM(GEOGRAPHICLIB_VERSION_MAJOR, \
GEOGRAPHICLIB_VERSION_MINOR, \
GEOGRAPHICLIB_VERSION_PATCH)
// For reference, here is a table of Visual Studio and _MSC_VER
// correspondences:
//
// _MSC_VER Visual Studio
// 1100 vc5
// 1200 vc6
// 1300 vc7
// 1310 vc7.1 (2003)
// 1400 vc8 (2005)
// 1500 vc9 (2008)
// 1600 vc10 (2010)
// 1700 vc11 (2012)
// 1800 vc12 (2013)
// 1900 vc14 (2015) First version of VS to include enough C++11 support
// 191[0-9] vc15 (2017)
// 192[0-9] vc16 (2019)
#if defined(_MSC_VER) && defined(GEOGRAPHICLIB_SHARED_LIB) && \
GEOGRAPHICLIB_SHARED_LIB
# if GEOGRAPHICLIB_SHARED_LIB > 1
# error GEOGRAPHICLIB_SHARED_LIB must be 0 or 1
# elif defined(GeographicLib_SHARED_EXPORTS)
# define GEOGRAPHICLIB_EXPORT __declspec(dllexport)
# else
# define GEOGRAPHICLIB_EXPORT __declspec(dllimport)
# endif
#else
# define GEOGRAPHICLIB_EXPORT
#endif
// Use GEOGRAPHICLIB_DEPRECATED to mark functions, types or variables as
// deprecated. Code inspired by Apache Subversion's svn_types.h file (via
// MPFR).
#if defined(__GNUC__)
# if __GNUC__ > 4
# define GEOGRAPHICLIB_DEPRECATED(msg) __attribute__((deprecated(msg)))
# else
# define GEOGRAPHICLIB_DEPRECATED(msg) __attribute__((deprecated))
# endif
#elif defined(_MSC_VER) && _MSC_VER >= 1300
# define GEOGRAPHICLIB_DEPRECATED(msg) __declspec(deprecated(msg))
#else
# define GEOGRAPHICLIB_DEPRECATED(msg)
#endif
#include <stdexcept>
#include <string>
#include <GeographicLib/Math.hpp>
/**
* \brief Namespace for %GeographicLib
*
* All of %GeographicLib is defined within the GeographicLib namespace. In
* addition all the header files are included via %GeographicLib/Class.hpp.
* This minimizes the likelihood of conflicts with other packages.
**********************************************************************/
namespace GeographicLib {
/**
* \brief %Constants needed by %GeographicLib
*
* Define constants specifying the WGS84 ellipsoid, the UTM and UPS
* projections, and various unit conversions.
*
* Example of use:
* \include example-Constants.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Constants {
private:
typedef Math::real real;
Constants(); // Disable constructor
public:
/**
* A synonym for Math::degree<real>().
**********************************************************************/
static Math::real degree() { return Math::degree(); }
/**
* @return the number of radians in an arcminute.
**********************************************************************/
static Math::real arcminute()
{ return Math::degree() / 60; }
/**
* @return the number of radians in an arcsecond.
**********************************************************************/
static Math::real arcsecond()
{ return Math::degree() / 3600; }
/** \name Ellipsoid parameters
**********************************************************************/
///@{
/**
* @tparam T the type of the returned value.
* @return the equatorial radius of WGS84 ellipsoid (6378137 m).
**********************************************************************/
template<typename T = real> static T WGS84_a()
{ return 6378137 * meter<T>(); }
/**
* @tparam T the type of the returned value.
* @return the flattening of WGS84 ellipsoid (1/298.257223563).
**********************************************************************/
template<typename T = real> static T WGS84_f() {
// Evaluating this as 1000000000 / T(298257223563LL) reduces the
// round-off error by about 10%. However, expressing the flattening as
// 1/298.257223563 is well ingrained.
return 1 / ( T(298257223563LL) / 1000000000 );
}
/**
* @tparam T the type of the returned value.
* @return the gravitational constant of the WGS84 ellipsoid, \e GM, in
* m<sup>3</sup> s<sup>&minus;2</sup>.
**********************************************************************/
template<typename T = real> static T WGS84_GM()
{ return T(3986004) * 100000000 + 41800000; }
/**
* @tparam T the type of the returned value.
* @return the angular velocity of the WGS84 ellipsoid, &omega;, in rad
* s<sup>&minus;1</sup>.
**********************************************************************/
template<typename T = real> static T WGS84_omega()
{ return 7292115 / (T(1000000) * 100000); }
/**
* @tparam T the type of the returned value.
* @return the equatorial radius of GRS80 ellipsoid, \e a, in m.
**********************************************************************/
template<typename T = real> static T GRS80_a()
{ return 6378137 * meter<T>(); }
/**
* @tparam T the type of the returned value.
* @return the gravitational constant of the GRS80 ellipsoid, \e GM, in
* m<sup>3</sup> s<sup>&minus;2</sup>.
**********************************************************************/
template<typename T = real> static T GRS80_GM()
{ return T(3986005) * 100000000; }
/**
* @tparam T the type of the returned value.
* @return the angular velocity of the GRS80 ellipsoid, &omega;, in rad
* s<sup>&minus;1</sup>.
*
* This is about 2 &pi; 366.25 / (365.25 &times; 24 &times; 3600) rad
* s<sup>&minus;1</sup>. 365.25 is the number of days in a Julian year and
* 365.35/366.25 converts from solar days to sidereal days. Using the
* number of days in a Gregorian year (365.2425) results in a worse
* approximation (because the Gregorian year includes the precession of the
* earth's axis).
**********************************************************************/
template<typename T = real> static T GRS80_omega()
{ return 7292115 / (T(1000000) * 100000); }
/**
* @tparam T the type of the returned value.
* @return the dynamical form factor of the GRS80 ellipsoid,
* <i>J</i><sub>2</sub>.
**********************************************************************/
template<typename T = real> static T GRS80_J2()
{ return T(108263) / 100000000; }
/**
* @tparam T the type of the returned value.
* @return the central scale factor for UTM (0.9996).
**********************************************************************/
template<typename T = real> static T UTM_k0()
{return T(9996) / 10000; }
/**
* @tparam T the type of the returned value.
* @return the central scale factor for UPS (0.994).
**********************************************************************/
template<typename T = real> static T UPS_k0()
{ return T(994) / 1000; }
///@}
/** \name SI units
**********************************************************************/
///@{
/**
* @tparam T the type of the returned value.
* @return the number of meters in a meter.
*
* This is unity, but this lets the internal system of units be changed if
* necessary.
**********************************************************************/
template<typename T = real> static T meter() { return T(1); }
/**
* @return the number of meters in a kilometer.
**********************************************************************/
static Math::real kilometer()
{ return 1000 * meter<real>(); }
/**
* @return the number of meters in a nautical mile (approximately 1 arc
* minute)
**********************************************************************/
static Math::real nauticalmile()
{ return 1852 * meter<real>(); }
/**
* @tparam T the type of the returned value.
* @return the number of square meters in a square meter.
*
* This is unity, but this lets the internal system of units be changed if
* necessary.
**********************************************************************/
template<typename T = real> static T square_meter()
{ return meter<T>() * meter<T>(); }
/**
* @return the number of square meters in a hectare.
**********************************************************************/
static Math::real hectare()
{ return 10000 * square_meter<real>(); }
/**
* @return the number of square meters in a square kilometer.
**********************************************************************/
static Math::real square_kilometer()
{ return kilometer() * kilometer(); }
/**
* @return the number of square meters in a square nautical mile.
**********************************************************************/
static Math::real square_nauticalmile()
{ return nauticalmile() * nauticalmile(); }
///@}
/** \name Anachronistic British units
**********************************************************************/
///@{
/**
* @return the number of meters in an international foot.
**********************************************************************/
static Math::real foot()
{ return real(254 * 12) / 10000 * meter<real>(); }
/**
* @return the number of meters in a yard.
**********************************************************************/
static Math::real yard() { return 3 * foot(); }
/**
* @return the number of meters in a fathom.
**********************************************************************/
static Math::real fathom() { return 2 * yard(); }
/**
* @return the number of meters in a chain.
**********************************************************************/
static Math::real chain() { return 22 * yard(); }
/**
* @return the number of meters in a furlong.
**********************************************************************/
static Math::real furlong() { return 10 * chain(); }
/**
* @return the number of meters in a statute mile.
**********************************************************************/
static Math::real mile() { return 8 * furlong(); }
/**
* @return the number of square meters in an acre.
**********************************************************************/
static Math::real acre() { return chain() * furlong(); }
/**
* @return the number of square meters in a square statute mile.
**********************************************************************/
static Math::real square_mile() { return mile() * mile(); }
///@}
/** \name Anachronistic US units
**********************************************************************/
///@{
/**
* @return the number of meters in a US survey foot.
**********************************************************************/
static Math::real surveyfoot()
{ return real(1200) / 3937 * meter<real>(); }
///@}
};
/**
* \brief Exception handling for %GeographicLib
*
* A class to handle exceptions. It's derived from std::runtime_error so it
* can be caught by the usual catch clauses.
*
* Example of use:
* \include example-GeographicErr.cpp
**********************************************************************/
class GeographicErr : public std::runtime_error {
public:
/**
* Constructor
*
* @param[in] msg a string message, which is accessible in the catch
* clause via what().
**********************************************************************/
GeographicErr(const std::string& msg) : std::runtime_error(msg) {}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_CONSTANTS_HPP

405
external/include/GeographicLib/DMS.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,405 @@
/**
* \file DMS.hpp
* \brief Header for GeographicLib::DMS class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_DMS_HPP)
#define GEOGRAPHICLIB_DMS_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/Utility.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector and constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4251 4127)
#endif
namespace GeographicLib {
/**
* \brief Convert between degrees and the %DMS representation
*
* Parse a string representing degree, minutes, and seconds and return the
* angle in degrees and format an angle in degrees as degree, minutes, and
* seconds. In addition, handle NANs and infinities on input and output.
*
* Example of use:
* \include example-DMS.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT DMS {
public:
/**
* Indicator for presence of hemisphere indicator (N/S/E/W) on latitudes
* and longitudes.
**********************************************************************/
enum flag {
/**
* No indicator present.
* @hideinitializer
**********************************************************************/
NONE = 0,
/**
* Latitude indicator (N/S) present.
* @hideinitializer
**********************************************************************/
LATITUDE = 1,
/**
* Longitude indicator (E/W) present.
* @hideinitializer
**********************************************************************/
LONGITUDE = 2,
/**
* Used in Encode to indicate output of an azimuth in [000, 360) with no
* letter indicator.
* @hideinitializer
**********************************************************************/
AZIMUTH = 3,
/**
* Used in Encode to indicate output of a plain number.
* @hideinitializer
**********************************************************************/
NUMBER = 4,
};
/**
* Indicator for trailing units on an angle.
**********************************************************************/
enum component {
/**
* Trailing unit is degrees.
* @hideinitializer
**********************************************************************/
DEGREE = 0,
/**
* Trailing unit is arc minutes.
* @hideinitializer
**********************************************************************/
MINUTE = 1,
/**
* Trailing unit is arc seconds.
* @hideinitializer
**********************************************************************/
SECOND = 2,
};
private:
typedef Math::real real;
// Replace all occurrences of pat by c. If c is NULL remove pat.
static void replace(std::string& s, const std::string& pat, char c) {
std::string::size_type p = 0;
int count = c ? 1 : 0;
while (true) {
p = s.find(pat, p);
if (p == std::string::npos)
break;
s.replace(p, pat.length(), count, c);
}
}
static const char* const hemispheres_;
static const char* const signs_;
static const char* const digits_;
static const char* const dmsindicators_;
static const char* const components_[3];
static Math::real NumMatch(const std::string& s);
static Math::real InternalDecode(const std::string& dmsa, flag& ind);
DMS(); // Disable constructor
public:
/**
* Convert a string in DMS to an angle.
*
* @param[in] dms string input.
* @param[out] ind a DMS::flag value signaling the presence of a
* hemisphere indicator.
* @exception GeographicErr if \e dms is malformed (see below).
* @return angle (degrees).
*
* Degrees, minutes, and seconds are indicated by the characters d, '
* (single quote), &quot; (double quote), and these components may only be
* given in this order. Any (but not all) components may be omitted and
* other symbols (e.g., the &deg; symbol for degrees and the unicode prime
* and double prime symbols for minutes and seconds) may be substituted;
* two single quotes can be used instead of &quot;. The last component
* indicator may be omitted and is assumed to be the next smallest unit
* (thus 33d10 is interpreted as 33d10'). The final component may be a
* decimal fraction but the non-final components must be integers. Instead
* of using d, ', and &quot; to indicate degrees, minutes, and seconds, :
* (colon) may be used to <i>separate</i> these components (numbers must
* appear before and after each colon); thus 50d30'10.3&quot; may be
* written as 50:30:10.3, 5.5' may be written 0:5.5, and so on. The
* integer parts of the minutes and seconds components must be less
* than 60. A single leading sign is permitted. A hemisphere designator
* (N, E, W, S) may be added to the beginning or end of the string. The
* result is multiplied by the implied sign of the hemisphere designator
* (negative for S and W). In addition \e ind is set to DMS::LATITUDE if N
* or S is present, to DMS::LONGITUDE if E or W is present, and to
* DMS::NONE otherwise. Throws an error on a malformed string. No check
* is performed on the range of the result. Examples of legal and illegal
* strings are
* - <i>LEGAL</i> (all the entries on each line are equivalent)
* - -20.51125, 20d30'40.5&quot;S, -20&deg;30'40.5, -20d30.675,
* N-20d30'40.5&quot;, -20:30:40.5
* - 4d0'9, 4d9&quot;, 4d9'', 4:0:9, 004:00:09, 4.0025, 4.0025d, 4d0.15,
* 04:.15
* - 4:59.99999999999999, 4:60.0, 4:59:59.9999999999999, 4:59:60.0, 5
* - <i>ILLEGAL</i> (the exception thrown explains the problem)
* - 4d5&quot;4', 4::5, 4:5:, :4:5, 4d4.5'4&quot;, -N20.5, 1.8e2d, 4:60,
* 4:59:60
*
* The decoding operation can also perform addition and subtraction
* operations. If the string includes <i>internal</i> signs (i.e., not at
* the beginning nor immediately after an initial hemisphere designator),
* then the string is split immediately before such signs and each piece is
* decoded according to the above rules and the results added; thus
* <code>S3-2.5+4.1N</code> is parsed as the sum of <code>S3</code>,
* <code>-2.5</code>, <code>+4.1N</code>. Any piece can include a
* hemisphere designator; however, if multiple designators are given, they
* must compatible; e.g., you cannot mix N and E. In addition, the
* designator can appear at the beginning or end of the first piece, but
* must be at the end of all subsequent pieces (a hemisphere designator is
* not allowed after the initial sign). Examples of legal and illegal
* combinations are
* - <i>LEGAL</i> (these are all equivalent)
* - 070:00:45, 70:01:15W+0:0.5, 70:01:15W-0:0:30W, W70:01:15+0:0:30E
* - <i>ILLEGAL</i> (the exception thrown explains the problem)
* - 70:01:15W+0:0:15N, W70:01:15+W0:0:15
*
* \warning The "exponential" notation is not recognized. Thus
* <code>7.0E1</code> is illegal, while <code>7.0E+1</code> is parsed as
* <code>(7.0E) + (+1)</code>, yielding the same result as
* <code>8.0E</code>.
*
* \note At present, all the string handling in the C++ implementation of
* %GeographicLib is with 8-bit characters. The support for unicode
* symbols for degrees, minutes, and seconds is therefore via the
* <a href="https://en.wikipedia.org/wiki/UTF-8">UTF-8</a> encoding. (The
* JavaScript implementation of this class uses unicode natively, of
* course.)
*
* Here is the list of Unicode symbols supported for degrees, minutes,
* seconds, and the plus and minus signs; various symbols denoting variants
* of a space, which may separate the components of a DMS string, are
* removed:
* - degrees:
* - d, D lower and upper case letters
* - U+00b0 degree symbol (&deg;)
* - U+00ba masculine ordinal indicator (&ordm;)
* - U+2070 superscript zero (⁰)
* - U+02da ring above (˚)
* - U+2218 compose function (∘)
* - * the <a href="https://grid.nga.mil">GRiD</a> symbol for degrees
* - minutes:
* - ' apostrophe
* - ` grave accent
* - U+2032 prime (&prime;)
* - U+2035 back prime ()
* - U+00b4 acute accent (&acute;)
* - U+2018 left single quote (&lsquo;)
* - U+2019 right single quote (&rsquo;)
* - U+201b reversed-9 single quote ()
* - U+02b9 modifier letter prime (ʹ)
* - U+02ca modifier letter acute accent (ˊ)
* - U+02cb modifier letter grave accent (ˋ)
* - seconds:
* - &quot; quotation mark
* - U+2033 double prime (&Prime;)
* - U+2036 reversed double prime (‶)
* + U+02dd double acute accent (˝)
* - U+201c left double quote (&ldquo;)
* - U+201d right double quote (&rdquo;)
* - U+201f reversed-9 double quote (‟)
* - U+02ba modifier letter double prime (ʺ)
* - '&nbsp;' any two consecutive symbols for minutes
* - plus sign:
* - + plus
* - U+2795 heavy plus ()
* - U+2064 invisible plus (||)
* - minus sign:
* - - hyphen
* - U+2010 dash ()
* - U+2011 non-breaking hyphen ()
* - U+2013 en dash (&ndash;)
* - U+2014 em dash (&mdash;)
* - U+2212 minus sign (&minus;)
* - U+2796 heavy minus ()
* - ignored spaces:
* - U+00a0 non-breaking space
* - U+2007 figure space (||)
* - U+2009 thin space (|&thinsp;|)
* - U+200a hair space (||)
* - U+200b invisible space (||)
* - U+202f narrow space (||)
* - U+2063 invisible separator (||)
* .
* The codes with a leading zero byte, e.g., U+00b0, are accepted in their
* UTF-8 coded form 0xc2 0xb0 and as a single byte 0xb0.
**********************************************************************/
static Math::real Decode(const std::string& dms, flag& ind);
/**
* Convert DMS to an angle.
*
* @param[in] d degrees.
* @param[in] m arc minutes.
* @param[in] s arc seconds.
* @return angle (degrees)
*
* This does not propagate the sign on \e d to the other components,
* so -3d20' would need to be represented as - DMS::Decode(3.0, 20.0) or
* DMS::Decode(-3.0, -20.0).
**********************************************************************/
static Math::real Decode(real d, real m = 0, real s = 0)
{ return d + (m + s / 60) / 60; }
/**
* Convert a pair of strings to latitude and longitude.
*
* @param[in] dmsa first string.
* @param[in] dmsb second string.
* @param[out] lat latitude (degrees).
* @param[out] lon longitude (degrees).
* @param[in] longfirst if true assume longitude is given before latitude
* in the absence of hemisphere designators (default false).
* @exception GeographicErr if \e dmsa or \e dmsb is malformed.
* @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
* latitudes.
* @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
* longitudes.
* @exception GeographicErr if decoded latitude is not in [&minus;90&deg;,
* 90&deg;].
*
* By default, the \e lat (resp., \e lon) is assigned to the results of
* decoding \e dmsa (resp., \e dmsb). However this is overridden if either
* \e dmsa or \e dmsb contain a latitude or longitude hemisphere designator
* (N, S, E, W). If an exception is thrown, \e lat and \e lon are
* unchanged.
**********************************************************************/
static void DecodeLatLon(const std::string& dmsa, const std::string& dmsb,
real& lat, real& lon,
bool longfirst = false);
/**
* Convert a string to an angle in degrees.
*
* @param[in] angstr input string.
* @exception GeographicErr if \e angstr is malformed.
* @exception GeographicErr if \e angstr includes a hemisphere designator.
* @return angle (degrees)
*
* No hemisphere designator is allowed and no check is done on the range of
* the result.
**********************************************************************/
static Math::real DecodeAngle(const std::string& angstr);
/**
* Convert a string to an azimuth in degrees.
*
* @param[in] azistr input string.
* @exception GeographicErr if \e azistr is malformed.
* @exception GeographicErr if \e azistr includes a N/S designator.
* @return azimuth (degrees) reduced to the range [&minus;180&deg;,
* 180&deg;].
*
* A hemisphere designator E/W can be used; the result is multiplied by
* &minus;1 if W is present.
**********************************************************************/
static Math::real DecodeAzimuth(const std::string& azistr);
/**
* Convert angle (in degrees) into a DMS string (using d, ', and &quot;).
*
* @param[in] angle input angle (degrees)
* @param[in] trailing DMS::component value indicating the trailing units
* of the string (this component is given as a decimal number if
* necessary).
* @param[in] prec the number of digits after the decimal point for the
* trailing component.
* @param[in] ind DMS::flag value indicating additional formatting.
* @param[in] dmssep if non-null, use as the DMS separator character
* (instead of d, ', &quot; delimiters).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return formatted string
*
* The interpretation of \e ind is as follows:
* - ind == DMS::NONE, signed result no leading zeros on degrees except in
* the units place, e.g., -8d03'.
* - ind == DMS::LATITUDE, trailing N or S hemisphere designator, no sign,
* pad degrees to 2 digits, e.g., 08d03'S.
* - ind == DMS::LONGITUDE, trailing E or W hemisphere designator, no
* sign, pad degrees to 3 digits, e.g., 008d03'W.
* - ind == DMS::AZIMUTH, convert to the range [0, 360&deg;), no
* sign, pad degrees to 3 digits, e.g., 351d57'.
* .
* The integer parts of the minutes and seconds components are always given
* with 2 digits.
**********************************************************************/
static std::string Encode(real angle, component trailing, unsigned prec,
flag ind = NONE, char dmssep = char(0));
/**
* Convert angle into a DMS string (using d, ', and &quot;) selecting the
* trailing component based on the precision.
*
* @param[in] angle input angle (degrees)
* @param[in] prec the precision relative to 1 degree.
* @param[in] ind DMS::flag value indicated additional formatting.
* @param[in] dmssep if non-null, use as the DMS separator character
* (instead of d, ', &quot; delimiters).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return formatted string
*
* \e prec indicates the precision relative to 1 degree, e.g., \e prec = 3
* gives a result accurate to 0.1' and \e prec = 4 gives a result accurate
* to 1&quot;. \e ind is interpreted as in DMS::Encode with the additional
* facility that DMS::NUMBER represents \e angle as a number in fixed
* format with precision \e prec.
**********************************************************************/
static std::string Encode(real angle, unsigned prec, flag ind = NONE,
char dmssep = char(0)) {
return ind == NUMBER ? Utility::str(angle, int(prec)) :
Encode(angle,
prec < 2 ? DEGREE : (prec < 4 ? MINUTE : SECOND),
prec < 2 ? prec : (prec < 4 ? prec - 2 : prec - 4),
ind, dmssep);
}
/**
* Split angle into degrees and minutes
*
* @param[in] ang angle (degrees)
* @param[out] d degrees (an integer returned as a real)
* @param[out] m arc minutes.
**********************************************************************/
static void Encode(real ang, real& d, real& m) {
d = int(ang); m = 60 * (ang - d);
}
/**
* Split angle into degrees and minutes and seconds.
*
* @param[in] ang angle (degrees)
* @param[out] d degrees (an integer returned as a real)
* @param[out] m arc minutes (an integer returned as a real)
* @param[out] s arc seconds.
**********************************************************************/
static void Encode(real ang, real& d, real& m, real& s) {
d = int(ang); ang = 60 * (ang - d);
m = int(ang); s = 60 * (ang - m);
}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_DMS_HPP

542
external/include/GeographicLib/Ellipsoid.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,542 @@
/**
* \file Ellipsoid.hpp
* \brief Header for GeographicLib::Ellipsoid class
*
* Copyright (c) Charles Karney (2012-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_ELLIPSOID_HPP)
#define GEOGRAPHICLIB_ELLIPSOID_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/TransverseMercator.hpp>
#include <GeographicLib/EllipticFunction.hpp>
#include <GeographicLib/AlbersEqualArea.hpp>
namespace GeographicLib {
/**
* \brief Properties of an ellipsoid
*
* This class returns various properties of the ellipsoid and converts
* between various types of latitudes. The latitude conversions are also
* possible using the various projections supported by %GeographicLib; but
* Ellipsoid provides more direct access (sometimes using private functions
* of the projection classes). Ellipsoid::RectifyingLatitude,
* Ellipsoid::InverseRectifyingLatitude, and Ellipsoid::MeridianDistance
* provide functionality which can be provided by the Geodesic class.
* However Geodesic uses a series approximation (valid for abs \e f < 1/150),
* whereas Ellipsoid computes these quantities using EllipticFunction which
* provides accurate results even when \e f is large. Use of this class
* should be limited to &minus;3 < \e f < 3/4 (i.e., 1/4 < b/a < 4).
*
* Example of use:
* \include example-Ellipsoid.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Ellipsoid {
private:
typedef Math::real real;
static const int numit_ = 10;
real stol_;
real _a, _f, _f1, _f12, _e2, _es, _e12, _n, _b;
TransverseMercator _tm;
EllipticFunction _ell;
AlbersEqualArea _au;
// These are the alpha and beta coefficients in the Krueger series from
// TransverseMercator. Thy are used by RhumbSolve to compute
// (psi2-psi1)/(mu2-mu1).
const Math::real* ConformalToRectifyingCoeffs() const { return _tm._alp; }
const Math::real* RectifyingToConformalCoeffs() const { return _tm._bet; }
friend class Rhumb; friend class RhumbLine;
public:
/** \name Constructor
**********************************************************************/
///@{
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* positive.
**********************************************************************/
Ellipsoid(real a, real f);
///@}
/** \name %Ellipsoid dimensions.
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e b the polar semi-axis (meters).
**********************************************************************/
Math::real MinorRadius() const { return _b; }
/**
* @return \e L the distance between the equator and a pole along a
* meridian (meters). For a sphere \e L = (&pi;/2) \e a. The radius
* of a sphere with the same meridian length is \e L / (&pi;/2).
**********************************************************************/
Math::real QuarterMeridian() const;
/**
* @return \e A the total area of the ellipsoid (meters<sup>2</sup>). For
* a sphere \e A = 4&pi; <i>a</i><sup>2</sup>. The radius of a sphere
* with the same area is sqrt(\e A / (4&pi;)).
**********************************************************************/
Math::real Area() const;
/**
* @return \e V the total volume of the ellipsoid (meters<sup>3</sup>).
* For a sphere \e V = (4&pi; / 3) <i>a</i><sup>3</sup>. The radius of
* a sphere with the same volume is cbrt(\e V / (4&pi;/3)).
**********************************************************************/
Math::real Volume() const
{ return (4 * Math::pi()) * Math::sq(_a) * _b / 3; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/** \name %Ellipsoid shape
**********************************************************************/
///@{
/**
* @return \e f = (\e a &minus; \e b) / \e a, the flattening of the
* ellipsoid. This is the value used in the constructor. This is zero,
* positive, or negative for a sphere, oblate ellipsoid, or prolate
* ellipsoid.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return \e f ' = (\e a &minus; \e b) / \e b, the second flattening of
* the ellipsoid. This is zero, positive, or negative for a sphere,
* oblate ellipsoid, or prolate ellipsoid.
**********************************************************************/
Math::real SecondFlattening() const { return _f / (1 - _f); }
/**
* @return \e n = (\e a &minus; \e b) / (\e a + \e b), the third flattening
* of the ellipsoid. This is zero, positive, or negative for a sphere,
* oblate ellipsoid, or prolate ellipsoid.
**********************************************************************/
Math::real ThirdFlattening() const { return _n; }
/**
* @return <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity squared
* of the ellipsoid. This is zero, positive, or negative for a sphere,
* oblate ellipsoid, or prolate ellipsoid.
**********************************************************************/
Math::real EccentricitySq() const { return _e2; }
/**
* @return <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentricity
* squared of the ellipsoid. This is zero, positive, or negative for a
* sphere, oblate ellipsoid, or prolate ellipsoid.
**********************************************************************/
Math::real SecondEccentricitySq() const { return _e12; }
/**
* @return <i>e''</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / (<i>a</i><sup>2</sup> + <i>b</i><sup>2</sup>),
* the third eccentricity squared of the ellipsoid. This is zero,
* positive, or negative for a sphere, oblate ellipsoid, or prolate
* ellipsoid.
**********************************************************************/
Math::real ThirdEccentricitySq() const { return _e2 / (2 - _e2); }
///@}
/** \name Latitude conversion.
**********************************************************************/
///@{
/**
* @param[in] phi the geographic latitude (degrees).
* @return &beta; the parametric latitude (degrees).
*
* The geographic latitude, &phi;, is the angle between the equatorial
* plane and a vector normal to the surface of the ellipsoid.
*
* The parametric latitude (also called the reduced latitude), &beta;,
* allows the cartesian coordinated of a meridian to be expressed
* conveniently in parametric form as
* - \e R = \e a cos &beta;
* - \e Z = \e b sin &beta;
* .
* where \e a and \e b are the equatorial radius and the polar semi-axis.
* For a sphere &beta; = &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &beta; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real ParametricLatitude(real phi) const;
/**
* @param[in] beta the parametric latitude (degrees).
* @return &phi; the geographic latitude (degrees).
*
* &beta; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &phi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real InverseParametricLatitude(real beta) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &theta; the geocentric latitude (degrees).
*
* The geocentric latitude, &theta;, is the angle between the equatorial
* plane and a line between the center of the ellipsoid and a point on the
* ellipsoid. For a sphere &theta; = &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &theta; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real GeocentricLatitude(real phi) const;
/**
* @param[in] theta the geocentric latitude (degrees).
* @return &phi; the geographic latitude (degrees).
*
* &theta; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &phi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real InverseGeocentricLatitude(real theta) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &mu; the rectifying latitude (degrees).
*
* The rectifying latitude, &mu;, has the property that the distance along
* a meridian of the ellipsoid between two points with rectifying latitudes
* &mu;<sub>1</sub> and &mu;<sub>2</sub> is equal to
* (&mu;<sub>2</sub> - &mu;<sub>1</sub>) \e L / 90&deg;,
* where \e L = QuarterMeridian(). For a sphere &mu; = &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &mu; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real RectifyingLatitude(real phi) const;
/**
* @param[in] mu the rectifying latitude (degrees).
* @return &phi; the geographic latitude (degrees).
*
* &mu; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &phi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real InverseRectifyingLatitude(real mu) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &xi; the authalic latitude (degrees).
*
* The authalic latitude, &xi;, has the property that the area of the
* ellipsoid between two circles with authalic latitudes
* &xi;<sub>1</sub> and &xi;<sub>2</sub> is equal to (sin
* &xi;<sub>2</sub> - sin &xi;<sub>1</sub>) \e A / 2, where \e A
* = Area(). For a sphere &xi; = &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &xi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real AuthalicLatitude(real phi) const;
/**
* @param[in] xi the authalic latitude (degrees).
* @return &phi; the geographic latitude (degrees).
*
* &xi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &phi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real InverseAuthalicLatitude(real xi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &chi; the conformal latitude (degrees).
*
* The conformal latitude, &chi;, gives the mapping of the ellipsoid to a
* sphere which which is conformal (angles are preserved) and in which the
* equator of the ellipsoid maps to the equator of the sphere. For a
* sphere &chi; = &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &chi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real ConformalLatitude(real phi) const;
/**
* @param[in] chi the conformal latitude (degrees).
* @return &phi; the geographic latitude (degrees).
*
* &chi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold. The returned value
* &phi; lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real InverseConformalLatitude(real chi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &psi; the isometric latitude (degrees).
*
* The isometric latitude gives the mapping of the ellipsoid to a plane
* which which is conformal (angles are preserved) and in which the equator
* of the ellipsoid maps to a straight line of constant scale; this mapping
* defines the Mercator projection. For a sphere &psi; =
* sinh<sup>&minus;1</sup> tan &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the result is
* undefined if this condition does not hold. The value returned for &phi;
* = &plusmn;90&deg; is some (positive or negative) large but finite value,
* such that InverseIsometricLatitude returns the original value of &phi;.
**********************************************************************/
Math::real IsometricLatitude(real phi) const;
/**
* @param[in] psi the isometric latitude (degrees).
* @return &phi; the geographic latitude (degrees).
*
* The returned value &phi; lies in [&minus;90&deg;, 90&deg;]. For a
* sphere &phi; = tan<sup>&minus;1</sup> sinh &psi;.
**********************************************************************/
Math::real InverseIsometricLatitude(real psi) const;
///@}
/** \name Other quantities.
**********************************************************************/
///@{
/**
* @param[in] phi the geographic latitude (degrees).
* @return \e R = \e a cos &beta; the radius of a circle of latitude
* &phi; (meters). \e R (&pi;/180&deg;) gives meters per degree
* longitude measured along a circle of latitude.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold.
**********************************************************************/
Math::real CircleRadius(real phi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return \e Z = \e b sin &beta; the distance of a circle of latitude
* &phi; from the equator measured parallel to the ellipsoid axis
* (meters).
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold.
**********************************************************************/
Math::real CircleHeight(real phi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return \e s the distance along a meridian
* between the equator and a point of latitude &phi; (meters). \e s is
* given by \e s = &mu; \e L / 90&deg;, where \e L =
* QuarterMeridian()).
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold.
**********************************************************************/
Math::real MeridianDistance(real phi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &rho; the meridional radius of curvature of the ellipsoid at
* latitude &phi; (meters); this is the curvature of the meridian. \e
* rho is given by &rho; = (180&deg;/&pi;) d\e s / d&phi;,
* where \e s = MeridianDistance(); thus &rho; (&pi;/180&deg;)
* gives meters per degree latitude measured along a meridian.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold.
**********************************************************************/
Math::real MeridionalCurvatureRadius(real phi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @return &nu; the transverse radius of curvature of the ellipsoid at
* latitude &phi; (meters); this is the curvature of a curve on the
* ellipsoid which also lies in a plane perpendicular to the ellipsoid
* and to the meridian. &nu; is related to \e R = CircleRadius() by \e
* R = &nu; cos &phi;.
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the
* result is undefined if this condition does not hold.
**********************************************************************/
Math::real TransverseCurvatureRadius(real phi) const;
/**
* @param[in] phi the geographic latitude (degrees).
* @param[in] azi the angle between the meridian and the normal section
* (degrees).
* @return the radius of curvature of the ellipsoid in the normal
* section at latitude &phi; inclined at an angle \e azi to the
* meridian (meters).
*
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the result is
* undefined this condition does not hold.
**********************************************************************/
Math::real NormalCurvatureRadius(real phi, real azi) const;
///@}
/** \name Eccentricity conversions.
**********************************************************************/
///@{
/**
* @param[in] fp = \e f ' = (\e a &minus; \e b) / \e b, the second
* flattening.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening.
*
* \e f ' should lie in (&minus;1, &infin;).
* The returned value \e f lies in (&minus;&infin;, 1).
**********************************************************************/
static Math::real SecondFlatteningToFlattening(real fp)
{ return fp / (1 + fp); }
/**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return \e f ' = (\e a &minus; \e b) / \e b, the second flattening.
*
* \e f should lie in (&minus;&infin;, 1).
* The returned value \e f ' lies in (&minus;1, &infin;).
**********************************************************************/
static Math::real FlatteningToSecondFlattening(real f)
{ return f / (1 - f); }
/**
* @param[in] n = (\e a &minus; \e b) / (\e a + \e b), the third
* flattening.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening.
*
* \e n should lie in (&minus;1, 1).
* The returned value \e f lies in (&minus;&infin;, 1).
**********************************************************************/
static Math::real ThirdFlatteningToFlattening(real n)
{ return 2 * n / (1 + n); }
/**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return \e n = (\e a &minus; \e b) / (\e a + \e b), the third
* flattening.
*
* \e f should lie in (&minus;&infin;, 1).
* The returned value \e n lies in (&minus;1, 1).
**********************************************************************/
static Math::real FlatteningToThirdFlattening(real f)
{ return f / (2 - f); }
/**
* @param[in] e2 = <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity
* squared.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening.
*
* <i>e</i><sup>2</sup> should lie in (&minus;&infin;, 1).
* The returned value \e f lies in (&minus;&infin;, 1).
**********************************************************************/
static Math::real EccentricitySqToFlattening(real e2)
{ using std::sqrt; return e2 / (sqrt(1 - e2) + 1); }
/**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity
* squared.
*
* \e f should lie in (&minus;&infin;, 1).
* The returned value <i>e</i><sup>2</sup> lies in (&minus;&infin;, 1).
**********************************************************************/
static Math::real FlatteningToEccentricitySq(real f)
{ return f * (2 - f); }
/**
* @param[in] ep2 = <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentricity
* squared.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening.
*
* <i>e'</i> <sup>2</sup> should lie in (&minus;1, &infin;).
* The returned value \e f lies in (&minus;&infin;, 1).
**********************************************************************/
static Math::real SecondEccentricitySqToFlattening(real ep2)
{ using std::sqrt; return ep2 / (sqrt(1 + ep2) + 1 + ep2); }
/**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentricity
* squared.
*
* \e f should lie in (&minus;&infin;, 1).
* The returned value <i>e'</i> <sup>2</sup> lies in (&minus;1, &infin;).
**********************************************************************/
static Math::real FlatteningToSecondEccentricitySq(real f)
{ return f * (2 - f) / Math::sq(1 - f); }
/**
* @param[in] epp2 = <i>e''</i> <sup>2</sup> = (<i>a</i><sup>2</sup>
* &minus; <i>b</i><sup>2</sup>) / (<i>a</i><sup>2</sup> +
* <i>b</i><sup>2</sup>), the third eccentricity squared.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening.
*
* <i>e''</i> <sup>2</sup> should lie in (&minus;1, 1).
* The returned value \e f lies in (&minus;&infin;, 1).
**********************************************************************/
static Math::real ThirdEccentricitySqToFlattening(real epp2) {
using std::sqrt;
return 2 * epp2 / (sqrt((1 - epp2) * (1 + epp2)) + 1 + epp2);
}
/**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return <i>e''</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / (<i>a</i><sup>2</sup> + <i>b</i><sup>2</sup>),
* the third eccentricity squared.
*
* \e f should lie in (&minus;&infin;, 1).
* The returned value <i>e''</i> <sup>2</sup> lies in (&minus;1, 1).
**********************************************************************/
static Math::real FlatteningToThirdEccentricitySq(real f)
{ return f * (2 - f) / (1 + Math::sq(1 - f)); }
///@}
/**
* A global instantiation of Ellipsoid with the parameters for the WGS84
* ellipsoid.
**********************************************************************/
static const Ellipsoid& WGS84();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_ELLIPSOID_HPP

702
external/include/GeographicLib/EllipticFunction.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,702 @@
/**
* \file EllipticFunction.hpp
* \brief Header for GeographicLib::EllipticFunction class
*
* Copyright (c) Charles Karney (2008-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_ELLIPTICFUNCTION_HPP)
#define GEOGRAPHICLIB_ELLIPTICFUNCTION_HPP 1
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Elliptic integrals and functions
*
* This provides the elliptic functions and integrals needed for Ellipsoid,
* GeodesicExact, and TransverseMercatorExact. Two categories of function
* are provided:
* - \e static functions to compute symmetric elliptic integrals
* (https://dlmf.nist.gov/19.16.i)
* - \e member functions to compute Legrendre's elliptic
* integrals (https://dlmf.nist.gov/19.2.ii) and the
* Jacobi elliptic functions (https://dlmf.nist.gov/22.2).
* .
* In the latter case, an object is constructed giving the modulus \e k (and
* optionally the parameter &alpha;<sup>2</sup>). The modulus is always
* passed as its square <i>k</i><sup>2</sup> which allows \e k to be pure
* imaginary (<i>k</i><sup>2</sup> &lt; 0). (Confusingly, Abramowitz and
* Stegun call \e m = <i>k</i><sup>2</sup> the "parameter" and \e n =
* &alpha;<sup>2</sup> the "characteristic".)
*
* In geodesic applications, it is convenient to separate the incomplete
* integrals into secular and periodic components, e.g.,
* \f[
* E(\phi, k) = (2 E(k) / \pi) [ \phi + \delta E(\phi, k) ]
* \f]
* where &delta;\e E(&phi;, \e k) is an odd periodic function with period
* &pi;.
*
* The computation of the elliptic integrals uses the algorithms given in
* - B. C. Carlson,
* <a href="https://doi.org/10.1007/BF02198293"> Computation of real or
* complex elliptic integrals</a>, Numerical Algorithms 10, 13--26 (1995)
* .
* with the additional optimizations given in https://dlmf.nist.gov/19.36.i.
* The computation of the Jacobi elliptic functions uses the algorithm given
* in
* - R. Bulirsch,
* <a href="https://doi.org/10.1007/BF01397975"> Numerical Calculation of
* Elliptic Integrals and Elliptic Functions</a>, Numericshe Mathematik 7,
* 78--90 (1965).
* .
* The notation follows https://dlmf.nist.gov/19 and https://dlmf.nist.gov/22
*
* Example of use:
* \include example-EllipticFunction.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT EllipticFunction {
private:
typedef Math::real real;
enum { num_ = 13 }; // Max depth required for sncndn; probably 5 is enough.
real _k2, _kp2, _alpha2, _alphap2, _eps;
real _Kc, _Ec, _Dc, _Pic, _Gc, _Hc;
public:
/** \name Constructor
**********************************************************************/
///@{
/**
* Constructor specifying the modulus and parameter.
*
* @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>.
* <i>k</i><sup>2</sup> must lie in (&minus;&infin;, 1].
* @param[in] alpha2 the parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (&minus;&infin;, 1].
* @exception GeographicErr if \e k2 or \e alpha2 is out of its legal
* range.
*
* If only elliptic integrals of the first and second kinds are needed,
* then set &alpha;<sup>2</sup> = 0 (the default value); in this case, we
* have &Pi;(&phi;, 0, \e k) = \e F(&phi;, \e k), \e G(&phi;, 0, \e k) = \e
* E(&phi;, \e k), and \e H(&phi;, 0, \e k) = \e F(&phi;, \e k) - \e
* D(&phi;, \e k).
**********************************************************************/
EllipticFunction(real k2 = 0, real alpha2 = 0)
{ Reset(k2, alpha2); }
/**
* Constructor specifying the modulus and parameter and their complements.
*
* @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>.
* <i>k</i><sup>2</sup> must lie in (&minus;&infin;, 1].
* @param[in] alpha2 the parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (&minus;&infin;, 1].
* @param[in] kp2 the complementary modulus squared <i>k'</i><sup>2</sup> =
* 1 &minus; <i>k</i><sup>2</sup>. This must lie in [0, &infin;).
* @param[in] alphap2 the complementary parameter &alpha;'<sup>2</sup> = 1
* &minus; &alpha;<sup>2</sup>. This must lie in [0, &infin;).
* @exception GeographicErr if \e k2, \e alpha2, \e kp2, or \e alphap2 is
* out of its legal range.
*
* The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alphap2
* = 1. (No checking is done that these conditions are met.) This
* constructor is provided to enable accuracy to be maintained, e.g., when
* \e k is very close to unity.
**********************************************************************/
EllipticFunction(real k2, real alpha2, real kp2, real alphap2)
{ Reset(k2, alpha2, kp2, alphap2); }
/**
* Reset the modulus and parameter.
*
* @param[in] k2 the new value of square of the modulus
* <i>k</i><sup>2</sup> which must lie in (&minus;&infin;, ].
* done.)
* @param[in] alpha2 the new value of parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (&minus;&infin;, 1].
* @exception GeographicErr if \e k2 or \e alpha2 is out of its legal
* range.
**********************************************************************/
void Reset(real k2 = 0, real alpha2 = 0)
{ Reset(k2, alpha2, 1 - k2, 1 - alpha2); }
/**
* Reset the modulus and parameter supplying also their complements.
*
* @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>.
* <i>k</i><sup>2</sup> must lie in (&minus;&infin;, 1].
* @param[in] alpha2 the parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (&minus;&infin;, 1].
* @param[in] kp2 the complementary modulus squared <i>k'</i><sup>2</sup> =
* 1 &minus; <i>k</i><sup>2</sup>. This must lie in [0, &infin;).
* @param[in] alphap2 the complementary parameter &alpha;'<sup>2</sup> = 1
* &minus; &alpha;<sup>2</sup>. This must lie in [0, &infin;).
* @exception GeographicErr if \e k2, \e alpha2, \e kp2, or \e alphap2 is
* out of its legal range.
*
* The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alphap2
* = 1. (No checking is done that these conditions are met.) This
* constructor is provided to enable accuracy to be maintained, e.g., when
* is very small.
**********************************************************************/
void Reset(real k2, real alpha2, real kp2, real alphap2);
///@}
/** \name Inspector functions.
**********************************************************************/
///@{
/**
* @return the square of the modulus <i>k</i><sup>2</sup>.
**********************************************************************/
Math::real k2() const { return _k2; }
/**
* @return the square of the complementary modulus <i>k'</i><sup>2</sup> =
* 1 &minus; <i>k</i><sup>2</sup>.
**********************************************************************/
Math::real kp2() const { return _kp2; }
/**
* @return the parameter &alpha;<sup>2</sup>.
**********************************************************************/
Math::real alpha2() const { return _alpha2; }
/**
* @return the complementary parameter &alpha;'<sup>2</sup> = 1 &minus;
* &alpha;<sup>2</sup>.
**********************************************************************/
Math::real alphap2() const { return _alphap2; }
///@}
/** \name Complete elliptic integrals.
**********************************************************************/
///@{
/**
* The complete integral of the first kind.
*
* @return \e K(\e k).
*
* \e K(\e k) is defined in https://dlmf.nist.gov/19.2.E4
* \f[
* K(k) = \int_0^{\pi/2} \frac1{\sqrt{1-k^2\sin^2\phi}}\,d\phi.
* \f]
**********************************************************************/
Math::real K() const { return _Kc; }
/**
* The complete integral of the second kind.
*
* @return \e E(\e k).
*
* \e E(\e k) is defined in https://dlmf.nist.gov/19.2.E5
* \f[
* E(k) = \int_0^{\pi/2} \sqrt{1-k^2\sin^2\phi}\,d\phi.
* \f]
**********************************************************************/
Math::real E() const { return _Ec; }
/**
* Jahnke's complete integral.
*
* @return \e D(\e k).
*
* \e D(\e k) is defined in https://dlmf.nist.gov/19.2.E6
* \f[
* D(k) =
* \int_0^{\pi/2} \frac{\sin^2\phi}{\sqrt{1-k^2\sin^2\phi}}\,d\phi.
* \f]
**********************************************************************/
Math::real D() const { return _Dc; }
/**
* The difference between the complete integrals of the first and second
* kinds.
*
* @return \e K(\e k) &minus; \e E(\e k).
**********************************************************************/
Math::real KE() const { return _k2 * _Dc; }
/**
* The complete integral of the third kind.
*
* @return &Pi;(&alpha;<sup>2</sup>, \e k).
*
* &Pi;(&alpha;<sup>2</sup>, \e k) is defined in
* https://dlmf.nist.gov/19.2.E7
* \f[
* \Pi(\alpha^2, k) = \int_0^{\pi/2}
* \frac1{\sqrt{1-k^2\sin^2\phi}(1 - \alpha^2\sin^2\phi)}\,d\phi.
* \f]
**********************************************************************/
Math::real Pi() const { return _Pic; }
/**
* Legendre's complete geodesic longitude integral.
*
* @return \e G(&alpha;<sup>2</sup>, \e k).
*
* \e G(&alpha;<sup>2</sup>, \e k) is given by
* \f[
* G(\alpha^2, k) = \int_0^{\pi/2}
* \frac{\sqrt{1-k^2\sin^2\phi}}{1 - \alpha^2\sin^2\phi}\,d\phi.
* \f]
**********************************************************************/
Math::real G() const { return _Gc; }
/**
* Cayley's complete geodesic longitude difference integral.
*
* @return \e H(&alpha;<sup>2</sup>, \e k).
*
* \e H(&alpha;<sup>2</sup>, \e k) is given by
* \f[
* H(\alpha^2, k) = \int_0^{\pi/2}
* \frac{\cos^2\phi}{(1-\alpha^2\sin^2\phi)\sqrt{1-k^2\sin^2\phi}}
* \,d\phi.
* \f]
**********************************************************************/
Math::real H() const { return _Hc; }
///@}
/** \name Incomplete elliptic integrals.
**********************************************************************/
///@{
/**
* The incomplete integral of the first kind.
*
* @param[in] phi
* @return \e F(&phi;, \e k).
*
* \e F(&phi;, \e k) is defined in https://dlmf.nist.gov/19.2.E4
* \f[
* F(\phi, k) = \int_0^\phi \frac1{\sqrt{1-k^2\sin^2\theta}}\,d\theta.
* \f]
**********************************************************************/
Math::real F(real phi) const;
/**
* The incomplete integral of the second kind.
*
* @param[in] phi
* @return \e E(&phi;, \e k).
*
* \e E(&phi;, \e k) is defined in https://dlmf.nist.gov/19.2.E5
* \f[
* E(\phi, k) = \int_0^\phi \sqrt{1-k^2\sin^2\theta}\,d\theta.
* \f]
**********************************************************************/
Math::real E(real phi) const;
/**
* The incomplete integral of the second kind with the argument given in
* degrees.
*
* @param[in] ang in <i>degrees</i>.
* @return \e E(&pi; <i>ang</i>/180, \e k).
**********************************************************************/
Math::real Ed(real ang) const;
/**
* The inverse of the incomplete integral of the second kind.
*
* @param[in] x
* @return &phi; = <i>E</i><sup>&minus;1</sup>(\e x, \e k); i.e., the
* solution of such that \e E(&phi;, \e k) = \e x.
**********************************************************************/
Math::real Einv(real x) const;
/**
* The incomplete integral of the third kind.
*
* @param[in] phi
* @return &Pi;(&phi;, &alpha;<sup>2</sup>, \e k).
*
* &Pi;(&phi;, &alpha;<sup>2</sup>, \e k) is defined in
* https://dlmf.nist.gov/19.2.E7
* \f[
* \Pi(\phi, \alpha^2, k) = \int_0^\phi
* \frac1{\sqrt{1-k^2\sin^2\theta}(1 - \alpha^2\sin^2\theta)}\,d\theta.
* \f]
**********************************************************************/
Math::real Pi(real phi) const;
/**
* Jahnke's incomplete elliptic integral.
*
* @param[in] phi
* @return \e D(&phi;, \e k).
*
* \e D(&phi;, \e k) is defined in https://dlmf.nist.gov/19.2.E4
* \f[
* D(\phi, k) = \int_0^\phi
* \frac{\sin^2\theta}{\sqrt{1-k^2\sin^2\theta}}\,d\theta.
* \f]
**********************************************************************/
Math::real D(real phi) const;
/**
* Legendre's geodesic longitude integral.
*
* @param[in] phi
* @return \e G(&phi;, &alpha;<sup>2</sup>, \e k).
*
* \e G(&phi;, &alpha;<sup>2</sup>, \e k) is defined by
* \f[
* \begin{align}
* G(\phi, \alpha^2, k) &=
* \frac{k^2}{\alpha^2} F(\phi, k) +
* \biggl(1 - \frac{k^2}{\alpha^2}\biggr) \Pi(\phi, \alpha^2, k) \\
* &= \int_0^\phi
* \frac{\sqrt{1-k^2\sin^2\theta}}{1 - \alpha^2\sin^2\theta}\,d\theta.
* \end{align}
* \f]
*
* Legendre expresses the longitude of a point on the geodesic in terms of
* this combination of elliptic integrals in Exercices de Calcul
* Int&eacute;gral, Vol. 1 (1811), p. 181,
* https://books.google.com/books?id=riIOAAAAQAAJ&pg=PA181.
*
* See \ref geodellip for the expression for the longitude in terms of this
* function.
**********************************************************************/
Math::real G(real phi) const;
/**
* Cayley's geodesic longitude difference integral.
*
* @param[in] phi
* @return \e H(&phi;, &alpha;<sup>2</sup>, \e k).
*
* \e H(&phi;, &alpha;<sup>2</sup>, \e k) is defined by
* \f[
* \begin{align}
* H(\phi, \alpha^2, k) &=
* \frac1{\alpha^2} F(\phi, k) +
* \biggl(1 - \frac1{\alpha^2}\biggr) \Pi(\phi, \alpha^2, k) \\
* &= \int_0^\phi
* \frac{\cos^2\theta}
* {(1-\alpha^2\sin^2\theta)\sqrt{1-k^2\sin^2\theta}}
* \,d\theta.
* \end{align}
* \f]
*
* Cayley expresses the longitude difference of a point on the geodesic in
* terms of this combination of elliptic integrals in Phil. Mag. <b>40</b>
* (1870), p. 333, https://books.google.com/books?id=Zk0wAAAAIAAJ&pg=PA333.
*
* See \ref geodellip for the expression for the longitude in terms of this
* function.
**********************************************************************/
Math::real H(real phi) const;
///@}
/** \name Incomplete integrals in terms of Jacobi elliptic functions.
**********************************************************************/
///@{
/**
* The incomplete integral of the first kind in terms of Jacobi elliptic
* functions.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return \e F(&phi;, \e k) as though &phi; &isin; (&minus;&pi;, &pi;].
**********************************************************************/
Math::real F(real sn, real cn, real dn) const;
/**
* The incomplete integral of the second kind in terms of Jacobi elliptic
* functions.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return \e E(&phi;, \e k) as though &phi; &isin; (&minus;&pi;, &pi;].
**********************************************************************/
Math::real E(real sn, real cn, real dn) const;
/**
* The incomplete integral of the third kind in terms of Jacobi elliptic
* functions.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return &Pi;(&phi;, &alpha;<sup>2</sup>, \e k) as though &phi; &isin;
* (&minus;&pi;, &pi;].
**********************************************************************/
Math::real Pi(real sn, real cn, real dn) const;
/**
* Jahnke's incomplete elliptic integral in terms of Jacobi elliptic
* functions.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return \e D(&phi;, \e k) as though &phi; &isin; (&minus;&pi;, &pi;].
**********************************************************************/
Math::real D(real sn, real cn, real dn) const;
/**
* Legendre's geodesic longitude integral in terms of Jacobi elliptic
* functions.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return \e G(&phi;, &alpha;<sup>2</sup>, \e k) as though &phi; &isin;
* (&minus;&pi;, &pi;].
**********************************************************************/
Math::real G(real sn, real cn, real dn) const;
/**
* Cayley's geodesic longitude difference integral in terms of Jacobi
* elliptic functions.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return \e H(&phi;, &alpha;<sup>2</sup>, \e k) as though &phi; &isin;
* (&minus;&pi;, &pi;].
**********************************************************************/
Math::real H(real sn, real cn, real dn) const;
///@}
/** \name Periodic versions of incomplete elliptic integrals.
**********************************************************************/
///@{
/**
* The periodic incomplete integral of the first kind.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return the periodic function &pi; \e F(&phi;, \e k) / (2 \e K(\e k)) -
* &phi;.
**********************************************************************/
Math::real deltaF(real sn, real cn, real dn) const;
/**
* The periodic incomplete integral of the second kind.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return the periodic function &pi; \e E(&phi;, \e k) / (2 \e E(\e k)) -
* &phi;.
**********************************************************************/
Math::real deltaE(real sn, real cn, real dn) const;
/**
* The periodic inverse of the incomplete integral of the second kind.
*
* @param[in] stau = sin&tau;.
* @param[in] ctau = sin&tau;.
* @return the periodic function <i>E</i><sup>&minus;1</sup>(&tau; (2 \e
* E(\e k)/&pi;), \e k) - &tau;.
**********************************************************************/
Math::real deltaEinv(real stau, real ctau) const;
/**
* The periodic incomplete integral of the third kind.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return the periodic function &pi; &Pi;(&phi;, &alpha;<sup>2</sup>,
* \e k) / (2 &Pi;(&alpha;<sup>2</sup>, \e k)) - &phi;.
**********************************************************************/
Math::real deltaPi(real sn, real cn, real dn) const;
/**
* The periodic Jahnke's incomplete elliptic integral.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return the periodic function &pi; \e D(&phi;, \e k) / (2 \e D(\e k)) -
* &phi;.
**********************************************************************/
Math::real deltaD(real sn, real cn, real dn) const;
/**
* Legendre's periodic geodesic longitude integral.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return the periodic function &pi; \e G(&phi;, \e k) / (2 \e G(\e k)) -
* &phi;.
**********************************************************************/
Math::real deltaG(real sn, real cn, real dn) const;
/**
* Cayley's periodic geodesic longitude difference integral.
*
* @param[in] sn = sin&phi;.
* @param[in] cn = cos&phi;.
* @param[in] dn = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
* @return the periodic function &pi; \e H(&phi;, \e k) / (2 \e H(\e k)) -
* &phi;.
**********************************************************************/
Math::real deltaH(real sn, real cn, real dn) const;
///@}
/** \name Elliptic functions.
**********************************************************************/
///@{
/**
* The Jacobi elliptic functions.
*
* @param[in] x the argument.
* @param[out] sn sn(\e x, \e k).
* @param[out] cn cn(\e x, \e k).
* @param[out] dn dn(\e x, \e k).
**********************************************************************/
void sncndn(real x, real& sn, real& cn, real& dn) const;
/**
* The &Delta; amplitude function.
*
* @param[in] sn sin&phi;.
* @param[in] cn cos&phi;.
* @return &Delta; = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;).
**********************************************************************/
Math::real Delta(real sn, real cn) const {
using std::sqrt;
return sqrt(_k2 < 0 ? 1 - _k2 * sn*sn : _kp2 + _k2 * cn*cn);
}
///@}
/** \name Symmetric elliptic integrals.
**********************************************************************/
///@{
/**
* Symmetric integral of the first kind <i>R</i><sub><i>F</i></sub>.
*
* @param[in] x
* @param[in] y
* @param[in] z
* @return <i>R</i><sub><i>F</i></sub>(\e x, \e y, \e z).
*
* <i>R</i><sub><i>F</i></sub> is defined in https://dlmf.nist.gov/19.16.E1
* \f[ R_F(x, y, z) = \frac12
* \int_0^\infty\frac1{\sqrt{(t + x) (t + y) (t + z)}}\, dt \f]
* If one of the arguments is zero, it is more efficient to call the
* two-argument version of this function with the non-zero arguments.
**********************************************************************/
static real RF(real x, real y, real z);
/**
* Complete symmetric integral of the first kind,
* <i>R</i><sub><i>F</i></sub> with one argument zero.
*
* @param[in] x
* @param[in] y
* @return <i>R</i><sub><i>F</i></sub>(\e x, \e y, 0).
**********************************************************************/
static real RF(real x, real y);
/**
* Degenerate symmetric integral of the first kind
* <i>R</i><sub><i>C</i></sub>.
*
* @param[in] x
* @param[in] y
* @return <i>R</i><sub><i>C</i></sub>(\e x, \e y) =
* <i>R</i><sub><i>F</i></sub>(\e x, \e y, \e y).
*
* <i>R</i><sub><i>C</i></sub> is defined in https://dlmf.nist.gov/19.2.E17
* \f[ R_C(x, y) = \frac12
* \int_0^\infty\frac1{\sqrt{t + x}(t + y)}\,dt \f]
**********************************************************************/
static real RC(real x, real y);
/**
* Symmetric integral of the second kind <i>R</i><sub><i>G</i></sub>.
*
* @param[in] x
* @param[in] y
* @param[in] z
* @return <i>R</i><sub><i>G</i></sub>(\e x, \e y, \e z).
*
* <i>R</i><sub><i>G</i></sub> is defined in Carlson, eq 1.5
* \f[ R_G(x, y, z) = \frac14
* \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2}
* \biggl(
* \frac x{t + x} + \frac y{t + y} + \frac z{t + z}
* \biggr)t\,dt \f]
* See also https://dlmf.nist.gov/19.16.E3.
* If one of the arguments is zero, it is more efficient to call the
* two-argument version of this function with the non-zero arguments.
**********************************************************************/
static real RG(real x, real y, real z);
/**
* Complete symmetric integral of the second kind,
* <i>R</i><sub><i>G</i></sub> with one argument zero.
*
* @param[in] x
* @param[in] y
* @return <i>R</i><sub><i>G</i></sub>(\e x, \e y, 0).
**********************************************************************/
static real RG(real x, real y);
/**
* Symmetric integral of the third kind <i>R</i><sub><i>J</i></sub>.
*
* @param[in] x
* @param[in] y
* @param[in] z
* @param[in] p
* @return <i>R</i><sub><i>J</i></sub>(\e x, \e y, \e z, \e p).
*
* <i>R</i><sub><i>J</i></sub> is defined in https://dlmf.nist.gov/19.16.E2
* \f[ R_J(x, y, z, p) = \frac32
* \int_0^\infty
* [(t + x) (t + y) (t + z)]^{-1/2} (t + p)^{-1}\, dt \f]
**********************************************************************/
static real RJ(real x, real y, real z, real p);
/**
* Degenerate symmetric integral of the third kind
* <i>R</i><sub><i>D</i></sub>.
*
* @param[in] x
* @param[in] y
* @param[in] z
* @return <i>R</i><sub><i>D</i></sub>(\e x, \e y, \e z) =
* <i>R</i><sub><i>J</i></sub>(\e x, \e y, \e z, \e z).
*
* <i>R</i><sub><i>D</i></sub> is defined in https://dlmf.nist.gov/19.16.E5
* \f[ R_D(x, y, z) = \frac32
* \int_0^\infty[(t + x) (t + y)]^{-1/2} (t + z)^{-3/2}\, dt \f]
**********************************************************************/
static real RD(real x, real y, real z);
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_ELLIPTICFUNCTION_HPP

143
external/include/GeographicLib/GARS.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,143 @@
/**
* \file GARS.hpp
* \brief Header for GeographicLib::GARS class
*
* Copyright (c) Charles Karney (2015-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GARS_HPP)
#define GEOGRAPHICLIB_GARS_HPP 1
#include <GeographicLib/Constants.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs string
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
/**
* \brief Conversions for the Global Area Reference System (GARS)
*
* The Global Area Reference System is described in
* - https://en.wikipedia.org/wiki/Global_Area_Reference_System
* - https://earth-info.nga.mil/index.php?dir=coordsys&action=coordsys#tab_gars
* .
* It provides a compact string representation of a geographic area
* (expressed as latitude and longitude). The classes Georef and Geohash
* implement similar compact representations.
*
* Example of use:
* \include example-GARS.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GARS {
private:
typedef Math::real real;
static const char* const digits_;
static const char* const letters_;
enum {
lonorig_ = -180, // Origin for longitude
latorig_ = -90, // Origin for latitude
baselon_ = 10, // Base for longitude tiles
baselat_ = 24, // Base for latitude tiles
lonlen_ = 3,
latlen_ = 2,
baselen_ = lonlen_ + latlen_,
mult1_ = 2, // base precision = 1/2 degree
mult2_ = 2, // 6th char gives 2x more precision
mult3_ = 3, // 7th char gives 3x more precision
m_ = mult1_ * mult2_ * mult3_,
maxprec_ = 2,
maxlen_ = baselen_ + maxprec_,
};
GARS(); // Disable constructor
public:
/**
* Convert from geographic coordinates to GARS.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] prec the precision of the resulting GARS.
* @param[out] gars the GARS string.
* @exception GeographicErr if \e lat is not in [&minus;90&deg;,
* 90&deg;].
* @exception std::bad_alloc if memory for \e gars can't be allocated.
*
* \e prec specifies the precision of \e gars as follows:
* - \e prec = 0 (min), 30' precision, e.g., 006AG;
* - \e prec = 1, 15' precision, e.g., 006AG3;
* - \e prec = 2 (max), 5' precision, e.g., 006AG39.
*
* If \e lat or \e lon is NaN, then \e gars is set to "INVALID".
**********************************************************************/
static void Forward(real lat, real lon, int prec, std::string& gars);
/**
* Convert from GARS to geographic coordinates.
*
* @param[in] gars the GARS.
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] prec the precision of \e gars.
* @param[in] centerp if true (the default) return the center of the
* \e gars, otherwise return the south-west corner.
* @exception GeographicErr if \e gars is illegal.
*
* The case of the letters in \e gars is ignored. \e prec is in the range
* [0, 2] and gives the precision of \e gars as follows:
* - \e prec = 0 (min), 30' precision, e.g., 006AG;
* - \e prec = 1, 15' precision, e.g., 006AG3;
* - \e prec = 2 (max), 5' precision, e.g., 006AG39.
*
* If the first 3 characters of \e gars are "INV", then \e lat and \e lon
* are set to NaN and \e prec is unchanged.
**********************************************************************/
static void Reverse(const std::string& gars, real& lat, real& lon,
int& prec, bool centerp = true);
/**
* The angular resolution of a GARS.
*
* @param[in] prec the precision of the GARS.
* @return the latitude-longitude resolution (degrees).
*
* Internally, \e prec is first put in the range [0, 2].
**********************************************************************/
static Math::real Resolution(int prec) {
return 1/real(prec <= 0 ? mult1_ : (prec == 1 ? mult1_ * mult2_ :
mult1_ * mult2_ * mult3_));
}
/**
* The GARS precision required to meet a given geographic resolution.
*
* @param[in] res the minimum of resolution in latitude and longitude
* (degrees).
* @return GARS precision.
*
* The returned length is in the range [0, 2].
**********************************************************************/
static int Precision(real res) {
using std::abs; res = abs(res);
for (int prec = 0; prec < maxprec_; ++prec)
if (Resolution(prec) <= res)
return prec;
return maxprec_;
}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_GARS_HPP

553
external/include/GeographicLib/GeoCoords.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,553 @@
/**
* \file GeoCoords.hpp
* \brief Header for GeographicLib::GeoCoords class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEOCOORDS_HPP)
#define GEOGRAPHICLIB_GEOCOORDS_HPP 1
#include <GeographicLib/UTMUPS.hpp>
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Conversion between geographic coordinates
*
* This class stores a geographic position which may be set via the
* constructors or Reset via
* - latitude and longitude
* - UTM or UPS coordinates
* - a string representation of these or an MGRS coordinate string
*
* The state consists of the latitude and longitude and the supplied UTM or
* UPS coordinates (possibly derived from the MGRS coordinates). If latitude
* and longitude were given then the UTM/UPS coordinates follows the standard
* conventions.
*
* The mutable state consists of the UTM or UPS coordinates for a alternate
* zone. A method SetAltZone is provided to set the alternate UPS/UTM zone.
*
* Methods are provided to return the geographic coordinates, the input UTM
* or UPS coordinates (and associated meridian convergence and scale), or
* alternate UTM or UPS coordinates (and their associated meridian
* convergence and scale).
*
* Once the input string has been parsed, you can print the result out in any
* of the formats, decimal degrees, degrees minutes seconds, MGRS, UTM/UPS.
*
* Example of use:
* \include example-GeoCoords.cpp
*
* <a href="GeoConvert.1.html">GeoConvert</a> is a command-line utility
* providing access to the functionality of GeoCoords.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GeoCoords {
private:
typedef Math::real real;
real _lat, _long, _easting, _northing, _gamma, _k;
bool _northp;
int _zone; // See UTMUPS::zonespec
mutable real _alt_easting, _alt_northing, _alt_gamma, _alt_k;
mutable int _alt_zone;
void CopyToAlt() const {
_alt_easting = _easting;
_alt_northing = _northing;
_alt_gamma = _gamma;
_alt_k = _k;
_alt_zone = _zone;
}
static void UTMUPSString(int zone, bool northp,
real easting, real northing,
int prec, bool abbrev, std::string& utm);
void FixHemisphere();
public:
/** \name Initializing the GeoCoords object
**********************************************************************/
///@{
/**
* The default constructor sets the coordinate as undefined.
**********************************************************************/
GeoCoords()
: _lat(Math::NaN())
, _long(Math::NaN())
, _easting(Math::NaN())
, _northing(Math::NaN())
, _gamma(Math::NaN())
, _k(Math::NaN())
, _northp(false)
, _zone(UTMUPS::INVALID)
{ CopyToAlt(); }
/**
* Construct from a string.
*
* @param[in] s 1-element, 2-element, or 3-element string representation of
* the position.
* @param[in] centerp governs the interpretation of MGRS coordinates (see
* below).
* @param[in] longfirst governs the interpretation of geographic
* coordinates (see below).
* @exception GeographicErr if the \e s is malformed (see below).
*
* Parse as a string and interpret it as a geographic position. The input
* string is broken into space (or comma) separated pieces and Basic
* decision on which format is based on number of components
* -# MGRS
* -# "Lat Long" or "Long Lat"
* -# "Zone Easting Northing" or "Easting Northing Zone"
*
* The following inputs are approximately the same (Ar Ramadi Bridge, Iraq)
* - Latitude and Longitude
* - 33.44 43.27
* - N33d26.4' E43d16.2'
* - 43d16'12&quot;E 33d26'24&quot;N
* - 43:16:12E 33:26:24
* - MGRS
* - 38SLC30
* - 38SLC391014
* - 38SLC3918701405
* - 37SHT9708
* - UTM
* - 38n 339188 3701405
* - 897039 3708229 37n
*
* <b>Latitude and Longitude parsing</b>: Latitude precedes longitude,
* unless a N, S, E, W hemisphere designator is used on one or both
* coordinates. If \e longfirst = true (default is false), then
* longitude precedes latitude in the absence of a hemisphere designator.
* Thus (with \e longfirst = false)
* - 40 -75
* - N40 W75
* - -75 N40
* - 75W 40N
* - E-75 -40S
* .
* are all the same position. The coordinates may be given in
* decimal degrees, degrees and decimal minutes, degrees, minutes,
* seconds, etc. Use d, ', and &quot; to mark off the degrees,
* minutes and seconds. Various alternative symbols for degrees, minutes,
* and seconds are allowed. Alternatively, use : to separate these
* components. A single addition or subtraction is allowed. (See
* DMS::Decode for details.) Thus
* - 40d30'30&quot;
* - 40d30'30
* - 40&deg;30'30
* - 40d30.5'
* - 40d30.5
* - 40:30:30
* - 40:30.5
* - 40.508333333
* - 40:30+0:0:30
* - 40:31-0:0.5
* .
* all specify the same angle. The leading sign applies to the following
* components so -1d30 is -(1+30/60) = &minus;1.5. However, note
* that -1:30-0:0:15 is parsed as (-1:30) + (-0:0:15) = &minus;(1+30/60)
* &minus; (15/3600). Latitudes must be in the range [&minus;90&deg;,
* 90&deg;]. Internally longitudes are reduced to the range
* [&minus;180&deg;, 180&deg;].
*
* <b>UTM/UPS parsing</b>: For UTM zones (&minus;80&deg; &le; Lat <
* 84&deg;), the zone designator is made up of a zone number (for 1 to 60)
* and a hemisphere letter (n or s), e.g., 38n (38north can also be used).
* The latitude band designer ([C--M] in the southern hemisphere and [N--X]
* in the northern) should NOT be used. (This is part of the MGRS
* coordinate.) The zone designator for the poles (where UPS is employed)
* is a hemisphere letter by itself, i.e., n or s (north or south can also
* be used).
*
* <b>MGRS parsing</b> interprets the grid references as square area at the
* specified precision (1m, 10m, 100m, etc.). If \e centerp = true (the
* default), the center of this square is then taken to be the precise
* position; thus:
* - 38SMB = 38n 450000 3650000
* - 38SMB4484 = 38n 444500 3684500
* - 38SMB44148470 = 38n 444145 3684705
* .
* Otherwise, the "south-west" corner of the square is used, i.e.,
* - 38SMB = 38n 400000 3600000
* - 38SMB4484 = 38n 444000 3684000
* - 38SMB44148470 = 38n 444140 3684700
**********************************************************************/
explicit GeoCoords(const std::string& s,
bool centerp = true, bool longfirst = false)
{ Reset(s, centerp, longfirst); }
/**
* Construct from geographic coordinates.
*
* @param[in] latitude (degrees).
* @param[in] longitude (degrees).
* @param[in] zone if specified, force the UTM/UPS representation to use a
* specified zone using the rules given in UTMUPS::zonespec.
* @exception GeographicErr if \e latitude is not in [&minus;90&deg;,
* 90&deg;].
* @exception GeographicErr if \e zone cannot be used for this location.
**********************************************************************/
GeoCoords(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
Reset(latitude, longitude, zone);
}
/**
* Construct from UTM/UPS coordinates.
*
* @param[in] zone UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @param[in] easting (meters).
* @param[in] northing (meters).
* @exception GeographicErr if \e zone, \e easting, or \e northing is
* outside its allowed range.
**********************************************************************/
GeoCoords(int zone, bool northp, real easting, real northing) {
Reset(zone, northp, easting, northing);
}
/**
* Reset the location from a string. See
* GeoCoords(const std::string& s, bool centerp, bool longfirst).
*
* @param[in] s 1-element, 2-element, or 3-element string representation of
* the position.
* @param[in] centerp governs the interpretation of MGRS coordinates.
* @param[in] longfirst governs the interpretation of geographic
* coordinates.
* @exception GeographicErr if the \e s is malformed.
**********************************************************************/
void Reset(const std::string& s,
bool centerp = true, bool longfirst = false);
/**
* Reset the location in terms of geographic coordinates. See
* GeoCoords(real latitude, real longitude, int zone).
*
* @param[in] latitude (degrees).
* @param[in] longitude (degrees).
* @param[in] zone if specified, force the UTM/UPS representation to use a
* specified zone using the rules given in UTMUPS::zonespec.
* @exception GeographicErr if \e latitude is not in [&minus;90&deg;,
* 90&deg;].
* @exception GeographicErr if \e zone cannot be used for this location.
**********************************************************************/
void Reset(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
UTMUPS::Forward(latitude, longitude,
_zone, _northp, _easting, _northing, _gamma, _k,
zone);
_lat = latitude;
_long = longitude;
if (_long >= 180) _long -= 360;
else if (_long < -180) _long += 360;
CopyToAlt();
}
/**
* Reset the location in terms of UPS/UPS coordinates. See
* GeoCoords(int zone, bool northp, real easting, real northing).
*
* @param[in] zone UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @param[in] easting (meters).
* @param[in] northing (meters).
* @exception GeographicErr if \e zone, \e easting, or \e northing is
* outside its allowed range.
**********************************************************************/
void Reset(int zone, bool northp, real easting, real northing) {
UTMUPS::Reverse(zone, northp, easting, northing,
_lat, _long, _gamma, _k);
_zone = zone;
_northp = northp;
_easting = easting;
_northing = northing;
FixHemisphere();
CopyToAlt();
}
///@}
/** \name Querying the GeoCoords object
**********************************************************************/
///@{
/**
* @return latitude (degrees)
**********************************************************************/
Math::real Latitude() const { return _lat; }
/**
* @return longitude (degrees)
**********************************************************************/
Math::real Longitude() const { return _long; }
/**
* @return easting (meters)
**********************************************************************/
Math::real Easting() const { return _easting; }
/**
* @return northing (meters)
**********************************************************************/
Math::real Northing() const { return _northing; }
/**
* @return meridian convergence (degrees) for the UTM/UPS projection.
**********************************************************************/
Math::real Convergence() const { return _gamma; }
/**
* @return scale for the UTM/UPS projection.
**********************************************************************/
Math::real Scale() const { return _k; }
/**
* @return hemisphere (false means south, true means north).
**********************************************************************/
bool Northp() const { return _northp; }
/**
* @return hemisphere letter n or s.
**********************************************************************/
char Hemisphere() const { return _northp ? 'n' : 's'; }
/**
* @return the zone corresponding to the input (return 0 for UPS).
**********************************************************************/
int Zone() const { return _zone; }
///@}
/** \name Setting and querying the alternate zone
**********************************************************************/
///@{
/**
* Specify alternate zone number.
*
* @param[in] zone zone number for the alternate representation.
* @exception GeographicErr if \e zone cannot be used for this location.
*
* See UTMUPS::zonespec for more information on the interpretation of \e
* zone. Note that \e zone == UTMUPS::STANDARD (the default) use the
* standard UPS or UTM zone, UTMUPS::MATCH does nothing retaining the
* existing alternate representation. Before this is called the alternate
* zone is the input zone.
**********************************************************************/
void SetAltZone(int zone = UTMUPS::STANDARD) const {
if (zone == UTMUPS::MATCH)
return;
zone = UTMUPS::StandardZone(_lat, _long, zone);
if (zone == _zone)
CopyToAlt();
else {
bool northp;
UTMUPS::Forward(_lat, _long,
_alt_zone, northp,
_alt_easting, _alt_northing, _alt_gamma, _alt_k,
zone);
}
}
/**
* @return current alternate zone (return 0 for UPS).
**********************************************************************/
int AltZone() const { return _alt_zone; }
/**
* @return easting (meters) for alternate zone.
**********************************************************************/
Math::real AltEasting() const { return _alt_easting; }
/**
* @return northing (meters) for alternate zone.
**********************************************************************/
Math::real AltNorthing() const { return _alt_northing; }
/**
* @return meridian convergence (degrees) for alternate zone.
**********************************************************************/
Math::real AltConvergence() const { return _alt_gamma; }
/**
* @return scale for alternate zone.
**********************************************************************/
Math::real AltScale() const { return _alt_k; }
///@}
/** \name String representations of the GeoCoords object
**********************************************************************/
///@{
/**
* String representation with latitude and longitude as signed decimal
* degrees.
*
* @param[in] prec precision (relative to about 1m).
* @param[in] longfirst if true give longitude first (default = false)
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return decimal latitude/longitude string representation.
*
* Precision specifies accuracy of representation as follows:
* - prec = &minus;5 (min), 1&deg;
* - prec = 0, 10<sup>&minus;5</sup>&deg; (about 1m)
* - prec = 3, 10<sup>&minus;8</sup>&deg;
* - prec = 9 (max), 10<sup>&minus;14</sup>&deg;
**********************************************************************/
std::string GeoRepresentation(int prec = 0, bool longfirst = false) const;
/**
* String representation with latitude and longitude as degrees, minutes,
* seconds, and hemisphere.
*
* @param[in] prec precision (relative to about 1m)
* @param[in] longfirst if true give longitude first (default = false)
* @param[in] dmssep if non-null, use as the DMS separator character
* (instead of d, ', &quot; delimiters).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return DMS latitude/longitude string representation.
*
* Precision specifies accuracy of representation as follows:
* - prec = &minus;5 (min), 1&deg;
* - prec = &minus;4, 0.1&deg;
* - prec = &minus;3, 1'
* - prec = &minus;2, 0.1'
* - prec = &minus;1, 1&quot;
* - prec = 0, 0.1&quot; (about 3m)
* - prec = 1, 0.01&quot;
* - prec = 10 (max), 10<sup>&minus;11</sup>&quot;
**********************************************************************/
std::string DMSRepresentation(int prec = 0, bool longfirst = false,
char dmssep = char(0))
const;
/**
* MGRS string.
*
* @param[in] prec precision (relative to about 1m).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return MGRS string.
*
* This gives the coordinates of the enclosing grid square with size given
* by the precision. Thus 38n 444180 3684790 converted to a MGRS
* coordinate at precision &minus;2 (100m) is 38SMB441847 and not
* 38SMB442848. \e prec specifies the precision of the MGRS string as
* follows:
* - prec = &minus;6 (min), only the grid zone is returned, e.g., 38S
* - prec = &minus;5, 100km, e.g., 38SMB
* - prec = &minus;4, 10km
* - prec = &minus;3, 1km
* - prec = &minus;2, 100m
* - prec = &minus;1, 10m
* - prec = 0, 1m
* - prec = 1, 0.1m
* - prec = 6 (max), 1&mu;m
**********************************************************************/
std::string MGRSRepresentation(int prec = 0) const;
/**
* UTM/UPS string.
*
* @param[in] prec precision (relative to about 1m)
* @param[in] abbrev if true (the default) use abbreviated (n/s) notation
* for hemisphere; otherwise spell out the hemisphere (north/south)
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return UTM/UPS string representation: zone designator, easting, and
* northing.
*
* Precision specifies accuracy of representation as follows:
* - prec = &minus;5 (min), 100km
* - prec = &minus;3, 1km
* - prec = 0, 1m
* - prec = 3, 1mm
* - prec = 6, 1&mu;m
* - prec = 9 (max), 1nm
**********************************************************************/
std::string UTMUPSRepresentation(int prec = 0, bool abbrev = true) const;
/**
* UTM/UPS string with hemisphere override.
*
* @param[in] northp hemisphere override
* @param[in] prec precision (relative to about 1m)
* @param[in] abbrev if true (the default) use abbreviated (n/s) notation
* for hemisphere; otherwise spell out the hemisphere (north/south)
* @exception GeographicErr if the hemisphere override attempts to change
* UPS N to UPS S or vice versa.
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return UTM/UPS string representation: zone designator, easting, and
* northing.
**********************************************************************/
std::string UTMUPSRepresentation(bool northp, int prec = 0,
bool abbrev = true) const;
/**
* MGRS string for the alternate zone. See GeoCoords::MGRSRepresentation.
*
* @param[in] prec precision (relative to about 1m).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return MGRS string.
**********************************************************************/
std::string AltMGRSRepresentation(int prec = 0) const;
/**
* UTM/UPS string for the alternate zone. See
* GeoCoords::UTMUPSRepresentation.
*
* @param[in] prec precision (relative to about 1m)
* @param[in] abbrev if true (the default) use abbreviated (n/s) notation
* for hemisphere; otherwise spell out the hemisphere (north/south)
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return UTM/UPS string representation: zone designator, easting, and
* northing.
**********************************************************************/
std::string AltUTMUPSRepresentation(int prec = 0, bool abbrev = true)
const;
/**
* UTM/UPS string for the alternate zone, with hemisphere override.
*
* @param[in] northp hemisphere override
* @param[in] prec precision (relative to about 1m)
* @param[in] abbrev if true (the default) use abbreviated (n/s) notation
* for hemisphere; otherwise spell out the hemisphere (north/south)
* @exception GeographicErr if the hemisphere override attempts to change
* UPS n to UPS s or vice verse.
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return UTM/UPS string representation: zone designator, easting, and
* northing.
**********************************************************************/
std::string AltUTMUPSRepresentation(bool northp, int prec = 0,
bool abbrev = true) const;
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
*
* (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.)
**********************************************************************/
Math::real EquatorialRadius() const { return UTMUPS::EquatorialRadius(); }
/**
* @return \e f the flattening of the WGS84 ellipsoid.
*
* (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.)
**********************************************************************/
Math::real Flattening() const { return UTMUPS::Flattening(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEOCOORDS_HPP

274
external/include/GeographicLib/Geocentric.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,274 @@
/**
* \file Geocentric.hpp
* \brief Header for GeographicLib::Geocentric class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEOCENTRIC_HPP)
#define GEOGRAPHICLIB_GEOCENTRIC_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief %Geocentric coordinates
*
* Convert between geodetic coordinates latitude = \e lat, longitude = \e
* lon, height = \e h (measured vertically from the surface of the ellipsoid)
* to geocentric coordinates (\e X, \e Y, \e Z). The origin of geocentric
* coordinates is at the center of the earth. The \e Z axis goes thru the
* north pole, \e lat = 90&deg;. The \e X axis goes thru \e lat = 0,
* \e lon = 0. %Geocentric coordinates are also known as earth centered,
* earth fixed (ECEF) coordinates.
*
* The conversion from geographic to geocentric coordinates is
* straightforward. For the reverse transformation we use
* - H. Vermeille,
* <a href="https://doi.org/10.1007/s00190-002-0273-6"> Direct
* transformation from geocentric coordinates to geodetic coordinates</a>,
* J. Geodesy 76, 451--454 (2002).
* .
* Several changes have been made to ensure that the method returns accurate
* results for all finite inputs (even if \e h is infinite). The changes are
* described in Appendix B of
* - C. F. F. Karney,
* <a href="https://arxiv.org/abs/1102.1215v1">Geodesics
* on an ellipsoid of revolution</a>,
* Feb. 2011;
* preprint
* <a href="https://arxiv.org/abs/1102.1215v1">arxiv:1102.1215v1</a>.
* .
* Vermeille similarly updated his method in
* - H. Vermeille,
* <a href="https://doi.org/10.1007/s00190-010-0419-x">
* An analytical method to transform geocentric into
* geodetic coordinates</a>, J. Geodesy 85, 105--117 (2011).
* .
* See \ref geocentric for more information.
*
* The errors in these routines are close to round-off. Specifically, for
* points within 5000 km of the surface of the ellipsoid (either inside or
* outside the ellipsoid), the error is bounded by 7 nm (7 nanometers) for
* the WGS84 ellipsoid. See \ref geocentric for further information on the
* errors.
*
* Example of use:
* \include example-Geocentric.cpp
*
* <a href="CartConvert.1.html">CartConvert</a> is a command-line utility
* providing access to the functionality of Geocentric and LocalCartesian.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Geocentric {
private:
typedef Math::real real;
friend class LocalCartesian;
friend class MagneticCircle; // MagneticCircle uses Rotation
friend class MagneticModel; // MagneticModel uses IntForward
friend class GravityCircle; // GravityCircle uses Rotation
friend class GravityModel; // GravityModel uses IntForward
friend class NormalGravity; // NormalGravity uses IntForward
static const size_t dim_ = 3;
static const size_t dim2_ = dim_ * dim_;
real _a, _f, _e2, _e2m, _e2a, _e4a, _maxrad;
static void Rotation(real sphi, real cphi, real slam, real clam,
real M[dim2_]);
static void Rotate(const real M[dim2_], real x, real y, real z,
real& X, real& Y, real& Z) {
// Perform [X,Y,Z]^t = M.[x,y,z]^t
// (typically local cartesian to geocentric)
X = M[0] * x + M[1] * y + M[2] * z;
Y = M[3] * x + M[4] * y + M[5] * z;
Z = M[6] * x + M[7] * y + M[8] * z;
}
static void Unrotate(const real M[dim2_], real X, real Y, real Z,
real& x, real& y, real& z) {
// Perform [x,y,z]^t = M^t.[X,Y,Z]^t
// (typically geocentric to local cartesian)
x = M[0] * X + M[3] * Y + M[6] * Z;
y = M[1] * X + M[4] * Y + M[7] * Z;
z = M[2] * X + M[5] * Y + M[8] * Z;
}
void IntForward(real lat, real lon, real h, real& X, real& Y, real& Z,
real M[dim2_]) const;
void IntReverse(real X, real Y, real Z, real& lat, real& lon, real& h,
real M[dim2_]) const;
public:
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* positive.
**********************************************************************/
Geocentric(real a, real f);
/**
* A default constructor (for use by NormalGravity).
**********************************************************************/
Geocentric() : _a(-1) {}
/**
* Convert from geodetic to geocentric coordinates.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] h height of point above the ellipsoid (meters).
* @param[out] X geocentric coordinate (meters).
* @param[out] Y geocentric coordinate (meters).
* @param[out] Z geocentric coordinate (meters).
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
void Forward(real lat, real lon, real h, real& X, real& Y, real& Z)
const {
if (Init())
IntForward(lat, lon, h, X, Y, Z, NULL);
}
/**
* Convert from geodetic to geocentric coordinates and return rotation
* matrix.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] h height of point above the ellipsoid (meters).
* @param[out] X geocentric coordinate (meters).
* @param[out] Y geocentric coordinate (meters).
* @param[out] Z geocentric coordinate (meters).
* @param[out] M if the length of the vector is 9, fill with the rotation
* matrix in row-major order.
*
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
* express \e v as \e column vectors in one of two ways
* - in east, north, up coordinates (where the components are relative to a
* local coordinate system at (\e lat, \e lon, \e h)); call this
* representation \e v1.
* - in geocentric \e X, \e Y, \e Z coordinates; call this representation
* \e v0.
* .
* Then we have \e v0 = \e M &sdot; \e v1.
**********************************************************************/
void Forward(real lat, real lon, real h, real& X, real& Y, real& Z,
std::vector<real>& M)
const {
if (!Init())
return;
if (M.end() == M.begin() + dim2_) {
real t[dim2_];
IntForward(lat, lon, h, X, Y, Z, t);
std::copy(t, t + dim2_, M.begin());
} else
IntForward(lat, lon, h, X, Y, Z, NULL);
}
/**
* Convert from geocentric to geodetic to coordinates.
*
* @param[in] X geocentric coordinate (meters).
* @param[in] Y geocentric coordinate (meters).
* @param[in] Z geocentric coordinate (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] h height of point above the ellipsoid (meters).
*
* In general, there are multiple solutions and the result which minimizes
* |<i>h</i> |is returned, i.e., (<i>lat</i>, <i>lon</i>) corresponds to
* the closest point on the ellipsoid. If there are still multiple
* solutions with different latitudes (applies only if \e Z = 0), then the
* solution with \e lat > 0 is returned. If there are still multiple
* solutions with different longitudes (applies only if \e X = \e Y = 0)
* then \e lon = 0 is returned. The value of \e h returned satisfies \e h
* &ge; &minus; \e a (1 &minus; <i>e</i><sup>2</sup>) / sqrt(1 &minus;
* <i>e</i><sup>2</sup> sin<sup>2</sup>\e lat). The value of \e lon
* returned is in the range [&minus;180&deg;, 180&deg;].
**********************************************************************/
void Reverse(real X, real Y, real Z, real& lat, real& lon, real& h)
const {
if (Init())
IntReverse(X, Y, Z, lat, lon, h, NULL);
}
/**
* Convert from geocentric to geodetic to coordinates.
*
* @param[in] X geocentric coordinate (meters).
* @param[in] Y geocentric coordinate (meters).
* @param[in] Z geocentric coordinate (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] h height of point above the ellipsoid (meters).
* @param[out] M if the length of the vector is 9, fill with the rotation
* matrix in row-major order.
*
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
* express \e v as \e column vectors in one of two ways
* - in east, north, up coordinates (where the components are relative to a
* local coordinate system at (\e lat, \e lon, \e h)); call this
* representation \e v1.
* - in geocentric \e X, \e Y, \e Z coordinates; call this representation
* \e v0.
* .
* Then we have \e v1 = <i>M</i><sup>T</sup> &sdot; \e v0, where
* <i>M</i><sup>T</sup> is the transpose of \e M.
**********************************************************************/
void Reverse(real X, real Y, real Z, real& lat, real& lon, real& h,
std::vector<real>& M)
const {
if (!Init())
return;
if (M.end() == M.begin() + dim2_) {
real t[dim2_];
IntReverse(X, Y, Z, lat, lon, h, t);
std::copy(t, t + dim2_, M.begin());
} else
IntReverse(X, Y, Z, lat, lon, h, NULL);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _a > 0; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const
{ return Init() ? _a : Math::NaN(); }
/**
* @return \e f the flattening of the ellipsoid. This is the
* value used in the constructor.
**********************************************************************/
Math::real Flattening() const
{ return Init() ? _f : Math::NaN(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of Geocentric with the parameters for the WGS84
* ellipsoid.
**********************************************************************/
static const Geocentric& WGS84();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEOCENTRIC_HPP

977
external/include/GeographicLib/Geodesic.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,977 @@
/**
* \file Geodesic.hpp
* \brief Header for GeographicLib::Geodesic class
*
* Copyright (c) Charles Karney (2009-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEODESIC_HPP)
#define GEOGRAPHICLIB_GEODESIC_HPP 1
#include <GeographicLib/Constants.hpp>
#if !defined(GEOGRAPHICLIB_GEODESIC_ORDER)
/**
* The order of the expansions used by Geodesic.
* GEOGRAPHICLIB_GEODESIC_ORDER can be set to any integer in [3, 8].
**********************************************************************/
# define GEOGRAPHICLIB_GEODESIC_ORDER \
(GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
(GEOGRAPHICLIB_PRECISION == 1 ? 3 : \
(GEOGRAPHICLIB_PRECISION == 3 ? 7 : 8)))
#endif
namespace GeographicLib {
class GeodesicLine;
/**
* \brief %Geodesic calculations
*
* The shortest path between two points on a ellipsoid at (\e lat1, \e lon1)
* and (\e lat2, \e lon2) is called the geodesic. Its length is \e s12 and
* the geodesic from point 1 to point 2 has azimuths \e azi1 and \e azi2 at
* the two end points. (The azimuth is the heading measured clockwise from
* north. \e azi2 is the "forward" azimuth, i.e., the heading that takes you
* beyond point 2 not back to point 1.) In the figure below, latitude if
* labeled &phi;, longitude &lambda; (with &lambda;<sub>12</sub> =
* &lambda;<sub>2</sub> &minus; &lambda;<sub>1</sub>), and azimuth &alpha;.
*
* <img src="https://upload.wikimedia.org/wikipedia/commons/c/cb/Geodesic_problem_on_an_ellipsoid.svg" width=250 alt="spheroidal triangle">
*
* Given \e lat1, \e lon1, \e azi1, and \e s12, we can determine \e lat2, \e
* lon2, and \e azi2. This is the \e direct geodesic problem and its
* solution is given by the function Geodesic::Direct. (If \e s12 is
* sufficiently large that the geodesic wraps more than halfway around the
* earth, there will be another geodesic between the points with a smaller \e
* s12.)
*
* Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi1, \e
* azi2, and \e s12. This is the \e inverse geodesic problem, whose solution
* is given by Geodesic::Inverse. Usually, the solution to the inverse
* problem is unique. In cases where there are multiple solutions (all with
* the same \e s12, of course), all the solutions can be easily generated
* once a particular solution is provided.
*
* The standard way of specifying the direct problem is the specify the
* distance \e s12 to the second point. However it is sometimes useful
* instead to specify the arc length \e a12 (in degrees) on the auxiliary
* sphere. This is a mathematical construct used in solving the geodesic
* problems. The solution of the direct problem in this form is provided by
* Geodesic::ArcDirect. An arc length in excess of 180&deg; indicates that
* the geodesic is not a shortest path. In addition, the arc length between
* an equatorial crossing and the next extremum of latitude for a geodesic is
* 90&deg;.
*
* This class can also calculate several other quantities related to
* geodesics. These are:
* - <i>reduced length</i>. If we fix the first point and increase \e azi1
* by \e dazi1 (radians), the second point is displaced \e m12 \e dazi1 in
* the direction \e azi2 + 90&deg;. The quantity \e m12 is called
* the "reduced length" and is symmetric under interchange of the two
* points. On a curved surface the reduced length obeys a symmetry
* relation, \e m12 + \e m21 = 0. On a flat surface, we have \e m12 = \e
* s12. The ratio <i>s12</i>/\e m12 gives the azimuthal scale for an
* azimuthal equidistant projection.
* - <i>geodesic scale</i>. Consider a reference geodesic and a second
* geodesic parallel to this one at point 1 and separated by a small
* distance \e dt. The separation of the two geodesics at point 2 is \e
* M12 \e dt where \e M12 is called the "geodesic scale". \e M21 is
* defined similarly (with the geodesics being parallel at point 2). On a
* flat surface, we have \e M12 = \e M21 = 1. The quantity 1/\e M12 gives
* the scale of the Cassini-Soldner projection.
* - <i>area</i>. The area between the geodesic from point 1 to point 2 and
* the equation is represented by \e S12; it is the area, measured
* counter-clockwise, of the geodesic quadrilateral with corners
* (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>), (0,<i>lon2</i>), and
* (<i>lat2</i>,<i>lon2</i>). It can be used to compute the area of any
* geodesic polygon.
*
* Overloaded versions of Geodesic::Direct, Geodesic::ArcDirect, and
* Geodesic::Inverse allow these quantities to be returned. In addition
* there are general functions Geodesic::GenDirect, and Geodesic::GenInverse
* which allow an arbitrary set of results to be computed. The quantities \e
* m12, \e M12, \e M21 which all specify the behavior of nearby geodesics
* obey addition rules. If points 1, 2, and 3 all lie on a single geodesic,
* then the following rules hold:
* - \e s13 = \e s12 + \e s23
* - \e a13 = \e a12 + \e a23
* - \e S13 = \e S12 + \e S23
* - \e m13 = \e m12 \e M23 + \e m23 \e M21
* - \e M13 = \e M12 \e M23 &minus; (1 &minus; \e M12 \e M21) \e m23 / \e m12
* - \e M31 = \e M32 \e M21 &minus; (1 &minus; \e M23 \e M32) \e m12 / \e m23
*
* Additional functionality is provided by the GeodesicLine class, which
* allows a sequence of points along a geodesic to be computed.
*
* The shortest distance returned by the solution of the inverse problem is
* (obviously) uniquely defined. However, in a few special cases there are
* multiple azimuths which yield the same shortest distance. Here is a
* catalog of those cases:
* - \e lat1 = &minus;\e lat2 (with neither point at a pole). If \e azi1 =
* \e azi2, the geodesic is unique. Otherwise there are two geodesics and
* the second one is obtained by setting [\e azi1, \e azi2] &rarr; [\e
* azi2, \e azi1], [\e M12, \e M21] &rarr; [\e M21, \e M12], \e S12 &rarr;
* &minus;\e S12. (This occurs when the longitude difference is near
* &plusmn;180&deg; for oblate ellipsoids.)
* - \e lon2 = \e lon1 &plusmn; 180&deg; (with neither point at a pole). If
* \e azi1 = 0&deg; or &plusmn;180&deg;, the geodesic is unique. Otherwise
* there are two geodesics and the second one is obtained by setting [\e
* azi1, \e azi2] &rarr; [&minus;\e azi1, &minus;\e azi2], \e S12 &rarr;
* &minus;\e S12. (This occurs when \e lat2 is near &minus;\e lat1 for
* prolate ellipsoids.)
* - Points 1 and 2 at opposite poles. There are infinitely many geodesics
* which can be generated by setting [\e azi1, \e azi2] &rarr; [\e azi1, \e
* azi2] + [\e d, &minus;\e d], for arbitrary \e d. (For spheres, this
* prescription applies when points 1 and 2 are antipodal.)
* - \e s12 = 0 (coincident points). There are infinitely many geodesics
* which can be generated by setting [\e azi1, \e azi2] &rarr;
* [\e azi1, \e azi2] + [\e d, \e d], for arbitrary \e d.
*
* The calculations are accurate to better than 15 nm (15 nanometers) for the
* WGS84 ellipsoid. See Sec. 9 of
* <a href="https://arxiv.org/abs/1102.1215v1">arXiv:1102.1215v1</a> for
* details. The algorithms used by this class are based on series expansions
* using the flattening \e f as a small parameter. These are only accurate
* for |<i>f</i>| &lt; 0.02; however reasonably accurate results will be
* obtained for |<i>f</i>| &lt; 0.2. Here is a table of the approximate
* maximum error (expressed as a distance) for an ellipsoid with the same
* equatorial radius as the WGS84 ellipsoid and different values of the
* flattening.<pre>
* |f| error
* 0.01 25 nm
* 0.02 30 nm
* 0.05 10 um
* 0.1 1.5 mm
* 0.2 300 mm
* </pre>
* For very eccentric ellipsoids, use GeodesicExact instead.
*
* The algorithms are described in
* - C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-012-0578-z">
* Algorithms for geodesics</a>,
* J. Geodesy <b>87</b>, 43--55 (2013);
* DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
* 10.1007/s00190-012-0578-z</a>;
* addenda:
* <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
* geod-addenda.html</a>.
* .
* For more information on geodesics see \ref geodesic.
*
* Example of use:
* \include example-Geodesic.cpp
*
* <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility
* providing access to the functionality of Geodesic and GeodesicLine.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Geodesic {
private:
typedef Math::real real;
friend class GeodesicLine;
static const int nA1_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC1_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC1p_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nA2_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC2_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nA3_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nA3x_ = nA3_;
static const int nC3_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC3x_ = (nC3_ * (nC3_ - 1)) / 2;
static const int nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2;
// Size for temporary array
// nC = max(max(nC1_, nC1p_, nC2_) + 1, max(nC3_, nC4_))
static const int nC_ = GEOGRAPHICLIB_GEODESIC_ORDER + 1;
static const unsigned maxit1_ = 20;
unsigned maxit2_;
real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_;
enum captype {
CAP_NONE = 0U,
CAP_C1 = 1U<<0,
CAP_C1p = 1U<<1,
CAP_C2 = 1U<<2,
CAP_C3 = 1U<<3,
CAP_C4 = 1U<<4,
CAP_ALL = 0x1FU,
CAP_MASK = CAP_ALL,
OUT_ALL = 0x7F80U,
OUT_MASK = 0xFF80U, // Includes LONG_UNROLL
};
static real SinCosSeries(bool sinp,
real sinx, real cosx, const real c[], int n);
static real Astroid(real x, real y);
real _a, _f, _f1, _e2, _ep2, _n, _b, _c2, _etol2;
real _A3x[nA3x_], _C3x[nC3x_], _C4x[nC4x_];
void Lengths(real eps, real sig12,
real ssig1, real csig1, real dn1,
real ssig2, real csig2, real dn2,
real cbet1, real cbet2, unsigned outmask,
real& s12s, real& m12a, real& m0,
real& M12, real& M21, real Ca[]) const;
real InverseStart(real sbet1, real cbet1, real dn1,
real sbet2, real cbet2, real dn2,
real lam12, real slam12, real clam12,
real& salp1, real& calp1,
real& salp2, real& calp2, real& dnm,
real Ca[]) const;
real Lambda12(real sbet1, real cbet1, real dn1,
real sbet2, real cbet2, real dn2,
real salp1, real calp1, real slam120, real clam120,
real& salp2, real& calp2, real& sig12,
real& ssig1, real& csig1, real& ssig2, real& csig2,
real& eps, real& domg12,
bool diffp, real& dlam12, real Ca[]) const;
real GenInverse(real lat1, real lon1, real lat2, real lon2,
unsigned outmask, real& s12,
real& salp1, real& calp1, real& salp2, real& calp2,
real& m12, real& M12, real& M21, real& S12) const;
// These are Maxima generated functions to provide series approximations to
// the integrals for the ellipsoidal geodesic.
static real A1m1f(real eps);
static void C1f(real eps, real c[]);
static void C1pf(real eps, real c[]);
static real A2m1f(real eps);
static void C2f(real eps, real c[]);
void A3coeff();
real A3f(real eps) const;
void C3coeff();
void C3f(real eps, real c[]) const;
void C4coeff();
void C4f(real k2, real c[]) const;
public:
/**
* Bit masks for what calculations to do. These masks do double duty.
* They signify to the GeodesicLine::GeodesicLine constructor and to
* Geodesic::Line what capabilities should be included in the GeodesicLine
* object. They also specify which results to return in the general
* routines Geodesic::GenDirect and Geodesic::GenInverse routines.
* GeodesicLine::mask is a duplication of this enum.
**********************************************************************/
enum mask {
/**
* No capabilities, no output.
* @hideinitializer
**********************************************************************/
NONE = 0U,
/**
* Calculate latitude \e lat2. (It's not necessary to include this as a
* capability to GeodesicLine because this is included by default.)
* @hideinitializer
**********************************************************************/
LATITUDE = 1U<<7 | CAP_NONE,
/**
* Calculate longitude \e lon2.
* @hideinitializer
**********************************************************************/
LONGITUDE = 1U<<8 | CAP_C3,
/**
* Calculate azimuths \e azi1 and \e azi2. (It's not necessary to
* include this as a capability to GeodesicLine because this is included
* by default.)
* @hideinitializer
**********************************************************************/
AZIMUTH = 1U<<9 | CAP_NONE,
/**
* Calculate distance \e s12.
* @hideinitializer
**********************************************************************/
DISTANCE = 1U<<10 | CAP_C1,
/**
* Allow distance \e s12 to be used as input in the direct geodesic
* problem.
* @hideinitializer
**********************************************************************/
DISTANCE_IN = 1U<<11 | CAP_C1 | CAP_C1p,
/**
* Calculate reduced length \e m12.
* @hideinitializer
**********************************************************************/
REDUCEDLENGTH = 1U<<12 | CAP_C1 | CAP_C2,
/**
* Calculate geodesic scales \e M12 and \e M21.
* @hideinitializer
**********************************************************************/
GEODESICSCALE = 1U<<13 | CAP_C1 | CAP_C2,
/**
* Calculate area \e S12.
* @hideinitializer
**********************************************************************/
AREA = 1U<<14 | CAP_C4,
/**
* Unroll \e lon2 in the direct calculation.
* @hideinitializer
**********************************************************************/
LONG_UNROLL = 1U<<15,
/**
* All capabilities, calculate everything. (LONG_UNROLL is not
* included in this mask.)
* @hideinitializer
**********************************************************************/
ALL = OUT_ALL| CAP_ALL,
};
/** \name Constructor
**********************************************************************/
///@{
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* positive.
**********************************************************************/
Geodesic(real a, real f);
///@}
/** \name Direct geodesic problem specified in terms of distance.
**********************************************************************/
///@{
/**
* Solve the direct geodesic problem where the length of the geodesic
* is specified in terms of distance.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The values of
* \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
* 180&deg;].
*
* If either point is at a pole, the azimuth is defined by keeping the
* longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
* and taking the limit &epsilon; &rarr; 0+. An arc length greater that
* 180&deg; signifies a geodesic which is not a shortest path. (For a
* prolate ellipsoid, an additional condition is necessary for a shortest
* path: the longitudinal extent must not exceed of 180&deg;.)
*
* The following functions are overloaded versions of Geodesic::Direct
* which omit some of the output parameters. Note, however, that the arc
* length is always computed and returned as the function value.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21, real& S12)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, t, m12, M12, M21, S12);
}
/**
* See the documentation for Geodesic::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for Geodesic::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for Geodesic::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2, real& m12)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH | REDUCEDLENGTH,
lat2, lon2, azi2, t, m12, t, t, t);
}
/**
* See the documentation for Geodesic::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2,
real& M12, real& M21)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH | GEODESICSCALE,
lat2, lon2, azi2, t, t, M12, M21, t);
}
/**
* See the documentation for Geodesic::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, t, m12, M12, M21, t);
}
///@}
/** \name Direct geodesic problem specified in terms of arc length.
**********************************************************************/
///@{
/**
* Solve the direct geodesic problem where the length of the geodesic
* is specified in terms of arc length.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] a12 arc length between point 1 and point 2 (degrees); it can
* be negative.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The values of
* \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
* 180&deg;].
*
* If either point is at a pole, the azimuth is defined by keeping the
* longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
* and taking the limit &epsilon; &rarr; 0+. An arc length greater that
* 180&deg; signifies a geodesic which is not a shortest path. (For a
* prolate ellipsoid, an additional condition is necessary for a shortest
* path: the longitudinal extent must not exceed of 180&deg;.)
*
* The following functions are overloaded versions of Geodesic::Direct
* which omit some of the output parameters.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12,
real& m12, real& M12, real& M21, real& S12)
const {
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, s12, m12, M12, M21, S12);
}
/**
* See the documentation for Geodesic::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for Geodesic::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for Geodesic::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12)
const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
lat2, lon2, azi2, s12, t, t, t, t);
}
/**
* See the documentation for Geodesic::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2,
real& s12, real& m12) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH,
lat2, lon2, azi2, s12, m12, t, t, t);
}
/**
* See the documentation for Geodesic::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12,
real& M12, real& M21) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
GEODESICSCALE,
lat2, lon2, azi2, s12, t, M12, M21, t);
}
/**
* See the documentation for Geodesic::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12,
real& m12, real& M12, real& M21) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, s12, m12, M12, M21, t);
}
///@}
/** \name General version of the direct geodesic solution.
**********************************************************************/
///@{
/**
* The general direct geodesic problem. Geodesic::Direct and
* Geodesic::ArcDirect are defined in terms of this function.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] arcmode boolean flag determining the meaning of the \e
* s12_a12.
* @param[in] s12_a12 if \e arcmode is false, this is the distance between
* point 1 and point 2 (meters); otherwise it is the arc length between
* point 1 and point 2 (degrees); it can be negative.
* @param[in] outmask a bitor'ed combination of Geodesic::mask values
* specifying which of the following parameters should be set.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* The Geodesic::mask values possible for \e outmask are
* - \e outmask |= Geodesic::LATITUDE for the latitude \e lat2;
* - \e outmask |= Geodesic::LONGITUDE for the latitude \e lon2;
* - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2;
* - \e outmask |= Geodesic::DISTANCE for the distance \e s12;
* - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e
* m12;
* - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
* M12 and \e M21;
* - \e outmask |= Geodesic::AREA for the area \e S12;
* - \e outmask |= Geodesic::ALL for all of the above;
* - \e outmask |= Geodesic::LONG_UNROLL to unroll \e lon2 instead of
* wrapping it into the range [&minus;180&deg;, 180&deg;].
* .
* The function value \e a12 is always computed and returned and this
* equals \e s12_a12 is \e arcmode is true. If \e outmask includes
* Geodesic::DISTANCE and \e arcmode is false, then \e s12 = \e s12_a12.
* It is not necessary to include Geodesic::DISTANCE_IN in \e outmask; this
* is automatically included is \e arcmode is false.
*
* With the Geodesic::LONG_UNROLL bit set, the quantity \e lon2 &minus; \e
* lon1 indicates how many times and in what sense the geodesic encircles
* the ellipsoid.
**********************************************************************/
Math::real GenDirect(real lat1, real lon1, real azi1,
bool arcmode, real s12_a12, unsigned outmask,
real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21,
real& S12) const;
///@}
/** \name Inverse geodesic problem.
**********************************************************************/
///@{
/**
* Solve the inverse geodesic problem.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] azi1 azimuth at point 1 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
* The values of \e azi1 and \e azi2 returned are in the range
* [&minus;180&deg;, 180&deg;].
*
* If either point is at a pole, the azimuth is defined by keeping the
* longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
* and taking the limit &epsilon; &rarr; 0+.
*
* The solution to the inverse problem is found using Newton's method. If
* this fails to converge (this is very unlikely in geodetic applications
* but does occur for very eccentric ellipsoids), then the bisection method
* is used to refine the solution.
*
* The following functions are overloaded versions of Geodesic::Inverse
* which omit some of the output parameters. Note, however, that the arc
* length is always computed and returned as the function value.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2, real& m12,
real& M12, real& M21, real& S12) const {
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE | AREA,
s12, azi1, azi2, m12, M12, M21, S12);
}
/**
* See the documentation for Geodesic::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE,
s12, t, t, t, t, t, t);
}
/**
* See the documentation for Geodesic::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& azi1, real& azi2) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
AZIMUTH,
t, azi1, azi2, t, t, t, t);
}
/**
* See the documentation for Geodesic::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2)
const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH,
s12, azi1, azi2, t, t, t, t);
}
/**
* See the documentation for Geodesic::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2, real& m12)
const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH | REDUCEDLENGTH,
s12, azi1, azi2, m12, t, t, t);
}
/**
* See the documentation for Geodesic::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2,
real& M12, real& M21) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH | GEODESICSCALE,
s12, azi1, azi2, t, M12, M21, t);
}
/**
* See the documentation for Geodesic::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2, real& m12,
real& M12, real& M21) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE,
s12, azi1, azi2, m12, M12, M21, t);
}
///@}
/** \name General version of inverse geodesic solution.
**********************************************************************/
///@{
/**
* The general inverse geodesic calculation. Geodesic::Inverse is defined
* in terms of this function.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[in] outmask a bitor'ed combination of Geodesic::mask values
* specifying which of the following parameters should be set.
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] azi1 azimuth at point 1 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* The Geodesic::mask values possible for \e outmask are
* - \e outmask |= Geodesic::DISTANCE for the distance \e s12;
* - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2;
* - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e
* m12;
* - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
* M12 and \e M21;
* - \e outmask |= Geodesic::AREA for the area \e S12;
* - \e outmask |= Geodesic::ALL for all of the above.
* .
* The arc length is always computed and returned as the function value.
**********************************************************************/
Math::real GenInverse(real lat1, real lon1, real lat2, real lon2,
unsigned outmask,
real& s12, real& azi1, real& azi2,
real& m12, real& M12, real& M21, real& S12) const;
///@}
/** \name Interface to GeodesicLine.
**********************************************************************/
///@{
/**
* Set up to compute several points on a single geodesic.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] caps bitor'ed combination of Geodesic::mask values
* specifying the capabilities the GeodesicLine object should possess,
* i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
* @return a GeodesicLine object.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
*
* The Geodesic::mask values are
* - \e caps |= Geodesic::LATITUDE for the latitude \e lat2; this is
* added automatically;
* - \e caps |= Geodesic::LONGITUDE for the latitude \e lon2;
* - \e caps |= Geodesic::AZIMUTH for the azimuth \e azi2; this is
* added automatically;
* - \e caps |= Geodesic::DISTANCE for the distance \e s12;
* - \e caps |= Geodesic::REDUCEDLENGTH for the reduced length \e m12;
* - \e caps |= Geodesic::GEODESICSCALE for the geodesic scales \e M12
* and \e M21;
* - \e caps |= Geodesic::AREA for the area \e S12;
* - \e caps |= Geodesic::DISTANCE_IN permits the length of the
* geodesic to be given in terms of \e s12; without this capability the
* length can only be specified in terms of arc length;
* - \e caps |= Geodesic::ALL for all of the above.
* .
* The default value of \e caps is Geodesic::ALL.
*
* If the point is at a pole, the azimuth is defined by keeping \e lon1
* fixed, writing \e lat1 = &plusmn;(90 &minus; &epsilon;), and taking the
* limit &epsilon; &rarr; 0+.
**********************************************************************/
GeodesicLine Line(real lat1, real lon1, real azi1, unsigned caps = ALL)
const;
/**
* Define a GeodesicLine in terms of the inverse geodesic problem.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[in] caps bitor'ed combination of Geodesic::mask values
* specifying the capabilities the GeodesicLine object should possess,
* i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
* @return a GeodesicLine object.
*
* This function sets point 3 of the GeodesicLine to correspond to point 2
* of the inverse geodesic problem.
*
* \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLine InverseLine(real lat1, real lon1, real lat2, real lon2,
unsigned caps = ALL) const;
/**
* Define a GeodesicLine in terms of the direct geodesic problem specified
* in terms of distance.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[in] caps bitor'ed combination of Geodesic::mask values
* specifying the capabilities the GeodesicLine object should possess,
* i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
* @return a GeodesicLine object.
*
* This function sets point 3 of the GeodesicLine to correspond to point 2
* of the direct geodesic problem.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLine DirectLine(real lat1, real lon1, real azi1, real s12,
unsigned caps = ALL) const;
/**
* Define a GeodesicLine in terms of the direct geodesic problem specified
* in terms of arc length.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] a12 arc length between point 1 and point 2 (degrees); it can
* be negative.
* @param[in] caps bitor'ed combination of Geodesic::mask values
* specifying the capabilities the GeodesicLine object should possess,
* i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
* @return a GeodesicLine object.
*
* This function sets point 3 of the GeodesicLine to correspond to point 2
* of the direct geodesic problem.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLine ArcDirectLine(real lat1, real lon1, real azi1, real a12,
unsigned caps = ALL) const;
/**
* Define a GeodesicLine in terms of the direct geodesic problem specified
* in terms of either distance or arc length.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] arcmode boolean flag determining the meaning of the \e
* s12_a12.
* @param[in] s12_a12 if \e arcmode is false, this is the distance between
* point 1 and point 2 (meters); otherwise it is the arc length between
* point 1 and point 2 (degrees); it can be negative.
* @param[in] caps bitor'ed combination of Geodesic::mask values
* specifying the capabilities the GeodesicLine object should possess,
* i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
* @return a GeodesicLine object.
*
* This function sets point 3 of the GeodesicLine to correspond to point 2
* of the direct geodesic problem.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLine GenDirectLine(real lat1, real lon1, real azi1,
bool arcmode, real s12_a12,
unsigned caps = ALL) const;
///@}
/** \name Inspector functions.
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the
* value used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return total area of ellipsoid in meters<sup>2</sup>. The area of a
* polygon encircling a pole can be found by adding
* Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the
* polygon.
**********************************************************************/
Math::real EllipsoidArea() const
{ return 4 * Math::pi() * _c2; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of Geodesic with the parameters for the WGS84
* ellipsoid.
**********************************************************************/
static const Geodesic& WGS84();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEODESIC_HPP

869
external/include/GeographicLib/GeodesicExact.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,869 @@
/**
* \file GeodesicExact.hpp
* \brief Header for GeographicLib::GeodesicExact class
*
* Copyright (c) Charles Karney (2012-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEODESICEXACT_HPP)
#define GEOGRAPHICLIB_GEODESICEXACT_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/EllipticFunction.hpp>
#if !defined(GEOGRAPHICLIB_GEODESICEXACT_ORDER)
/**
* The order of the expansions used by GeodesicExact.
**********************************************************************/
# define GEOGRAPHICLIB_GEODESICEXACT_ORDER 30
#endif
namespace GeographicLib {
class GeodesicLineExact;
/**
* \brief Exact geodesic calculations
*
* The equations for geodesics on an ellipsoid can be expressed in terms of
* incomplete elliptic integrals. The Geodesic class expands these integrals
* in a series in the flattening \e f and this provides an accurate solution
* for \e f &isin; [-0.01, 0.01]. The GeodesicExact class computes the
* ellitpic integrals directly and so provides a solution which is valid for
* all \e f. However, in practice, its use should be limited to about
* <i>b</i>/\e a &isin; [0.01, 100] or \e f &isin; [&minus;99, 0.99].
*
* For the WGS84 ellipsoid, these classes are 2--3 times \e slower than the
* series solution and 2--3 times \e less \e accurate (because it's less easy
* to control round-off errors with the elliptic integral formulation); i.e.,
* the error is about 40 nm (40 nanometers) instead of 15 nm. However the
* error in the series solution scales as <i>f</i><sup>7</sup> while the
* error in the elliptic integral solution depends weakly on \e f. If the
* quarter meridian distance is 10000 km and the ratio <i>b</i>/\e a = 1
* &minus; \e f is varied then the approximate maximum error (expressed as a
* distance) is <pre>
* 1 - f error (nm)
* 1/128 387
* 1/64 345
* 1/32 269
* 1/16 210
* 1/8 115
* 1/4 69
* 1/2 36
* 1 15
* 2 25
* 4 96
* 8 318
* 16 985
* 32 2352
* 64 6008
* 128 19024
* </pre>
*
* The computation of the area in these classes is via a 30th order series.
* This gives accurate results for <i>b</i>/\e a &isin; [1/2, 2]; the
* accuracy is about 8 decimal digits for <i>b</i>/\e a &isin; [1/4, 4].
*
* See \ref geodellip for the formulation. See the documentation on the
* Geodesic class for additional information on the geodesic problems.
*
* Example of use:
* \include example-GeodesicExact.cpp
*
* <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility
* providing access to the functionality of GeodesicExact and
* GeodesicLineExact (via the -E option).
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GeodesicExact {
private:
typedef Math::real real;
friend class GeodesicLineExact;
static const int nC4_ = GEOGRAPHICLIB_GEODESICEXACT_ORDER;
static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2;
static const unsigned maxit1_ = 20;
unsigned maxit2_;
real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_;
enum captype {
CAP_NONE = 0U,
CAP_E = 1U<<0,
// Skip 1U<<1 for compatibility with Geodesic (not required)
CAP_D = 1U<<2,
CAP_H = 1U<<3,
CAP_C4 = 1U<<4,
CAP_ALL = 0x1FU,
CAP_MASK = CAP_ALL,
OUT_ALL = 0x7F80U,
OUT_MASK = 0xFF80U, // Includes LONG_UNROLL
};
static real CosSeries(real sinx, real cosx, const real c[], int n);
static real Astroid(real x, real y);
real _a, _f, _f1, _e2, _ep2, _n, _b, _c2, _etol2;
real _C4x[nC4x_];
void Lengths(const EllipticFunction& E,
real sig12,
real ssig1, real csig1, real dn1,
real ssig2, real csig2, real dn2,
real cbet1, real cbet2, unsigned outmask,
real& s12s, real& m12a, real& m0,
real& M12, real& M21) const;
real InverseStart(EllipticFunction& E,
real sbet1, real cbet1, real dn1,
real sbet2, real cbet2, real dn2,
real lam12, real slam12, real clam12,
real& salp1, real& calp1,
real& salp2, real& calp2, real& dnm) const;
real Lambda12(real sbet1, real cbet1, real dn1,
real sbet2, real cbet2, real dn2,
real salp1, real calp1, real slam120, real clam120,
real& salp2, real& calp2, real& sig12,
real& ssig1, real& csig1, real& ssig2, real& csig2,
EllipticFunction& E,
real& domg12, bool diffp, real& dlam12) const;
real GenInverse(real lat1, real lon1, real lat2, real lon2,
unsigned outmask, real& s12,
real& salp1, real& calp1, real& salp2, real& calp2,
real& m12, real& M12, real& M21, real& S12) const;
// These are Maxima generated functions to provide series approximations to
// the integrals for the area.
void C4coeff();
void C4f(real k2, real c[]) const;
// Large coefficients are split so that lo contains the low 52 bits and hi
// the rest. This choice avoids double rounding with doubles and higher
// precision types. float coefficients will suffer double rounding;
// however the accuracy is already lousy for floats.
static Math::real reale(long long hi, long long lo) {
using std::ldexp;
return ldexp(real(hi), 52) + lo;
}
public:
/**
* Bit masks for what calculations to do. These masks do double duty.
* They signify to the GeodesicLineExact::GeodesicLineExact constructor and
* to GeodesicExact::Line what capabilities should be included in the
* GeodesicLineExact object. They also specify which results to return in
* the general routines GeodesicExact::GenDirect and
* GeodesicExact::GenInverse routines. GeodesicLineExact::mask is a
* duplication of this enum.
**********************************************************************/
enum mask {
/**
* No capabilities, no output.
* @hideinitializer
**********************************************************************/
NONE = 0U,
/**
* Calculate latitude \e lat2. (It's not necessary to include this as a
* capability to GeodesicLineExact because this is included by default.)
* @hideinitializer
**********************************************************************/
LATITUDE = 1U<<7 | CAP_NONE,
/**
* Calculate longitude \e lon2.
* @hideinitializer
**********************************************************************/
LONGITUDE = 1U<<8 | CAP_H,
/**
* Calculate azimuths \e azi1 and \e azi2. (It's not necessary to
* include this as a capability to GeodesicLineExact because this is
* included by default.)
* @hideinitializer
**********************************************************************/
AZIMUTH = 1U<<9 | CAP_NONE,
/**
* Calculate distance \e s12.
* @hideinitializer
**********************************************************************/
DISTANCE = 1U<<10 | CAP_E,
/**
* Allow distance \e s12 to be used as input in the direct geodesic
* problem.
* @hideinitializer
**********************************************************************/
DISTANCE_IN = 1U<<11 | CAP_E,
/**
* Calculate reduced length \e m12.
* @hideinitializer
**********************************************************************/
REDUCEDLENGTH = 1U<<12 | CAP_D,
/**
* Calculate geodesic scales \e M12 and \e M21.
* @hideinitializer
**********************************************************************/
GEODESICSCALE = 1U<<13 | CAP_D,
/**
* Calculate area \e S12.
* @hideinitializer
**********************************************************************/
AREA = 1U<<14 | CAP_C4,
/**
* Unroll \e lon2 in the direct calculation.
* @hideinitializer
**********************************************************************/
LONG_UNROLL = 1U<<15,
/**
* All capabilities, calculate everything. (LONG_UNROLL is not
* included in this mask.)
* @hideinitializer
**********************************************************************/
ALL = OUT_ALL| CAP_ALL,
};
/** \name Constructor
**********************************************************************/
///@{
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* positive.
**********************************************************************/
GeodesicExact(real a, real f);
///@}
/** \name Direct geodesic problem specified in terms of distance.
**********************************************************************/
///@{
/**
* Perform the direct geodesic calculation where the length of the geodesic
* is specified in terms of distance.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* signed.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The values of
* \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
* 180&deg;].
*
* If either point is at a pole, the azimuth is defined by keeping the
* longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
* and taking the limit &epsilon; &rarr; 0+. An arc length greater that
* 180&deg; signifies a geodesic which is not a shortest path. (For a
* prolate ellipsoid, an additional condition is necessary for a shortest
* path: the longitudinal extent must not exceed of 180&deg;.)
*
* The following functions are overloaded versions of GeodesicExact::Direct
* which omit some of the output parameters. Note, however, that the arc
* length is always computed and returned as the function value.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21, real& S12)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, t, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicExact::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2, real& m12)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH | REDUCEDLENGTH,
lat2, lon2, azi2, t, m12, t, t, t);
}
/**
* See the documentation for GeodesicExact::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2,
real& M12, real& M21)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH | GEODESICSCALE,
lat2, lon2, azi2, t, t, M12, M21, t);
}
/**
* See the documentation for GeodesicExact::Direct.
**********************************************************************/
Math::real Direct(real lat1, real lon1, real azi1, real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21)
const {
real t;
return GenDirect(lat1, lon1, azi1, false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, t, m12, M12, M21, t);
}
///@}
/** \name Direct geodesic problem specified in terms of arc length.
**********************************************************************/
///@{
/**
* Perform the direct geodesic calculation where the length of the geodesic
* is specified in terms of arc length.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] a12 arc length between point 1 and point 2 (degrees); it can
* be signed.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The values of
* \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
* 180&deg;].
*
* If either point is at a pole, the azimuth is defined by keeping the
* longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
* and taking the limit &epsilon; &rarr; 0+. An arc length greater that
* 180&deg; signifies a geodesic which is not a shortest path. (For a
* prolate ellipsoid, an additional condition is necessary for a shortest
* path: the longitudinal extent must not exceed of 180&deg;.)
*
* The following functions are overloaded versions of GeodesicExact::Direct
* which omit some of the output parameters.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12,
real& m12, real& M12, real& M21, real& S12)
const {
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, s12, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicExact::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12)
const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
lat2, lon2, azi2, s12, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2,
real& s12, real& m12) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH,
lat2, lon2, azi2, s12, m12, t, t, t);
}
/**
* See the documentation for GeodesicExact::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12,
real& M12, real& M21) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
GEODESICSCALE,
lat2, lon2, azi2, s12, t, M12, M21, t);
}
/**
* See the documentation for GeodesicExact::ArcDirect.
**********************************************************************/
void ArcDirect(real lat1, real lon1, real azi1, real a12,
real& lat2, real& lon2, real& azi2, real& s12,
real& m12, real& M12, real& M21) const {
real t;
GenDirect(lat1, lon1, azi1, true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, s12, m12, M12, M21, t);
}
///@}
/** \name General version of the direct geodesic solution.
**********************************************************************/
///@{
/**
* The general direct geodesic calculation. GeodesicExact::Direct and
* GeodesicExact::ArcDirect are defined in terms of this function.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] arcmode boolean flag determining the meaning of the second
* parameter.
* @param[in] s12_a12 if \e arcmode is false, this is the distance between
* point 1 and point 2 (meters); otherwise it is the arc length between
* point 1 and point 2 (degrees); it can be signed.
* @param[in] outmask a bitor'ed combination of GeodesicExact::mask values
* specifying which of the following parameters should be set.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* The GeodesicExact::mask values possible for \e outmask are
* - \e outmask |= GeodesicExact::LATITUDE for the latitude \e lat2;
* - \e outmask |= GeodesicExact::LONGITUDE for the latitude \e lon2;
* - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2;
* - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12;
* - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e
* m12;
* - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
* M12 and \e M21;
* - \e outmask |= GeodesicExact::AREA for the area \e S12;
* - \e outmask |= GeodesicExact::ALL for all of the above;
* - \e outmask |= GeodesicExact::LONG_UNROLL to unroll \e lon2 instead of
* wrapping it into the range [&minus;180&deg;, 180&deg;].
* .
* The function value \e a12 is always computed and returned and this
* equals \e s12_a12 is \e arcmode is true. If \e outmask includes
* GeodesicExact::DISTANCE and \e arcmode is false, then \e s12 = \e
* s12_a12. It is not necessary to include GeodesicExact::DISTANCE_IN in
* \e outmask; this is automatically included is \e arcmode is false.
*
* With the GeodesicExact::LONG_UNROLL bit set, the quantity \e lon2
* &minus; \e lon1 indicates how many times and in what sense the geodesic
* encircles the ellipsoid.
**********************************************************************/
Math::real GenDirect(real lat1, real lon1, real azi1,
bool arcmode, real s12_a12, unsigned outmask,
real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21,
real& S12) const;
///@}
/** \name Inverse geodesic problem.
**********************************************************************/
///@{
/**
* Perform the inverse geodesic calculation.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] azi1 azimuth at point 1 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
* The values of \e azi1 and \e azi2 returned are in the range
* [&minus;180&deg;, 180&deg;].
*
* If either point is at a pole, the azimuth is defined by keeping the
* longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
* and taking the limit &epsilon; &rarr; 0+.
*
* The following functions are overloaded versions of
* GeodesicExact::Inverse which omit some of the output parameters. Note,
* however, that the arc length is always computed and returned as the
* function value.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2, real& m12,
real& M12, real& M21, real& S12) const {
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE | AREA,
s12, azi1, azi2, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicExact::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE,
s12, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& azi1, real& azi2) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
AZIMUTH,
t, azi1, azi2, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2)
const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH,
s12, azi1, azi2, t, t, t, t);
}
/**
* See the documentation for GeodesicExact::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2, real& m12)
const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH | REDUCEDLENGTH,
s12, azi1, azi2, m12, t, t, t);
}
/**
* See the documentation for GeodesicExact::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2,
real& M12, real& M21) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH | GEODESICSCALE,
s12, azi1, azi2, t, M12, M21, t);
}
/**
* See the documentation for GeodesicExact::Inverse.
**********************************************************************/
Math::real Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi1, real& azi2, real& m12,
real& M12, real& M21) const {
real t;
return GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE,
s12, azi1, azi2, m12, M12, M21, t);
}
///@}
/** \name General version of inverse geodesic solution.
**********************************************************************/
///@{
/**
* The general inverse geodesic calculation. GeodesicExact::Inverse is
* defined in terms of this function.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[in] outmask a bitor'ed combination of GeodesicExact::mask values
* specifying which of the following parameters should be set.
* @param[out] s12 distance between point 1 and point 2 (meters).
* @param[out] azi1 azimuth at point 1 (degrees).
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters).
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless).
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless).
* @param[out] S12 area under the geodesic (meters<sup>2</sup>).
* @return \e a12 arc length of between point 1 and point 2 (degrees).
*
* The GeodesicExact::mask values possible for \e outmask are
* - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12;
* - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2;
* - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e
* m12;
* - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
* M12 and \e M21;
* - \e outmask |= GeodesicExact::AREA for the area \e S12;
* - \e outmask |= GeodesicExact::ALL for all of the above.
* .
* The arc length is always computed and returned as the function value.
**********************************************************************/
Math::real GenInverse(real lat1, real lon1, real lat2, real lon2,
unsigned outmask,
real& s12, real& azi1, real& azi2,
real& m12, real& M12, real& M21, real& S12) const;
///@}
/** \name Interface to GeodesicLineExact.
**********************************************************************/
///@{
/**
* Set up to compute several points on a single geodesic.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] caps bitor'ed combination of GeodesicExact::mask values
* specifying the capabilities the GeodesicLineExact object should
* possess, i.e., which quantities can be returned in calls to
* GeodesicLineExact::Position.
* @return a GeodesicLineExact object.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
*
* The GeodesicExact::mask values are
* - \e caps |= GeodesicExact::LATITUDE for the latitude \e lat2; this is
* added automatically;
* - \e caps |= GeodesicExact::LONGITUDE for the latitude \e lon2;
* - \e caps |= GeodesicExact::AZIMUTH for the azimuth \e azi2; this is
* added automatically;
* - \e caps |= GeodesicExact::DISTANCE for the distance \e s12;
* - \e caps |= GeodesicExact::REDUCEDLENGTH for the reduced length \e m12;
* - \e caps |= GeodesicExact::GEODESICSCALE for the geodesic scales \e M12
* and \e M21;
* - \e caps |= GeodesicExact::AREA for the area \e S12;
* - \e caps |= GeodesicExact::DISTANCE_IN permits the length of the
* geodesic to be given in terms of \e s12; without this capability the
* length can only be specified in terms of arc length;
* - \e caps |= GeodesicExact::ALL for all of the above.
* .
* The default value of \e caps is GeodesicExact::ALL which turns on all
* the capabilities.
*
* If the point is at a pole, the azimuth is defined by keeping \e lon1
* fixed, writing \e lat1 = &plusmn;(90 &minus; &epsilon;), and taking the
* limit &epsilon; &rarr; 0+.
**********************************************************************/
GeodesicLineExact Line(real lat1, real lon1, real azi1,
unsigned caps = ALL) const;
/**
* Define a GeodesicLineExact in terms of the inverse geodesic problem.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[in] caps bitor'ed combination of GeodesicExact::mask values
* specifying the capabilities the GeodesicLineExact object should
* possess, i.e., which quantities can be returned in calls to
* GeodesicLineExact::Position.
* @return a GeodesicLineExact object.
*
* This function sets point 3 of the GeodesicLineExact to correspond to
* point 2 of the inverse geodesic problem.
*
* \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLineExact InverseLine(real lat1, real lon1, real lat2, real lon2,
unsigned caps = ALL) const;
/**
* Define a GeodesicLineExact in terms of the direct geodesic problem
* specified in terms of distance.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[in] caps bitor'ed combination of GeodesicExact::mask values
* specifying the capabilities the GeodesicLineExact object should
* possess, i.e., which quantities can be returned in calls to
* GeodesicLineExact::Position.
* @return a GeodesicLineExact object.
*
* This function sets point 3 of the GeodesicLineExact to correspond to
* point 2 of the direct geodesic problem.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLineExact DirectLine(real lat1, real lon1, real azi1, real s12,
unsigned caps = ALL) const;
/**
* Define a GeodesicLineExact in terms of the direct geodesic problem
* specified in terms of arc length.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] a12 arc length between point 1 and point 2 (degrees); it can
* be negative.
* @param[in] caps bitor'ed combination of GeodesicExact::mask values
* specifying the capabilities the GeodesicLineExact object should
* possess, i.e., which quantities can be returned in calls to
* GeodesicLineExact::Position.
* @return a GeodesicLineExact object.
*
* This function sets point 3 of the GeodesicLineExact to correspond to
* point 2 of the direct geodesic problem.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLineExact ArcDirectLine(real lat1, real lon1, real azi1, real a12,
unsigned caps = ALL) const;
/**
* Define a GeodesicLineExact in terms of the direct geodesic problem
* specified in terms of either distance or arc length.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] arcmode boolean flag determining the meaning of the \e
* s12_a12.
* @param[in] s12_a12 if \e arcmode is false, this is the distance between
* point 1 and point 2 (meters); otherwise it is the arc length between
* point 1 and point 2 (degrees); it can be negative.
* @param[in] caps bitor'ed combination of GeodesicExact::mask values
* specifying the capabilities the GeodesicLineExact object should
* possess, i.e., which quantities can be returned in calls to
* GeodesicLineExact::Position.
* @return a GeodesicLineExact object.
*
* This function sets point 3 of the GeodesicLineExact to correspond to
* point 2 of the direct geodesic problem.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
GeodesicLineExact GenDirectLine(real lat1, real lon1, real azi1,
bool arcmode, real s12_a12,
unsigned caps = ALL) const;
///@}
/** \name Inspector functions.
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the
* value used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return total area of ellipsoid in meters<sup>2</sup>. The area of a
* polygon encircling a pole can be found by adding
* GeodesicExact::EllipsoidArea()/2 to the sum of \e S12 for each side of
* the polygon.
**********************************************************************/
Math::real EllipsoidArea() const
{ return 4 * Math::pi() * _c2; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of GeodesicExact with the parameters for the
* WGS84 ellipsoid.
**********************************************************************/
static const GeodesicExact& WGS84();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEODESICEXACT_HPP

708
external/include/GeographicLib/GeodesicLine.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,708 @@
/**
* \file GeodesicLine.hpp
* \brief Header for GeographicLib::GeodesicLine class
*
* Copyright (c) Charles Karney (2009-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEODESICLINE_HPP)
#define GEOGRAPHICLIB_GEODESICLINE_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/Geodesic.hpp>
namespace GeographicLib {
/**
* \brief A geodesic line
*
* GeodesicLine facilitates the determination of a series of points on a
* single geodesic. The starting point (\e lat1, \e lon1) and the azimuth \e
* azi1 are specified in the constructor; alternatively, the Geodesic::Line
* method can be used to create a GeodesicLine. GeodesicLine.Position
* returns the location of point 2 a distance \e s12 along the geodesic. In
* addition, GeodesicLine.ArcPosition gives the position of point 2 an arc
* length \e a12 along the geodesic.
*
* You can register the position of a reference point 3 a distance (arc
* length), \e s13 (\e a13) along the geodesic with the
* GeodesicLine.SetDistance (GeodesicLine.SetArc) functions. Points a
* fractional distance along the line can be found by providing, for example,
* 0.5 * Distance() as an argument to GeodesicLine.Position. The
* Geodesic::InverseLine or Geodesic::DirectLine methods return GeodesicLine
* objects with point 3 set to the point 2 of the corresponding geodesic
* problem. GeodesicLine objects created with the public constructor or with
* Geodesic::Line have \e s13 and \e a13 set to NaNs.
*
* The default copy constructor and assignment operators work with this
* class. Similarly, a vector can be used to hold GeodesicLine objects.
*
* The calculations are accurate to better than 15 nm (15 nanometers). See
* Sec. 9 of
* <a href="https://arxiv.org/abs/1102.1215v1">arXiv:1102.1215v1</a> for
* details. The algorithms used by this class are based on series expansions
* using the flattening \e f as a small parameter. These are only accurate
* for |<i>f</i>| &lt; 0.02; however reasonably accurate results will be
* obtained for |<i>f</i>| &lt; 0.2. For very eccentric ellipsoids, use
* GeodesicLineExact instead.
*
* The algorithms are described in
* - C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-012-0578-z">
* Algorithms for geodesics</a>,
* J. Geodesy <b>87</b>, 43--55 (2013);
* DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
* 10.1007/s00190-012-0578-z</a>;
* addenda:
* <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
* geod-addenda.html</a>.
* .
* For more information on geodesics see \ref geodesic.
*
* Example of use:
* \include example-GeodesicLine.cpp
*
* <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility
* providing access to the functionality of Geodesic and GeodesicLine.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GeodesicLine {
private:
typedef Math::real real;
friend class Geodesic;
static const int nC1_ = Geodesic::nC1_;
static const int nC1p_ = Geodesic::nC1p_;
static const int nC2_ = Geodesic::nC2_;
static const int nC3_ = Geodesic::nC3_;
static const int nC4_ = Geodesic::nC4_;
real tiny_;
real _lat1, _lon1, _azi1;
real _a, _f, _b, _c2, _f1, _salp0, _calp0, _k2,
_salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1, _somg1, _comg1,
_A1m1, _A2m1, _A3c, _B11, _B21, _B31, _A4, _B41;
real _a13, _s13;
// index zero elements of _C1a, _C1pa, _C2a, _C3a are unused
real _C1a[nC1_ + 1], _C1pa[nC1p_ + 1], _C2a[nC2_ + 1], _C3a[nC3_],
_C4a[nC4_]; // all the elements of _C4a are used
unsigned _caps;
void LineInit(const Geodesic& g,
real lat1, real lon1,
real azi1, real salp1, real calp1,
unsigned caps);
GeodesicLine(const Geodesic& g,
real lat1, real lon1,
real azi1, real salp1, real calp1,
unsigned caps, bool arcmode, real s13_a13);
enum captype {
CAP_NONE = Geodesic::CAP_NONE,
CAP_C1 = Geodesic::CAP_C1,
CAP_C1p = Geodesic::CAP_C1p,
CAP_C2 = Geodesic::CAP_C2,
CAP_C3 = Geodesic::CAP_C3,
CAP_C4 = Geodesic::CAP_C4,
CAP_ALL = Geodesic::CAP_ALL,
CAP_MASK = Geodesic::CAP_MASK,
OUT_ALL = Geodesic::OUT_ALL,
OUT_MASK = Geodesic::OUT_MASK,
};
public:
/**
* Bit masks for what calculations to do. They signify to the
* GeodesicLine::GeodesicLine constructor and to Geodesic::Line what
* capabilities should be included in the GeodesicLine object. This is
* merely a duplication of Geodesic::mask.
**********************************************************************/
enum mask {
/**
* No capabilities, no output.
* @hideinitializer
**********************************************************************/
NONE = Geodesic::NONE,
/**
* Calculate latitude \e lat2. (It's not necessary to include this as a
* capability to GeodesicLine because this is included by default.)
* @hideinitializer
**********************************************************************/
LATITUDE = Geodesic::LATITUDE,
/**
* Calculate longitude \e lon2.
* @hideinitializer
**********************************************************************/
LONGITUDE = Geodesic::LONGITUDE,
/**
* Calculate azimuths \e azi1 and \e azi2. (It's not necessary to
* include this as a capability to GeodesicLine because this is included
* by default.)
* @hideinitializer
**********************************************************************/
AZIMUTH = Geodesic::AZIMUTH,
/**
* Calculate distance \e s12.
* @hideinitializer
**********************************************************************/
DISTANCE = Geodesic::DISTANCE,
/**
* Allow distance \e s12 to be used as input in the direct geodesic
* problem.
* @hideinitializer
**********************************************************************/
DISTANCE_IN = Geodesic::DISTANCE_IN,
/**
* Calculate reduced length \e m12.
* @hideinitializer
**********************************************************************/
REDUCEDLENGTH = Geodesic::REDUCEDLENGTH,
/**
* Calculate geodesic scales \e M12 and \e M21.
* @hideinitializer
**********************************************************************/
GEODESICSCALE = Geodesic::GEODESICSCALE,
/**
* Calculate area \e S12.
* @hideinitializer
**********************************************************************/
AREA = Geodesic::AREA,
/**
* Unroll \e lon2 in the direct calculation.
* @hideinitializer
**********************************************************************/
LONG_UNROLL = Geodesic::LONG_UNROLL,
/**
* All capabilities, calculate everything. (LONG_UNROLL is not
* included in this mask.)
* @hideinitializer
**********************************************************************/
ALL = Geodesic::ALL,
};
/** \name Constructors
**********************************************************************/
///@{
/**
* Constructor for a geodesic line staring at latitude \e lat1, longitude
* \e lon1, and azimuth \e azi1 (all in degrees).
*
* @param[in] g A Geodesic object used to compute the necessary information
* about the GeodesicLine.
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] caps bitor'ed combination of GeodesicLine::mask values
* specifying the capabilities the GeodesicLine object should possess,
* i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
*
* The GeodesicLine::mask values are
* - \e caps |= GeodesicLine::LATITUDE for the latitude \e lat2; this is
* added automatically;
* - \e caps |= GeodesicLine::LONGITUDE for the latitude \e lon2;
* - \e caps |= GeodesicLine::AZIMUTH for the latitude \e azi2; this is
* added automatically;
* - \e caps |= GeodesicLine::DISTANCE for the distance \e s12;
* - \e caps |= GeodesicLine::REDUCEDLENGTH for the reduced length \e m12;
* - \e caps |= GeodesicLine::GEODESICSCALE for the geodesic scales \e M12
* and \e M21;
* - \e caps |= GeodesicLine::AREA for the area \e S12;
* - \e caps |= GeodesicLine::DISTANCE_IN permits the length of the
* geodesic to be given in terms of \e s12; without this capability the
* length can only be specified in terms of arc length;
* - \e caps |= GeodesicLine::ALL for all of the above.
* .
* The default value of \e caps is GeodesicLine::ALL.
*
* If the point is at a pole, the azimuth is defined by keeping \e lon1
* fixed, writing \e lat1 = &plusmn;(90&deg; &minus; &epsilon;), and taking
* the limit &epsilon; &rarr; 0+.
**********************************************************************/
GeodesicLine(const Geodesic& g, real lat1, real lon1, real azi1,
unsigned caps = ALL);
/**
* A default constructor. If GeodesicLine::Position is called on the
* resulting object, it returns immediately (without doing any
* calculations). The object can be set with a call to Geodesic::Line.
* Use Init() to test whether object is still in this uninitialized state.
**********************************************************************/
GeodesicLine() : _caps(0U) {}
///@}
/** \name Position in terms of distance
**********************************************************************/
///@{
/**
* Compute the position of point 2 which is a distance \e s12 (meters) from
* point 1.
*
* @param[in] s12 distance from point 1 to point 2 (meters); it can be
* negative.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees); requires that the
* GeodesicLine object was constructed with \e caps |=
* GeodesicLine::LONGITUDE.
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters); requires that the
* GeodesicLine object was constructed with \e caps |=
* GeodesicLine::REDUCEDLENGTH.
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless); requires that the GeodesicLine object was constructed
* with \e caps |= GeodesicLine::GEODESICSCALE.
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless); requires that the GeodesicLine object was constructed
* with \e caps |= GeodesicLine::GEODESICSCALE.
* @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
* that the GeodesicLine object was constructed with \e caps |=
* GeodesicLine::AREA.
* @return \e a12 arc length from point 1 to point 2 (degrees).
*
* The values of \e lon2 and \e azi2 returned are in the range
* [&minus;180&deg;, 180&deg;].
*
* The GeodesicLine object \e must have been constructed with \e caps |=
* GeodesicLine::DISTANCE_IN; otherwise Math::NaN() is returned and no
* parameters are set. Requesting a value which the GeodesicLine object is
* not capable of computing is not an error; the corresponding argument
* will not be altered.
*
* The following functions are overloaded versions of
* GeodesicLine::Position which omit some of the output parameters. Note,
* however, that the arc length is always computed and returned as the
* function value.
**********************************************************************/
Math::real Position(real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21,
real& S12) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, t, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicLine::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLine::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2,
real& azi2) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLine::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2,
real& azi2, real& m12) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE |
AZIMUTH | REDUCEDLENGTH,
lat2, lon2, azi2, t, m12, t, t, t);
}
/**
* See the documentation for GeodesicLine::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2,
real& azi2, real& M12, real& M21)
const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE |
AZIMUTH | GEODESICSCALE,
lat2, lon2, azi2, t, t, M12, M21, t);
}
/**
* See the documentation for GeodesicLine::Position.
**********************************************************************/
Math::real Position(real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21)
const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, t, m12, M12, M21, t);
}
///@}
/** \name Position in terms of arc length
**********************************************************************/
///@{
/**
* Compute the position of point 2 which is an arc length \e a12 (degrees)
* from point 1.
*
* @param[in] a12 arc length from point 1 to point 2 (degrees); it can
* be negative.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees); requires that the
* GeodesicLine object was constructed with \e caps |=
* GeodesicLine::LONGITUDE.
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance from point 1 to point 2 (meters); requires
* that the GeodesicLine object was constructed with \e caps |=
* GeodesicLine::DISTANCE.
* @param[out] m12 reduced length of geodesic (meters); requires that the
* GeodesicLine object was constructed with \e caps |=
* GeodesicLine::REDUCEDLENGTH.
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless); requires that the GeodesicLine object was constructed
* with \e caps |= GeodesicLine::GEODESICSCALE.
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless); requires that the GeodesicLine object was constructed
* with \e caps |= GeodesicLine::GEODESICSCALE.
* @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
* that the GeodesicLine object was constructed with \e caps |=
* GeodesicLine::AREA.
*
* The values of \e lon2 and \e azi2 returned are in the range
* [&minus;180&deg;, 180&deg;].
*
* Requesting a value which the GeodesicLine object is not capable of
* computing is not an error; the corresponding argument will not be
* altered.
*
* The following functions are overloaded versions of
* GeodesicLine::ArcPosition which omit some of the output parameters.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21,
real& S12) const {
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, s12, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicLine::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLine::ArcPosition.
**********************************************************************/
void ArcPosition(real a12,
real& lat2, real& lon2, real& azi2)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLine::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12) const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
lat2, lon2, azi2, s12, t, t, t, t);
}
/**
* See the documentation for GeodesicLine::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& m12) const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH |
DISTANCE | REDUCEDLENGTH,
lat2, lon2, azi2, s12, m12, t, t, t);
}
/**
* See the documentation for GeodesicLine::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& M12, real& M21)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH |
DISTANCE | GEODESICSCALE,
lat2, lon2, azi2, s12, t, M12, M21, t);
}
/**
* See the documentation for GeodesicLine::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH |
DISTANCE | REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, s12, m12, M12, M21, t);
}
///@}
/** \name The general position function.
**********************************************************************/
///@{
/**
* The general position function. GeodesicLine::Position and
* GeodesicLine::ArcPosition are defined in terms of this function.
*
* @param[in] arcmode boolean flag determining the meaning of the second
* parameter; if \e arcmode is false, then the GeodesicLine object must
* have been constructed with \e caps |= GeodesicLine::DISTANCE_IN.
* @param[in] s12_a12 if \e arcmode is false, this is the distance between
* point 1 and point 2 (meters); otherwise it is the arc length between
* point 1 and point 2 (degrees); it can be negative.
* @param[in] outmask a bitor'ed combination of GeodesicLine::mask values
* specifying which of the following parameters should be set.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees); requires that the
* GeodesicLine object was constructed with \e caps |=
* GeodesicLine::LONGITUDE.
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance from point 1 to point 2 (meters); requires
* that the GeodesicLine object was constructed with \e caps |=
* GeodesicLine::DISTANCE.
* @param[out] m12 reduced length of geodesic (meters); requires that the
* GeodesicLine object was constructed with \e caps |=
* GeodesicLine::REDUCEDLENGTH.
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless); requires that the GeodesicLine object was constructed
* with \e caps |= GeodesicLine::GEODESICSCALE.
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless); requires that the GeodesicLine object was constructed
* with \e caps |= GeodesicLine::GEODESICSCALE.
* @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
* that the GeodesicLine object was constructed with \e caps |=
* GeodesicLine::AREA.
* @return \e a12 arc length from point 1 to point 2 (degrees).
*
* The GeodesicLine::mask values possible for \e outmask are
* - \e outmask |= GeodesicLine::LATITUDE for the latitude \e lat2;
* - \e outmask |= GeodesicLine::LONGITUDE for the latitude \e lon2;
* - \e outmask |= GeodesicLine::AZIMUTH for the latitude \e azi2;
* - \e outmask |= GeodesicLine::DISTANCE for the distance \e s12;
* - \e outmask |= GeodesicLine::REDUCEDLENGTH for the reduced length \e
* m12;
* - \e outmask |= GeodesicLine::GEODESICSCALE for the geodesic scales \e
* M12 and \e M21;
* - \e outmask |= GeodesicLine::AREA for the area \e S12;
* - \e outmask |= GeodesicLine::ALL for all of the above;
* - \e outmask |= GeodesicLine::LONG_UNROLL to unroll \e lon2 instead of
* reducing it into the range [&minus;180&deg;, 180&deg;].
* .
* Requesting a value which the GeodesicLine object is not capable of
* computing is not an error; the corresponding argument will not be
* altered. Note, however, that the arc length is always computed and
* returned as the function value.
*
* With the GeodesicLine::LONG_UNROLL bit set, the quantity \e lon2 &minus;
* \e lon1 indicates how many times and in what sense the geodesic
* encircles the ellipsoid.
**********************************************************************/
Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask,
real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21,
real& S12) const;
///@}
/** \name Setting point 3
**********************************************************************/
///@{
/**
* Specify position of point 3 in terms of distance.
*
* @param[in] s13 the distance from point 1 to point 3 (meters); it
* can be negative.
*
* This is only useful if the GeodesicLine object has been constructed
* with \e caps |= GeodesicLine::DISTANCE_IN.
**********************************************************************/
void SetDistance(real s13);
/**
* Specify position of point 3 in terms of arc length.
*
* @param[in] a13 the arc length from point 1 to point 3 (degrees); it
* can be negative.
*
* The distance \e s13 is only set if the GeodesicLine object has been
* constructed with \e caps |= GeodesicLine::DISTANCE.
**********************************************************************/
void SetArc(real a13);
/**
* Specify position of point 3 in terms of either distance or arc length.
*
* @param[in] arcmode boolean flag determining the meaning of the second
* parameter; if \e arcmode is false, then the GeodesicLine object must
* have been constructed with \e caps |= GeodesicLine::DISTANCE_IN.
* @param[in] s13_a13 if \e arcmode is false, this is the distance from
* point 1 to point 3 (meters); otherwise it is the arc length from
* point 1 to point 3 (degrees); it can be negative.
**********************************************************************/
void GenSetDistance(bool arcmode, real s13_a13);
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _caps != 0U; }
/**
* @return \e lat1 the latitude of point 1 (degrees).
**********************************************************************/
Math::real Latitude() const
{ return Init() ? _lat1 : Math::NaN(); }
/**
* @return \e lon1 the longitude of point 1 (degrees).
**********************************************************************/
Math::real Longitude() const
{ return Init() ? _lon1 : Math::NaN(); }
/**
* @return \e azi1 the azimuth (degrees) of the geodesic line at point 1.
**********************************************************************/
Math::real Azimuth() const
{ return Init() ? _azi1 : Math::NaN(); }
/**
* The sine and cosine of \e azi1.
*
* @param[out] sazi1 the sine of \e azi1.
* @param[out] cazi1 the cosine of \e azi1.
**********************************************************************/
void Azimuth(real& sazi1, real& cazi1) const
{ if (Init()) { sazi1 = _salp1; cazi1 = _calp1; } }
/**
* @return \e azi0 the azimuth (degrees) of the geodesic line as it crosses
* the equator in a northward direction.
*
* The result lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real EquatorialAzimuth() const
{ return Init() ? Math::atan2d(_salp0, _calp0) : Math::NaN(); }
/**
* The sine and cosine of \e azi0.
*
* @param[out] sazi0 the sine of \e azi0.
* @param[out] cazi0 the cosine of \e azi0.
**********************************************************************/
void EquatorialAzimuth(real& sazi0, real& cazi0) const
{ if (Init()) { sazi0 = _salp0; cazi0 = _calp0; } }
/**
* @return \e a1 the arc length (degrees) between the northward equatorial
* crossing and point 1.
*
* The result lies in (&minus;180&deg;, 180&deg;].
**********************************************************************/
Math::real EquatorialArc() const {
return Init() ? Math::atan2d(_ssig1, _csig1) : Math::NaN();
}
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const
{ return Init() ? _a : Math::NaN(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real Flattening() const
{ return Init() ? _f : Math::NaN(); }
/**
* @return \e caps the computational capabilities that this object was
* constructed with. LATITUDE and AZIMUTH are always included.
**********************************************************************/
unsigned Capabilities() const { return _caps; }
/**
* Test what capabilities are available.
*
* @param[in] testcaps a set of bitor'ed GeodesicLine::mask values.
* @return true if the GeodesicLine object has all these capabilities.
**********************************************************************/
bool Capabilities(unsigned testcaps) const {
testcaps &= OUT_ALL;
return (_caps & testcaps) == testcaps;
}
/**
* The distance or arc length to point 3.
*
* @param[in] arcmode boolean flag determining the meaning of returned
* value.
* @return \e s13 if \e arcmode is false; \e a13 if \e arcmode is true.
**********************************************************************/
Math::real GenDistance(bool arcmode) const
{ return Init() ? (arcmode ? _a13 : _s13) : Math::NaN(); }
/**
* @return \e s13, the distance to point 3 (meters).
**********************************************************************/
Math::real Distance() const { return GenDistance(false); }
/**
* @return \e a13, the arc length to point 3 (degrees).
**********************************************************************/
Math::real Arc() const { return GenDistance(true); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEODESICLINE_HPP

673
external/include/GeographicLib/GeodesicLineExact.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,673 @@
/**
* \file GeodesicLineExact.hpp
* \brief Header for GeographicLib::GeodesicLineExact class
*
* Copyright (c) Charles Karney (2012-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEODESICLINEEXACT_HPP)
#define GEOGRAPHICLIB_GEODESICLINEEXACT_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/GeodesicExact.hpp>
#include <GeographicLib/EllipticFunction.hpp>
namespace GeographicLib {
/**
* \brief An exact geodesic line
*
* GeodesicLineExact facilitates the determination of a series of points on a
* single geodesic. This is a companion to the GeodesicExact class. For
* additional information on this class see the documentation on the
* GeodesicLine class.
*
* Example of use:
* \include example-GeodesicLineExact.cpp
*
* <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility
* providing access to the functionality of GeodesicExact and
* GeodesicLineExact (via the -E option).
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GeodesicLineExact {
private:
typedef Math::real real;
friend class GeodesicExact;
static const int nC4_ = GeodesicExact::nC4_;
real tiny_;
real _lat1, _lon1, _azi1;
real _a, _f, _b, _c2, _f1, _e2, _salp0, _calp0, _k2,
_salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1,
_somg1, _comg1, _cchi1,
_A4, _B41, _E0, _D0, _H0, _E1, _D1, _H1;
real _a13, _s13;
real _C4a[nC4_]; // all the elements of _C4a are used
EllipticFunction _E;
unsigned _caps;
void LineInit(const GeodesicExact& g,
real lat1, real lon1,
real azi1, real salp1, real calp1,
unsigned caps);
GeodesicLineExact(const GeodesicExact& g,
real lat1, real lon1,
real azi1, real salp1, real calp1,
unsigned caps, bool arcmode, real s13_a13);
enum captype {
CAP_NONE = GeodesicExact::CAP_NONE,
CAP_E = GeodesicExact::CAP_E,
CAP_D = GeodesicExact::CAP_D,
CAP_H = GeodesicExact::CAP_H,
CAP_C4 = GeodesicExact::CAP_C4,
CAP_ALL = GeodesicExact::CAP_ALL,
CAP_MASK = GeodesicExact::CAP_MASK,
OUT_ALL = GeodesicExact::OUT_ALL,
OUT_MASK = GeodesicExact::OUT_MASK,
};
public:
/**
* Bit masks for what calculations to do. They signify to the
* GeodesicLineExact::GeodesicLineExact constructor and to
* GeodesicExact::Line what capabilities should be included in the
* GeodesicLineExact object. This is merely a duplication of
* GeodesicExact::mask.
**********************************************************************/
enum mask {
/**
* No capabilities, no output.
* @hideinitializer
**********************************************************************/
NONE = GeodesicExact::NONE,
/**
* Calculate latitude \e lat2. (It's not necessary to include this as a
* capability to GeodesicLineExact because this is included by default.)
* @hideinitializer
**********************************************************************/
LATITUDE = GeodesicExact::LATITUDE,
/**
* Calculate longitude \e lon2.
* @hideinitializer
**********************************************************************/
LONGITUDE = GeodesicExact::LONGITUDE,
/**
* Calculate azimuths \e azi1 and \e azi2. (It's not necessary to
* include this as a capability to GeodesicLineExact because this is
* included by default.)
* @hideinitializer
**********************************************************************/
AZIMUTH = GeodesicExact::AZIMUTH,
/**
* Calculate distance \e s12.
* @hideinitializer
**********************************************************************/
DISTANCE = GeodesicExact::DISTANCE,
/**
* Allow distance \e s12 to be used as input in the direct geodesic
* problem.
* @hideinitializer
**********************************************************************/
DISTANCE_IN = GeodesicExact::DISTANCE_IN,
/**
* Calculate reduced length \e m12.
* @hideinitializer
**********************************************************************/
REDUCEDLENGTH = GeodesicExact::REDUCEDLENGTH,
/**
* Calculate geodesic scales \e M12 and \e M21.
* @hideinitializer
**********************************************************************/
GEODESICSCALE = GeodesicExact::GEODESICSCALE,
/**
* Calculate area \e S12.
* @hideinitializer
**********************************************************************/
AREA = GeodesicExact::AREA,
/**
* Unroll \e lon2 in the direct calculation.
* @hideinitializer
**********************************************************************/
LONG_UNROLL = GeodesicExact::LONG_UNROLL,
/**
* All capabilities, calculate everything. (LONG_UNROLL is not
* included in this mask.)
* @hideinitializer
**********************************************************************/
ALL = GeodesicExact::ALL,
};
/** \name Constructors
**********************************************************************/
///@{
/**
* Constructor for a geodesic line staring at latitude \e lat1, longitude
* \e lon1, and azimuth \e azi1 (all in degrees).
*
* @param[in] g A GeodesicExact object used to compute the necessary
* information about the GeodesicLineExact.
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi1 azimuth at point 1 (degrees).
* @param[in] caps bitor'ed combination of GeodesicLineExact::mask values
* specifying the capabilities the GeodesicLineExact object should
* possess, i.e., which quantities can be returned in calls to
* GeodesicLine::Position.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
*
* The GeodesicLineExact::mask values are
* - \e caps |= GeodesicLineExact::LATITUDE for the latitude \e lat2; this
* is added automatically;
* - \e caps |= GeodesicLineExact::LONGITUDE for the latitude \e lon2;
* - \e caps |= GeodesicLineExact::AZIMUTH for the latitude \e azi2; this
* is added automatically;
* - \e caps |= GeodesicLineExact::DISTANCE for the distance \e s12;
* - \e caps |= GeodesicLineExact::REDUCEDLENGTH for the reduced length \e
m12;
* - \e caps |= GeodesicLineExact::GEODESICSCALE for the geodesic scales \e
* M12 and \e M21;
* - \e caps |= GeodesicLineExact::AREA for the area \e S12;
* - \e caps |= GeodesicLineExact::DISTANCE_IN permits the length of the
* geodesic to be given in terms of \e s12; without this capability the
* length can only be specified in terms of arc length;
* - \e caps |= GeodesicLineExact::ALL for all of the above.
* .
* The default value of \e caps is GeodesicLineExact::ALL.
*
* If the point is at a pole, the azimuth is defined by keeping \e lon1
* fixed, writing \e lat1 = &plusmn;(90&deg; &minus; &epsilon;), and taking
* the limit &epsilon; &rarr; 0+.
**********************************************************************/
GeodesicLineExact(const GeodesicExact& g, real lat1, real lon1, real azi1,
unsigned caps = ALL);
/**
* A default constructor. If GeodesicLineExact::Position is called on the
* resulting object, it returns immediately (without doing any
* calculations). The object can be set with a call to
* GeodesicExact::Line. Use Init() to test whether object is still in this
* uninitialized state.
**********************************************************************/
GeodesicLineExact() : _caps(0U) {}
///@}
/** \name Position in terms of distance
**********************************************************************/
///@{
/**
* Compute the position of point 2 which is a distance \e s12 (meters)
* from point 1.
*
* @param[in] s12 distance from point 1 to point 2 (meters); it can be
* signed.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees); requires that the
* GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::LONGITUDE.
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] m12 reduced length of geodesic (meters); requires that the
* GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::REDUCEDLENGTH.
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless); requires that the GeodesicLineExact object was
* constructed with \e caps |= GeodesicLineExact::GEODESICSCALE.
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless); requires that the GeodesicLineExact object was
* constructed with \e caps |= GeodesicLineExact::GEODESICSCALE.
* @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
* that the GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::AREA.
* @return \e a12 arc length from point 1 to point 2 (degrees).
*
* The values of \e lon2 and \e azi2 returned are in the range
* [&minus;180&deg;, 180&deg;].
*
* The GeodesicLineExact object \e must have been constructed with \e caps
* |= GeodesicLineExact::DISTANCE_IN; otherwise Math::NaN() is returned and
* no parameters are set. Requesting a value which the GeodesicLineExact
* object is not capable of computing is not an error; the corresponding
* argument will not be altered.
*
* The following functions are overloaded versions of
* GeodesicLineExact::Position which omit some of the output parameters.
* Note, however, that the arc length is always computed and returned as
* the function value.
**********************************************************************/
Math::real Position(real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21,
real& S12) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, t, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicLineExact::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2,
real& azi2) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2,
real& azi2, real& m12) const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE |
AZIMUTH | REDUCEDLENGTH,
lat2, lon2, azi2, t, m12, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::Position.
**********************************************************************/
Math::real Position(real s12, real& lat2, real& lon2,
real& azi2, real& M12, real& M21)
const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE |
AZIMUTH | GEODESICSCALE,
lat2, lon2, azi2, t, t, M12, M21, t);
}
/**
* See the documentation for GeodesicLineExact::Position.
**********************************************************************/
Math::real Position(real s12,
real& lat2, real& lon2, real& azi2,
real& m12, real& M12, real& M21)
const {
real t;
return GenPosition(false, s12,
LATITUDE | LONGITUDE | AZIMUTH |
REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, t, m12, M12, M21, t);
}
///@}
/** \name Position in terms of arc length
**********************************************************************/
///@{
/**
* Compute the position of point 2 which is an arc length \e a12 (degrees)
* from point 1.
*
* @param[in] a12 arc length from point 1 to point 2 (degrees); it can
* be signed.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees); requires that the
* GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::LONGITUDE.
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance from point 1 to point 2 (meters); requires
* that the GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::DISTANCE.
* @param[out] m12 reduced length of geodesic (meters); requires that the
* GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::REDUCEDLENGTH.
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless); requires that the GeodesicLineExact object was
* constructed with \e caps |= GeodesicLineExact::GEODESICSCALE.
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless); requires that the GeodesicLineExact object was
* constructed with \e caps |= GeodesicLineExact::GEODESICSCALE.
* @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
* that the GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::AREA.
*
* The values of \e lon2 and \e azi2 returned are in the range
* [&minus;180&deg;, 180&deg;].
*
* Requesting a value which the GeodesicLineExact object is not capable of
* computing is not an error; the corresponding argument will not be
* altered.
*
* The following functions are overloaded versions of
* GeodesicLineExact::ArcPosition which omit some of the output parameters.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21,
real& S12) const {
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE |
REDUCEDLENGTH | GEODESICSCALE | AREA,
lat2, lon2, azi2, s12, m12, M12, M21, S12);
}
/**
* See the documentation for GeodesicLineExact::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE,
lat2, lon2, t, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::ArcPosition.
**********************************************************************/
void ArcPosition(real a12,
real& lat2, real& lon2, real& azi2)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH,
lat2, lon2, azi2, t, t, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12) const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH | DISTANCE,
lat2, lon2, azi2, s12, t, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& m12) const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH |
DISTANCE | REDUCEDLENGTH,
lat2, lon2, azi2, s12, m12, t, t, t);
}
/**
* See the documentation for GeodesicLineExact::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& M12, real& M21)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH |
DISTANCE | GEODESICSCALE,
lat2, lon2, azi2, s12, t, M12, M21, t);
}
/**
* See the documentation for GeodesicLineExact::ArcPosition.
**********************************************************************/
void ArcPosition(real a12, real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21)
const {
real t;
GenPosition(true, a12,
LATITUDE | LONGITUDE | AZIMUTH |
DISTANCE | REDUCEDLENGTH | GEODESICSCALE,
lat2, lon2, azi2, s12, m12, M12, M21, t);
}
///@}
/** \name The general position function.
**********************************************************************/
///@{
/**
* The general position function. GeodesicLineExact::Position and
* GeodesicLineExact::ArcPosition are defined in terms of this function.
*
* @param[in] arcmode boolean flag determining the meaning of the second
* parameter; if \e arcmode is false, then the GeodesicLineExact object
* must have been constructed with \e caps |=
* GeodesicLineExact::DISTANCE_IN.
* @param[in] s12_a12 if \e arcmode is false, this is the distance between
* point 1 and point 2 (meters); otherwise it is the arc length between
* point 1 and point 2 (degrees); it can be signed.
* @param[in] outmask a bitor'ed combination of GeodesicLineExact::mask
* values specifying which of the following parameters should be set.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees); requires that the
* GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::LONGITUDE.
* @param[out] azi2 (forward) azimuth at point 2 (degrees).
* @param[out] s12 distance from point 1 to point 2 (meters); requires
* that the GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::DISTANCE.
* @param[out] m12 reduced length of geodesic (meters); requires that the
* GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::REDUCEDLENGTH.
* @param[out] M12 geodesic scale of point 2 relative to point 1
* (dimensionless); requires that the GeodesicLineExact object was
* constructed with \e caps |= GeodesicLineExact::GEODESICSCALE.
* @param[out] M21 geodesic scale of point 1 relative to point 2
* (dimensionless); requires that the GeodesicLineExact object was
* constructed with \e caps |= GeodesicLineExact::GEODESICSCALE.
* @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
* that the GeodesicLineExact object was constructed with \e caps |=
* GeodesicLineExact::AREA.
* @return \e a12 arc length from point 1 to point 2 (degrees).
*
* The GeodesicLineExact::mask values possible for \e outmask are
* - \e outmask |= GeodesicLineExact::LATITUDE for the latitude \e lat2;
* - \e outmask |= GeodesicLineExact::LONGITUDE for the latitude \e lon2;
* - \e outmask |= GeodesicLineExact::AZIMUTH for the latitude \e azi2;
* - \e outmask |= GeodesicLineExact::DISTANCE for the distance \e s12;
* - \e outmask |= GeodesicLineExact::REDUCEDLENGTH for the reduced length
* \e m12;
* - \e outmask |= GeodesicLineExact::GEODESICSCALE for the geodesic scales
* \e M12 and \e M21;
* - \e outmask |= GeodesicLineExact::AREA for the area \e S12;
* - \e outmask |= GeodesicLineExact::ALL for all of the above;
* - \e outmask |= GeodesicLineExact::LONG_UNROLL to unroll \e lon2 instead
* of wrapping it into the range [&minus;180&deg;, 180&deg;].
* .
* Requesting a value which the GeodesicLineExact object is not capable of
* computing is not an error; the corresponding argument will not be
* altered. Note, however, that the arc length is always computed and
* returned as the function value.
*
* With the GeodesicLineExact::LONG_UNROLL bit set, the quantity \e lon2
* &minus; \e lon1 indicates how many times and in what sense the geodesic
* encircles the ellipsoid.
**********************************************************************/
Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask,
real& lat2, real& lon2, real& azi2,
real& s12, real& m12, real& M12, real& M21,
real& S12) const;
///@}
/** \name Setting point 3
**********************************************************************/
///@{
/**
* Specify position of point 3 in terms of distance.
*
* @param[in] s13 the distance from point 1 to point 3 (meters); it
* can be negative.
*
* This is only useful if the GeodesicLineExact object has been constructed
* with \e caps |= GeodesicLineExact::DISTANCE_IN.
**********************************************************************/
void SetDistance(real s13);
/**
* Specify position of point 3 in terms of arc length.
*
* @param[in] a13 the arc length from point 1 to point 3 (degrees); it
* can be negative.
*
* The distance \e s13 is only set if the GeodesicLineExact object has been
* constructed with \e caps |= GeodesicLineExact::DISTANCE.
**********************************************************************/
void SetArc(real a13);
/**
* Specify position of point 3 in terms of either distance or arc length.
*
* @param[in] arcmode boolean flag determining the meaning of the second
* parameter; if \e arcmode is false, then the GeodesicLineExact object
* must have been constructed with \e caps |=
* GeodesicLineExact::DISTANCE_IN.
* @param[in] s13_a13 if \e arcmode is false, this is the distance from
* point 1 to point 3 (meters); otherwise it is the arc length from
* point 1 to point 3 (degrees); it can be negative.
**********************************************************************/
void GenSetDistance(bool arcmode, real s13_a13);
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _caps != 0U; }
/**
* @return \e lat1 the latitude of point 1 (degrees).
**********************************************************************/
Math::real Latitude() const
{ return Init() ? _lat1 : Math::NaN(); }
/**
* @return \e lon1 the longitude of point 1 (degrees).
**********************************************************************/
Math::real Longitude() const
{ return Init() ? _lon1 : Math::NaN(); }
/**
* @return \e azi1 the azimuth (degrees) of the geodesic line at point 1.
**********************************************************************/
Math::real Azimuth() const
{ return Init() ? _azi1 : Math::NaN(); }
/**
* The sine and cosine of \e azi1.
*
* @param[out] sazi1 the sine of \e azi1.
* @param[out] cazi1 the cosine of \e azi1.
**********************************************************************/
void Azimuth(real& sazi1, real& cazi1) const
{ if (Init()) { sazi1 = _salp1; cazi1 = _calp1; } }
/**
* @return \e azi0 the azimuth (degrees) of the geodesic line as it crosses
* the equator in a northward direction.
*
* The result lies in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real EquatorialAzimuth() const
{ return Init() ? Math::atan2d(_salp0, _calp0) : Math::NaN(); }
/**
* The sine and cosine of \e azi0.
*
* @param[out] sazi0 the sine of \e azi0.
* @param[out] cazi0 the cosine of \e azi0.
**********************************************************************/
void EquatorialAzimuth(real& sazi0, real& cazi0) const
{ if (Init()) { sazi0 = _salp0; cazi0 = _calp0; } }
/**
* @return \e a1 the arc length (degrees) between the northward equatorial
* crossing and point 1.
*
* The result lies in (&minus;180&deg;, 180&deg;].
**********************************************************************/
Math::real EquatorialArc() const {
using std::atan2;
return Init() ? atan2(_ssig1, _csig1) / Math::degree() : Math::NaN();
}
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the GeodesicExact object used in the
* constructor.
**********************************************************************/
Math::real EquatorialRadius() const
{ return Init() ? _a : Math::NaN(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the GeodesicExact object used in the constructor.
**********************************************************************/
Math::real Flattening() const
{ return Init() ? _f : Math::NaN(); }
/**
* @return \e caps the computational capabilities that this object was
* constructed with. LATITUDE and AZIMUTH are always included.
**********************************************************************/
unsigned Capabilities() const { return _caps; }
/**
* Test what capabilities are available.
*
* @param[in] testcaps a set of bitor'ed GeodesicLineExact::mask values.
* @return true if the GeodesicLineExact object has all these capabilities.
**********************************************************************/
bool Capabilities(unsigned testcaps) const {
testcaps &= OUT_ALL;
return (_caps & testcaps) == testcaps;
}
/**
* The distance or arc length to point 3.
*
* @param[in] arcmode boolean flag determining the meaning of returned
* value.
* @return \e s13 if \e arcmode is false; \e a13 if \e arcmode is true.
**********************************************************************/
Math::real GenDistance(bool arcmode) const
{ return Init() ? (arcmode ? _a13 : _s13) : Math::NaN(); }
/**
* @return \e s13, the distance to point 3 (meters).
**********************************************************************/
Math::real Distance() const { return GenDistance(false); }
/**
* @return \e a13, the arc length to point 3 (degrees).
**********************************************************************/
Math::real Arc() const { return GenDistance(true); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEODESICLINEEXACT_HPP

180
external/include/GeographicLib/Geohash.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,180 @@
/**
* \file Geohash.hpp
* \brief Header for GeographicLib::Geohash class
*
* Copyright (c) Charles Karney (2012-2017) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEOHASH_HPP)
#define GEOGRAPHICLIB_GEOHASH_HPP 1
#include <GeographicLib/Constants.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs string
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
/**
* \brief Conversions for geohashes
*
* Geohashes are described in
* - https://en.wikipedia.org/wiki/Geohash
* - http://geohash.org/
* .
* They provide a compact string representation of a particular geographic
* location (expressed as latitude and longitude), with the property that if
* trailing characters are dropped from the string the geographic location
* remains nearby. The classes Georef and GARS implement similar compact
* representations.
*
* Example of use:
* \include example-Geohash.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Geohash {
private:
typedef Math::real real;
static const int maxlen_ = 18;
static const unsigned long long mask_ = 1ULL << 45;
static const char* const lcdigits_;
static const char* const ucdigits_;
Geohash(); // Disable constructor
public:
/**
* Convert from geographic coordinates to a geohash.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] len the length of the resulting geohash.
* @param[out] geohash the geohash.
* @exception GeographicErr if \e lat is not in [&minus;90&deg;,
* 90&deg;].
* @exception std::bad_alloc if memory for \e geohash can't be allocated.
*
* Internally, \e len is first put in the range [0, 18]. (\e len = 18
* provides approximately 1&mu;m precision.)
*
* If \e lat or \e lon is NaN, the returned geohash is "invalid".
**********************************************************************/
static void Forward(real lat, real lon, int len, std::string& geohash);
/**
* Convert from a geohash to geographic coordinates.
*
* @param[in] geohash the geohash.
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] len the length of the geohash.
* @param[in] centerp if true (the default) return the center of the
* geohash location, otherwise return the south-west corner.
* @exception GeographicErr if \e geohash contains illegal characters.
*
* Only the first 18 characters for \e geohash are considered. (18
* characters provides approximately 1&mu;m precision.) The case of the
* letters in \e geohash is ignored.
*
* If the first 3 characters of \e geohash are "inv", then \e lat and \e
* lon are set to NaN and \e len is unchanged. ("nan" is treated
* similarly.)
**********************************************************************/
static void Reverse(const std::string& geohash, real& lat, real& lon,
int& len, bool centerp = true);
/**
* The latitude resolution of a geohash.
*
* @param[in] len the length of the geohash.
* @return the latitude resolution (degrees).
*
* Internally, \e len is first put in the range [0, 18].
**********************************************************************/
static Math::real LatitudeResolution(int len) {
using std::ldexp;
len = (std::max)(0, (std::min)(int(maxlen_), len));
return ldexp(real(180), -(5 * len / 2));
}
/**
* The longitude resolution of a geohash.
*
* @param[in] len the length of the geohash.
* @return the longitude resolution (degrees).
*
* Internally, \e len is first put in the range [0, 18].
**********************************************************************/
static Math::real LongitudeResolution(int len) {
using std::ldexp;
len = (std::max)(0, (std::min)(int(maxlen_), len));
return ldexp(real(360), -(5 * len - 5 * len / 2));
}
/**
* The geohash length required to meet a given geographic resolution.
*
* @param[in] res the minimum of resolution in latitude and longitude
* (degrees).
* @return geohash length.
*
* The returned length is in the range [0, 18].
**********************************************************************/
static int GeohashLength(real res) {
using std::abs; res = abs(res);
for (int len = 0; len < maxlen_; ++len)
if (LongitudeResolution(len) <= res)
return len;
return maxlen_;
}
/**
* The geohash length required to meet a given geographic resolution.
*
* @param[in] latres the resolution in latitude (degrees).
* @param[in] lonres the resolution in longitude (degrees).
* @return geohash length.
*
* The returned length is in the range [0, 18].
**********************************************************************/
static int GeohashLength(real latres, real lonres) {
using std::abs;
latres = abs(latres);
lonres = abs(lonres);
for (int len = 0; len < maxlen_; ++len)
if (LatitudeResolution(len) <= latres &&
LongitudeResolution(len) <= lonres)
return len;
return maxlen_;
}
/**
* The decimal geographic precision required to match a given geohash
* length. This is the number of digits needed after decimal point in a
* decimal degrees representation.
*
* @param[in] len the length of the geohash.
* @return the decimal precision (may be negative).
*
* Internally, \e len is first put in the range [0, 18]. The returned
* decimal precision is in the range [&minus;2, 12].
**********************************************************************/
static int DecimalPrecision(int len) {
using std::floor; using std::log;
return -int(floor(log(LatitudeResolution(len))/log(Math::real(10))));
}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_GEOHASH_HPP

478
external/include/GeographicLib/Geoid.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,478 @@
/**
* \file Geoid.hpp
* \brief Header for GeographicLib::Geoid class
*
* Copyright (c) Charles Karney (2009-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEOID_HPP)
#define GEOGRAPHICLIB_GEOID_HPP 1
#include <vector>
#include <fstream>
#include <GeographicLib/Constants.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector and constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4251 4127)
#endif
#if !defined(GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH)
/**
* The size of the pixel data in the pgm data files for the geoids. 2 is the
* standard size corresponding to a maxval 2<sup>16</sup>&minus;1. Setting it
* to 4 uses a maxval of 2<sup>32</sup>&minus;1 and changes the extension for
* the data files from .pgm to .pgm4. Note that the format of these pgm4 files
* is a non-standard extension of the pgm format.
**********************************************************************/
# define GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH 2
#endif
namespace GeographicLib {
/**
* \brief Looking up the height of the geoid above the ellipsoid
*
* This class evaluates the height of one of the standard geoids, EGM84,
* EGM96, or EGM2008 by bilinear or cubic interpolation into a rectangular
* grid of data. These geoid models are documented in
* - EGM84:
* https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm84
* - EGM96:
* https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm96
* - EGM2008:
* https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm2008
*
* The geoids are defined in terms of spherical harmonics. However in order
* to provide a quick and flexible method of evaluating the geoid heights,
* this class evaluates the height by interpolation into a grid of
* precomputed values.
*
* The height of the geoid above the ellipsoid, \e N, is sometimes called the
* geoid undulation. It can be used to convert a height above the ellipsoid,
* \e h, to the corresponding height above the geoid (the orthometric height,
* roughly the height above mean sea level), \e H, using the relations
*
* &nbsp;&nbsp;&nbsp;\e h = \e N + \e H;
* &nbsp;&nbsp;\e H = &minus;\e N + \e h.
*
* See \ref geoid for details of how to install the data sets, the data
* format, estimates of the interpolation errors, and how to use caching.
*
* This class is typically \e not thread safe in that a single instantiation
* cannot be safely used by multiple threads because of the way the object
* reads the data set and because it maintains a single-cell cache. If
* multiple threads need to calculate geoid heights they should all construct
* thread-local instantiations. Alternatively, set the optional \e
* threadsafe parameter to true in the constructor. This causes the
* constructor to read all the data into memory and to turn off the
* single-cell caching which results in a Geoid object which \e is thread
* safe.
*
* Example of use:
* \include example-Geoid.cpp
*
* <a href="GeoidEval.1.html">GeoidEval</a> is a command-line utility
* providing access to the functionality of Geoid.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Geoid {
private:
typedef Math::real real;
#if GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH != 4
typedef unsigned short pixel_t;
static const unsigned pixel_size_ = 2;
static const unsigned pixel_max_ = 0xffffu;
#else
typedef unsigned pixel_t;
static const unsigned pixel_size_ = 4;
static const unsigned pixel_max_ = 0xffffffffu;
#endif
static const unsigned stencilsize_ = 12;
static const unsigned nterms_ = ((3 + 1) * (3 + 2))/2; // for a cubic fit
static const int c0_;
static const int c0n_;
static const int c0s_;
static const int c3_[stencilsize_ * nterms_];
static const int c3n_[stencilsize_ * nterms_];
static const int c3s_[stencilsize_ * nterms_];
std::string _name, _dir, _filename;
const bool _cubic;
const real _a, _e2, _degree, _eps;
mutable std::ifstream _file;
real _rlonres, _rlatres;
std::string _description, _datetime;
real _offset, _scale, _maxerror, _rmserror;
int _width, _height;
unsigned long long _datastart, _swidth;
bool _threadsafe;
// Area cache
mutable std::vector< std::vector<pixel_t> > _data;
mutable bool _cache;
// NE corner and extent of cache
mutable int _xoffset, _yoffset, _xsize, _ysize;
// Cell cache
mutable int _ix, _iy;
mutable real _v00, _v01, _v10, _v11;
mutable real _t[nterms_];
void filepos(int ix, int iy) const {
_file.seekg(std::streamoff
(_datastart +
pixel_size_ * (unsigned(iy)*_swidth + unsigned(ix))));
}
real rawval(int ix, int iy) const {
if (ix < 0)
ix += _width;
else if (ix >= _width)
ix -= _width;
if (_cache && iy >= _yoffset && iy < _yoffset + _ysize &&
((ix >= _xoffset && ix < _xoffset + _xsize) ||
(ix + _width >= _xoffset && ix + _width < _xoffset + _xsize))) {
return real(_data[iy - _yoffset]
[ix >= _xoffset ? ix - _xoffset : ix + _width - _xoffset]);
} else {
if (iy < 0 || iy >= _height) {
iy = iy < 0 ? -iy : 2 * (_height - 1) - iy;
ix += (ix < _width/2 ? 1 : -1) * _width/2;
}
try {
filepos(ix, iy);
// initial values to suppress warnings in case get fails
char a = 0, b = 0;
_file.get(a);
_file.get(b);
unsigned r = ((unsigned char)(a) << 8) | (unsigned char)(b);
if (pixel_size_ == 4) {
_file.get(a);
_file.get(b);
r = (r << 16) | ((unsigned char)(a) << 8) | (unsigned char)(b);
}
return real(r);
}
catch (const std::exception& e) {
// throw GeographicErr("Error reading " + _filename + ": "
// + e.what());
// triggers complaints about the "binary '+'" under Visual Studio.
// So use '+=' instead.
std::string err("Error reading ");
err += _filename;
err += ": ";
err += e.what();
throw GeographicErr(err);
}
}
}
real height(real lat, real lon) const;
Geoid(const Geoid&) = delete; // copy constructor not allowed
Geoid& operator=(const Geoid&) = delete; // copy assignment not allowed
public:
/**
* Flags indicating conversions between heights above the geoid and heights
* above the ellipsoid.
**********************************************************************/
enum convertflag {
/**
* The multiplier for converting from heights above the geoid to heights
* above the ellipsoid.
**********************************************************************/
ELLIPSOIDTOGEOID = -1,
/**
* No conversion.
**********************************************************************/
NONE = 0,
/**
* The multiplier for converting from heights above the ellipsoid to
* heights above the geoid.
**********************************************************************/
GEOIDTOELLIPSOID = 1,
};
/** \name Setting up the geoid
**********************************************************************/
///@{
/**
* Construct a geoid.
*
* @param[in] name the name of the geoid.
* @param[in] path (optional) directory for data file.
* @param[in] cubic (optional) interpolation method; false means bilinear,
* true (the default) means cubic.
* @param[in] threadsafe (optional), if true, construct a thread safe
* object. The default is false
* @exception GeographicErr if the data file cannot be found, is
* unreadable, or is corrupt.
* @exception GeographicErr if \e threadsafe is true but the memory
* necessary for caching the data can't be allocated.
*
* The data file is formed by appending ".pgm" to the name. If \e path is
* specified (and is non-empty), then the file is loaded from directory, \e
* path. Otherwise the path is given by DefaultGeoidPath(). If the \e
* threadsafe parameter is true, the data set is read into memory, the data
* file is closed, and single-cell caching is turned off; this results in a
* Geoid object which \e is thread safe.
**********************************************************************/
explicit Geoid(const std::string& name, const std::string& path = "",
bool cubic = true, bool threadsafe = false);
/**
* Set up a cache.
*
* @param[in] south latitude (degrees) of the south edge of the cached
* area.
* @param[in] west longitude (degrees) of the west edge of the cached area.
* @param[in] north latitude (degrees) of the north edge of the cached
* area.
* @param[in] east longitude (degrees) of the east edge of the cached area.
* @exception GeographicErr if the memory necessary for caching the data
* can't be allocated (in this case, you will have no cache and can try
* again with a smaller area).
* @exception GeographicErr if there's a problem reading the data.
* @exception GeographicErr if this is called on a threadsafe Geoid.
*
* Cache the data for the specified "rectangular" area bounded by the
* parallels \e south and \e north and the meridians \e west and \e east.
* \e east is always interpreted as being east of \e west, if necessary by
* adding 360&deg; to its value. \e south and \e north should be in
* the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
void CacheArea(real south, real west, real north, real east) const;
/**
* Cache all the data.
*
* @exception GeographicErr if the memory necessary for caching the data
* can't be allocated (in this case, you will have no cache and can try
* again with a smaller area).
* @exception GeographicErr if there's a problem reading the data.
* @exception GeographicErr if this is called on a threadsafe Geoid.
*
* On most computers, this is fast for data sets with grid resolution of 5'
* or coarser. For a 1' grid, the required RAM is 450MB; a 2.5' grid needs
* 72MB; and a 5' grid needs 18MB.
**********************************************************************/
void CacheAll() const { CacheArea(real(-90), real(0),
real(90), real(360)); }
/**
* Clear the cache. This never throws an error. (This does nothing with a
* thread safe Geoid.)
**********************************************************************/
void CacheClear() const;
///@}
/** \name Compute geoid heights
**********************************************************************/
///@{
/**
* Compute the geoid height at a point
*
* @param[in] lat latitude of the point (degrees).
* @param[in] lon longitude of the point (degrees).
* @exception GeographicErr if there's a problem reading the data; this
* never happens if (\e lat, \e lon) is within a successfully cached
* area.
* @return the height of the geoid above the ellipsoid (meters).
*
* The latitude should be in [&minus;90&deg;, 90&deg;].
**********************************************************************/
Math::real operator()(real lat, real lon) const {
return height(lat, lon);
}
/**
* Convert a height above the geoid to a height above the ellipsoid and
* vice versa.
*
* @param[in] lat latitude of the point (degrees).
* @param[in] lon longitude of the point (degrees).
* @param[in] h height of the point (degrees).
* @param[in] d a Geoid::convertflag specifying the direction of the
* conversion; Geoid::GEOIDTOELLIPSOID means convert a height above the
* geoid to a height above the ellipsoid; Geoid::ELLIPSOIDTOGEOID means
* convert a height above the ellipsoid to a height above the geoid.
* @exception GeographicErr if there's a problem reading the data; this
* never happens if (\e lat, \e lon) is within a successfully cached
* area.
* @return converted height (meters).
**********************************************************************/
Math::real ConvertHeight(real lat, real lon, real h,
convertflag d) const {
return h + real(d) * height(lat, lon);
}
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return geoid description, if available, in the data file; if
* absent, return "NONE".
**********************************************************************/
const std::string& Description() const { return _description; }
/**
* @return date of the data file; if absent, return "UNKNOWN".
**********************************************************************/
const std::string& DateTime() const { return _datetime; }
/**
* @return full file name used to load the geoid data.
**********************************************************************/
const std::string& GeoidFile() const { return _filename; }
/**
* @return "name" used to load the geoid data (from the first argument of
* the constructor).
**********************************************************************/
const std::string& GeoidName() const { return _name; }
/**
* @return directory used to load the geoid data.
**********************************************************************/
const std::string& GeoidDirectory() const { return _dir; }
/**
* @return interpolation method ("cubic" or "bilinear").
**********************************************************************/
const std::string Interpolation() const
{ return std::string(_cubic ? "cubic" : "bilinear"); }
/**
* @return estimate of the maximum interpolation and quantization error
* (meters).
*
* This relies on the value being stored in the data file. If the value is
* absent, return &minus;1.
**********************************************************************/
Math::real MaxError() const { return _maxerror; }
/**
* @return estimate of the RMS interpolation and quantization error
* (meters).
*
* This relies on the value being stored in the data file. If the value is
* absent, return &minus;1.
**********************************************************************/
Math::real RMSError() const { return _rmserror; }
/**
* @return offset (meters).
*
* This in used in converting from the pixel values in the data file to
* geoid heights.
**********************************************************************/
Math::real Offset() const { return _offset; }
/**
* @return scale (meters).
*
* This in used in converting from the pixel values in the data file to
* geoid heights.
**********************************************************************/
Math::real Scale() const { return _scale; }
/**
* @return true if the object is constructed to be thread safe.
**********************************************************************/
bool ThreadSafe() const { return _threadsafe; }
/**
* @return true if a data cache is active.
**********************************************************************/
bool Cache() const { return _cache; }
/**
* @return west edge of the cached area; the cache includes this edge.
**********************************************************************/
Math::real CacheWest() const {
return _cache ? ((_xoffset + (_xsize == _width ? 0 : _cubic)
+ _width/2) % _width - _width/2) / _rlonres :
0;
}
/**
* @return east edge of the cached area; the cache excludes this edge.
**********************************************************************/
Math::real CacheEast() const {
return _cache ?
CacheWest() +
(_xsize - (_xsize == _width ? 0 : 1 + 2 * _cubic)) / _rlonres :
0;
}
/**
* @return north edge of the cached area; the cache includes this edge.
**********************************************************************/
Math::real CacheNorth() const {
return _cache ? 90 - (_yoffset + _cubic) / _rlatres : 0;
}
/**
* @return south edge of the cached area; the cache excludes this edge
* unless it's the south pole.
**********************************************************************/
Math::real CacheSouth() const {
return _cache ? 90 - ( _yoffset + _ysize - 1 - _cubic) / _rlatres : 0;
}
/**
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
*
* (The WGS84 value is returned because the supported geoid models are all
* based on this ellipsoid.)
**********************************************************************/
Math::real EquatorialRadius() const
{ return Constants::WGS84_a(); }
/**
* @return \e f the flattening of the WGS84 ellipsoid.
*
* (The WGS84 value is returned because the supported geoid models are all
* based on this ellipsoid.)
**********************************************************************/
Math::real Flattening() const { return Constants::WGS84_f(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* @return the default path for geoid data files.
*
* This is the value of the environment variable GEOGRAPHICLIB_GEOID_PATH,
* if set; otherwise, it is $GEOGRAPHICLIB_DATA/geoids if the environment
* variable GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time
* default (/usr/local/share/GeographicLib/geoids on non-Windows systems
* and C:/ProgramData/GeographicLib/geoids on Windows systems).
**********************************************************************/
static std::string DefaultGeoidPath();
/**
* @return the default name for the geoid.
*
* This is the value of the environment variable GEOGRAPHICLIB_GEOID_NAME,
* if set; otherwise, it is "egm96-5". The Geoid class does not use this
* function; it is just provided as a convenience for a calling program
* when constructing a Geoid object.
**********************************************************************/
static std::string DefaultGeoidName();
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_GEOID_HPP

161
external/include/GeographicLib/Georef.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,161 @@
/**
* \file Georef.hpp
* \brief Header for GeographicLib::Georef class
*
* Copyright (c) Charles Karney (2015-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GEOREF_HPP)
#define GEOGRAPHICLIB_GEOREF_HPP 1
#include <GeographicLib/Constants.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs string
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
/**
* \brief Conversions for the World Geographic Reference System (georef)
*
* The World Geographic Reference System is described in
* - https://en.wikipedia.org/wiki/Georef
* - https://web.archive.org/web/20161214054445/http://earth-info.nga.mil/GandG/coordsys/grids/georef.pdf
* .
* It provides a compact string representation of a geographic area
* (expressed as latitude and longitude). The classes GARS and Geohash
* implement similar compact representations.
*
* Example of use:
* \include example-Georef.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Georef {
private:
typedef Math::real real;
static const char* const digits_;
static const char* const lontile_;
static const char* const lattile_;
static const char* const degrees_;
enum {
tile_ = 15, // The size of tile in degrees
lonorig_ = -180, // Origin for longitude
latorig_ = -90, // Origin for latitude
base_ = 10, // Base for minutes
baselen_ = 4,
maxprec_ = 11, // approximately equivalent to MGRS class
maxlen_ = baselen_ + 2 * maxprec_,
};
Georef(); // Disable constructor
public:
/**
* Convert from geographic coordinates to georef.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] prec the precision of the resulting georef.
* @param[out] georef the georef string.
* @exception GeographicErr if \e lat is not in [&minus;90&deg;,
* 90&deg;].
* @exception std::bad_alloc if memory for \e georef can't be allocated.
*
* \e prec specifies the precision of \e georef as follows:
* - \e prec = &minus;1 (min), 15&deg;
* - \e prec = 0, 1&deg;
* - \e prec = 1, converted to \e prec = 2
* - \e prec = 2, 1'
* - \e prec = 3, 0.1'
* - \e prec = 4, 0.01'
* - \e prec = 5, 0.001'
* - &hellip;
* - \e prec = 11 (max), 10<sup>&minus;9</sup>'
*
* If \e lat or \e lon is NaN, then \e georef is set to "INVALID".
**********************************************************************/
static void Forward(real lat, real lon, int prec, std::string& georef);
/**
* Convert from Georef to geographic coordinates.
*
* @param[in] georef the Georef.
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] prec the precision of \e georef.
* @param[in] centerp if true (the default) return the center
* \e georef, otherwise return the south-west corner.
* @exception GeographicErr if \e georef is illegal.
*
* The case of the letters in \e georef is ignored. \e prec is in the
* range [&minus;1, 11] and gives the precision of \e georef as follows:
* - \e prec = &minus;1 (min), 15&deg;
* - \e prec = 0, 1&deg;
* - \e prec = 1, not returned
* - \e prec = 2, 1'
* - \e prec = 3, 0.1'
* - \e prec = 4, 0.01'
* - \e prec = 5, 0.001'
* - &hellip;
* - \e prec = 11 (max), 10<sup>&minus;9</sup>'
*
* If the first 3 characters of \e georef are "INV", then \e lat and \e lon
* are set to NaN and \e prec is unchanged.
**********************************************************************/
static void Reverse(const std::string& georef, real& lat, real& lon,
int& prec, bool centerp = true);
/**
* The angular resolution of a Georef.
*
* @param[in] prec the precision of the Georef.
* @return the latitude-longitude resolution (degrees).
*
* Internally, \e prec is first put in the range [&minus;1, 11].
**********************************************************************/
static Math::real Resolution(int prec) {
if (prec < 1)
return real(prec < 0 ? 15 : 1);
else {
using std::pow;
// Treat prec = 1 as 2.
prec = (std::max)(2, (std::min)(int(maxprec_), prec));
// Need extra real because, since C++11, pow(float, int) returns double
return 1/(60 * real(pow(real(base_), prec - 2)));
}
}
/**
* The Georef precision required to meet a given geographic resolution.
*
* @param[in] res the minimum of resolution in latitude and longitude
* (degrees).
* @return Georef precision.
*
* The returned length is in the range [0, 11].
**********************************************************************/
static int Precision(real res) {
using std::abs; res = abs(res);
for (int prec = 0; prec < maxprec_; ++prec) {
if (prec == 1)
continue;
if (Resolution(prec) <= res)
return prec;
}
return maxprec_;
}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_GEOREF_HPP

221
external/include/GeographicLib/Gnomonic.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,221 @@
/**
* \file Gnomonic.hpp
* \brief Header for GeographicLib::Gnomonic class
*
* Copyright (c) Charles Karney (2010-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GNOMONIC_HPP)
#define GEOGRAPHICLIB_GNOMONIC_HPP 1
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/GeodesicLine.hpp>
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief %Gnomonic projection
*
* %Gnomonic projection centered at an arbitrary position \e C on the
* ellipsoid. This projection is derived in Section 8 of
* - C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-012-0578-z">
* Algorithms for geodesics</a>,
* J. Geodesy <b>87</b>, 43--55 (2013);
* DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
* 10.1007/s00190-012-0578-z</a>;
* addenda:
* <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
* geod-addenda.html</a>.
* .
* The projection of \e P is defined as follows: compute the geodesic line
* from \e C to \e P; compute the reduced length \e m12, geodesic scale \e
* M12, and &rho; = <i>m12</i>/\e M12; finally \e x = &rho; sin \e azi1; \e
* y = &rho; cos \e azi1, where \e azi1 is the azimuth of the geodesic at \e
* C. The Gnomonic::Forward and Gnomonic::Reverse methods also return the
* azimuth \e azi of the geodesic at \e P and reciprocal scale \e rk in the
* azimuthal direction. The scale in the radial direction if
* 1/<i>rk</i><sup>2</sup>.
*
* For a sphere, &rho; is reduces to \e a tan(<i>s12</i>/<i>a</i>), where \e
* s12 is the length of the geodesic from \e C to \e P, and the gnomonic
* projection has the property that all geodesics appear as straight lines.
* For an ellipsoid, this property holds only for geodesics interesting the
* centers. However geodesic segments close to the center are approximately
* straight.
*
* Consider a geodesic segment of length \e l. Let \e T be the point on the
* geodesic (extended if necessary) closest to \e C the center of the
* projection and \e t be the distance \e CT. To lowest order, the maximum
* deviation (as a true distance) of the corresponding gnomonic line segment
* (i.e., with the same end points) from the geodesic is<br>
* <br>
* (<i>K</i>(<i>T</i>) - <i>K</i>(<i>C</i>))
* <i>l</i><sup>2</sup> \e t / 32.<br>
* <br>
* where \e K is the Gaussian curvature.
*
* This result applies for any surface. For an ellipsoid of revolution,
* consider all geodesics whose end points are within a distance \e r of \e
* C. For a given \e r, the deviation is maximum when the latitude of \e C
* is 45&deg;, when endpoints are a distance \e r away, and when their
* azimuths from the center are &plusmn; 45&deg; or &plusmn; 135&deg;.
* To lowest order in \e r and the flattening \e f, the deviation is \e f
* (<i>r</i>/2<i>a</i>)<sup>3</sup> \e r.
*
* The conversions all take place using a Geodesic object (by default
* Geodesic::WGS84()). For more information on geodesics see \ref geodesic.
*
* \warning The definition of this projection for a sphere is
* standard. However, there is no standard for how it should be extended to
* an ellipsoid. The choices are:
* - Declare that the projection is undefined for an ellipsoid.
* - Project to a tangent plane from the center of the ellipsoid. This
* causes great ellipses to appear as straight lines in the projection;
* i.e., it generalizes the spherical great circle to a great ellipse.
* This was proposed by independently by Bowring and Williams in 1997.
* - Project to the conformal sphere with the constant of integration chosen
* so that the values of the latitude match for the center point and
* perform a central projection onto the plane tangent to the conformal
* sphere at the center point. This causes normal sections through the
* center point to appear as straight lines in the projection; i.e., it
* generalizes the spherical great circle to a normal section. This was
* proposed by I. G. Letoval'tsev, Generalization of the gnomonic
* projection for a spheroid and the principal geodetic problems involved
* in the alignment of surface routes, Geodesy and Aerophotography (5),
* 271--274 (1963).
* - The projection given here. This causes geodesics close to the center
* point to appear as straight lines in the projection; i.e., it
* generalizes the spherical great circle to a geodesic.
*
* Example of use:
* \include example-Gnomonic.cpp
*
* <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utility
* providing access to the functionality of AzimuthalEquidistant, Gnomonic,
* and CassiniSoldner.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Gnomonic {
private:
typedef Math::real real;
real eps0_, eps_;
Geodesic _earth;
real _a, _f;
// numit_ increased from 10 to 20 to fix convergence failure with high
// precision (e.g., GEOGRAPHICLIB_DIGITS=2000) calculations. Reverse uses
// Newton's method which converges quadratically and so numit_ = 10 would
// normally be big enough. However, since the Geodesic class is based on a
// series it is of limited accuracy; in particular, the derivative rules
// used by Reverse only hold approximately. Consequently, after a few
// iterations, the convergence in the Reverse falls back to improvements in
// each step by a constant (albeit small) factor.
static const int numit_ = 20;
public:
/**
* Constructor for Gnomonic.
*
* @param[in] earth the Geodesic object to use for geodesic calculations.
* By default this uses the WGS84 ellipsoid.
**********************************************************************/
explicit Gnomonic(const Geodesic& earth = Geodesic::WGS84());
/**
* Forward projection, from geographic to gnomonic.
*
* @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] azi azimuth of geodesic at point (degrees).
* @param[out] rk reciprocal of azimuthal scale at point.
*
* \e lat0 and \e lat should be in the range [&minus;90&deg;, 90&deg;].
* The scale of the projection is 1/<i>rk</i><sup>2</sup> in the "radial"
* direction, \e azi clockwise from true north, and is 1/\e rk in the
* direction perpendicular to this. If the point lies "over the horizon",
* i.e., if \e rk &le; 0, then NaNs are returned for \e x and \e y (the
* correct values are returned for \e azi and \e rk). A call to Forward
* followed by a call to Reverse will return the original (\e lat, \e lon)
* (to within roundoff) provided the point in not over the horizon.
**********************************************************************/
void Forward(real lat0, real lon0, real lat, real lon,
real& x, real& y, real& azi, real& rk) const;
/**
* Reverse projection, from gnomonic to geographic.
*
* @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] azi azimuth of geodesic at point (degrees).
* @param[out] rk reciprocal of azimuthal scale at point.
*
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;]. \e lat will
* be in the range [&minus;90&deg;, 90&deg;] and \e lon will be in the
* range [&minus;180&deg;, 180&deg;]. The scale of the projection is
* 1/<i>rk</i><sup>2</sup> in the "radial" direction, \e azi clockwise from
* true north, and is 1/\e rk in the direction perpendicular to this. Even
* though all inputs should return a valid \e lat and \e lon, it's possible
* that the procedure fails to converge for very large \e x or \e y; in
* this case NaNs are returned for all the output arguments. A call to
* Reverse followed by a call to Forward will return the original (\e x, \e
* y) (to roundoff).
**********************************************************************/
void Reverse(real lat0, real lon0, real x, real y,
real& lat, real& lon, real& azi, real& rk) const;
/**
* Gnomonic::Forward without returning the azimuth and scale.
**********************************************************************/
void Forward(real lat0, real lon0, real lat, real lon,
real& x, real& y) const {
real azi, rk;
Forward(lat0, lon0, lat, lon, x, y, azi, rk);
}
/**
* Gnomonic::Reverse without returning the azimuth and scale.
**********************************************************************/
void Reverse(real lat0, real lon0, real x, real y,
real& lat, real& lon) const {
real azi, rk;
Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GNOMONIC_HPP

287
external/include/GeographicLib/GravityCircle.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,287 @@
/**
* \file GravityCircle.hpp
* \brief Header for GeographicLib::GravityCircle class
*
* Copyright (c) Charles Karney (2011-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GRAVITYCIRCLE_HPP)
#define GEOGRAPHICLIB_GRAVITYCIRCLE_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/CircularEngine.hpp>
#include <GeographicLib/GravityModel.hpp>
namespace GeographicLib {
/**
* \brief Gravity on a circle of latitude
*
* Evaluate the earth's gravity field on a circle of constant height and
* latitude. This uses a CircularEngine to pre-evaluate the inner sum of the
* spherical harmonic sum, allowing the values of the field at several
* different longitudes to be evaluated rapidly.
*
* Use GravityModel::Circle to create a GravityCircle object. (The
* constructor for this class is private.)
*
* See \ref gravityparallel for an example of using GravityCircle (together
* with OpenMP) to speed up the computation of geoid heights.
*
* Example of use:
* \include example-GravityCircle.cpp
*
* <a href="Gravity.1.html">Gravity</a> is a command-line utility providing
* access to the functionality of GravityModel and GravityCircle.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GravityCircle {
private:
typedef Math::real real;
enum mask {
NONE = GravityModel::NONE,
GRAVITY = GravityModel::GRAVITY,
DISTURBANCE = GravityModel::DISTURBANCE,
DISTURBING_POTENTIAL = GravityModel::DISTURBING_POTENTIAL,
GEOID_HEIGHT = GravityModel::GEOID_HEIGHT,
SPHERICAL_ANOMALY = GravityModel::SPHERICAL_ANOMALY,
ALL = GravityModel::ALL,
};
unsigned _caps;
real _a, _f, _lat, _h, _Z, _Px, _invR, _cpsi, _spsi,
_cphi, _sphi, _amodel, _GMmodel, _dzonal0,
_corrmult, _gamma0, _gamma, _frot;
CircularEngine _gravitational, _disturbing, _correction;
GravityCircle(mask caps, real a, real f, real lat, real h,
real Z, real P, real cphi, real sphi,
real amodel, real GMmodel,
real dzonal0, real corrmult,
real gamma0, real gamma, real frot,
const CircularEngine& gravitational,
const CircularEngine& disturbing,
const CircularEngine& correction);
friend class GravityModel; // GravityModel calls the private constructor
Math::real W(real slam, real clam,
real& gX, real& gY, real& gZ) const;
Math::real V(real slam, real clam,
real& gX, real& gY, real& gZ) const;
Math::real InternalT(real slam, real clam,
real& deltaX, real& deltaY, real& deltaZ,
bool gradp, bool correct) const;
public:
/**
* A default constructor for the normal gravity. This sets up an
* uninitialized object which can be later replaced by the
* GravityModel::Circle.
**********************************************************************/
GravityCircle() : _a(-1) {}
/** \name Compute the gravitational field
**********************************************************************/
///@{
/**
* Evaluate the gravity.
*
* @param[in] lon the geographic longitude (degrees).
* @param[out] gx the easterly component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gy the northerly component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gz the upward component of the acceleration
* (m s<sup>&minus;2</sup>); this is usually negative.
* @return \e W the sum of the gravitational and centrifugal potentials
* (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* The function includes the effects of the earth's rotation.
**********************************************************************/
Math::real Gravity(real lon, real& gx, real& gy, real& gz) const;
/**
* Evaluate the gravity disturbance vector.
*
* @param[in] lon the geographic longitude (degrees).
* @param[out] deltax the easterly component of the disturbance vector
* (m s<sup>&minus;2</sup>).
* @param[out] deltay the northerly component of the disturbance vector
* (m s<sup>&minus;2</sup>).
* @param[out] deltaz the upward component of the disturbance vector
* (m s<sup>&minus;2</sup>).
* @return \e T the corresponding disturbing potential
* (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real Disturbance(real lon, real& deltax, real& deltay, real& deltaz)
const;
/**
* Evaluate the geoid height.
*
* @param[in] lon the geographic longitude (degrees).
* @return \e N the height of the geoid above the reference ellipsoid
* (meters).
*
* Some approximations are made in computing the geoid height so that the
* results of the NGA codes are reproduced accurately. Details are given
* in \ref gravitygeoid.
**********************************************************************/
Math::real GeoidHeight(real lon) const;
/**
* Evaluate the components of the gravity anomaly vector using the
* spherical approximation.
*
* @param[in] lon the geographic longitude (degrees).
* @param[out] Dg01 the gravity anomaly (m s<sup>&minus;2</sup>).
* @param[out] xi the northerly component of the deflection of the vertical
* (degrees).
* @param[out] eta the easterly component of the deflection of the vertical
* (degrees).
*
* The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used
* so that the results of the NGA codes are reproduced accurately.
* approximations used here. Details are given in \ref gravitygeoid.
**********************************************************************/
void SphericalAnomaly(real lon, real& Dg01, real& xi, real& eta)
const;
/**
* Evaluate the components of the acceleration due to gravity and the
* centrifugal acceleration in geocentric coordinates.
*
* @param[in] lon the geographic longitude (degrees).
* @param[out] gX the \e X component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gY the \e Y component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gZ the \e Z component of the acceleration
* (m s<sup>&minus;2</sup>).
* @return \e W = \e V + &Phi; the sum of the gravitational and
* centrifugal potentials (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real W(real lon, real& gX, real& gY, real& gZ) const {
real slam, clam;
Math::sincosd(lon, slam, clam);
return W(slam, clam, gX, gY, gZ);
}
/**
* Evaluate the components of the acceleration due to gravity in geocentric
* coordinates.
*
* @param[in] lon the geographic longitude (degrees).
* @param[out] GX the \e X component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] GY the \e Y component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] GZ the \e Z component of the acceleration
* (m s<sup>&minus;2</sup>).
* @return \e V = \e W - &Phi; the gravitational potential
* (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real V(real lon, real& GX, real& GY, real& GZ) const {
real slam, clam;
Math::sincosd(lon, slam, clam);
return V(slam, clam, GX, GY, GZ);
}
/**
* Evaluate the components of the gravity disturbance in geocentric
* coordinates.
*
* @param[in] lon the geographic longitude (degrees).
* @param[out] deltaX the \e X component of the gravity disturbance
* (m s<sup>&minus;2</sup>).
* @param[out] deltaY the \e Y component of the gravity disturbance
* (m s<sup>&minus;2</sup>).
* @param[out] deltaZ the \e Z component of the gravity disturbance
* (m s<sup>&minus;2</sup>).
* @return \e T = \e W - \e U the disturbing potential (also called the
* anomalous potential) (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real T(real lon, real& deltaX, real& deltaY, real& deltaZ)
const {
real slam, clam;
Math::sincosd(lon, slam, clam);
return InternalT(slam, clam, deltaX, deltaY, deltaZ, true, true);
}
/**
* Evaluate disturbing potential in geocentric coordinates.
*
* @param[in] lon the geographic longitude (degrees).
* @return \e T = \e W - \e U the disturbing potential (also called the
* anomalous potential) (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real T(real lon) const {
real slam, clam, dummy;
Math::sincosd(lon, slam, clam);
return InternalT(slam, clam, dummy, dummy, dummy, false, true);
}
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _a > 0; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the GravityModel object used in the
* constructor.
**********************************************************************/
Math::real EquatorialRadius() const
{ return Init() ? _a : Math::NaN(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the GravityModel object used in the constructor.
**********************************************************************/
Math::real Flattening() const
{ return Init() ? _f : Math::NaN(); }
/**
* @return the latitude of the circle (degrees).
**********************************************************************/
Math::real Latitude() const
{ return Init() ? _lat : Math::NaN(); }
/**
* @return the height of the circle (meters).
**********************************************************************/
Math::real Height() const
{ return Init() ? _h : Math::NaN(); }
/**
* @return \e caps the computational capabilities that this object was
* constructed with.
**********************************************************************/
unsigned Capabilities() const { return _caps; }
/**
* @param[in] testcaps a set of bitor'ed GravityModel::mask values.
* @return true if the GravityCircle object has all these capabilities.
**********************************************************************/
bool Capabilities(unsigned testcaps) const {
return (_caps & testcaps) == testcaps;
}
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_GRAVITYCIRCLE_HPP

549
external/include/GeographicLib/GravityModel.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,549 @@
/**
* \file GravityModel.hpp
* \brief Header for GeographicLib::GravityModel class
*
* Copyright (c) Charles Karney (2011-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_GRAVITYMODEL_HPP)
#define GEOGRAPHICLIB_GRAVITYMODEL_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/NormalGravity.hpp>
#include <GeographicLib/SphericalHarmonic.hpp>
#include <GeographicLib/SphericalHarmonic1.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
class GravityCircle;
/**
* \brief Model of the earth's gravity field
*
* Evaluate the earth's gravity field according to a model. The supported
* models treat only the gravitational field exterior to the mass of the
* earth. When computing the field at points near (but above) the surface of
* the earth a small correction can be applied to account for the mass of the
* atmosphere above the point in question; see \ref gravityatmos.
* Determining the height of the geoid above the ellipsoid entails correcting
* for the mass of the earth above the geoid. The egm96 and egm2008 include
* separate correction terms to account for this mass.
*
* Definitions and terminology (from Heiskanen and Moritz, Sec 2-13):
* - \e V = gravitational potential;
* - &Phi; = rotational potential;
* - \e W = \e V + &Phi; = \e T + \e U = total potential;
* - <i>V</i><sub>0</sub> = normal gravitation potential;
* - \e U = <i>V</i><sub>0</sub> + &Phi; = total normal potential;
* - \e T = \e W &minus; \e U = \e V &minus; <i>V</i><sub>0</sub> = anomalous
* or disturbing potential;
* - <b>g</b> = &nabla;\e W = <b>&gamma;</b> + <b>&delta;</b>;
* - <b>f</b> = &nabla;&Phi;;
* - <b>&Gamma;</b> = &nabla;<i>V</i><sub>0</sub>;
* - <b>&gamma;</b> = &nabla;\e U;
* - <b>&delta;</b> = &nabla;\e T = gravity disturbance vector
* = <b>g</b><sub><i>P</i></sub> &minus; <b>&gamma;</b><sub><i>P</i></sub>;
* - &delta;\e g = gravity disturbance = <i>g</i><sub><i>P</i></sub> &minus;
* &gamma;<sub><i>P</i></sub>;
* - &Delta;<b>g</b> = gravity anomaly vector = <b>g</b><sub><i>P</i></sub>
* &minus; <b>&gamma;</b><sub><i>Q</i></sub>; here the line \e PQ is
* perpendicular to ellipsoid and the potential at \e P equals the normal
* potential at \e Q;
* - &Delta;\e g = gravity anomaly = <i>g</i><sub><i>P</i></sub> &minus;
* &gamma;<sub><i>Q</i></sub>;
* - (&xi;, &eta;) deflection of the vertical, the difference in
* directions of <b>g</b><sub><i>P</i></sub> and
* <b>&gamma;</b><sub><i>Q</i></sub>, &xi; = NS, &eta; = EW.
* - \e X, \e Y, \e Z, geocentric coordinates;
* - \e x, \e y, \e z, local cartesian coordinates used to denote the east,
* north and up directions.
*
* See \ref gravity for details of how to install the gravity models and the
* data format.
*
* References:
* - W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San
* Francisco, 1967).
*
* Example of use:
* \include example-GravityModel.cpp
*
* <a href="Gravity.1.html">Gravity</a> is a command-line utility providing
* access to the functionality of GravityModel and GravityCircle.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT GravityModel {
private:
typedef Math::real real;
friend class GravityCircle;
static const int idlength_ = 8;
std::string _name, _dir, _description, _date, _filename, _id;
real _amodel, _GMmodel, _zeta0, _corrmult;
int _nmx, _mmx;
SphericalHarmonic::normalization _norm;
NormalGravity _earth;
std::vector<real> _Cx, _Sx, _CC, _CS, _zonal;
real _dzonal0; // A left over contribution to _zonal.
SphericalHarmonic _gravitational;
SphericalHarmonic1 _disturbing;
SphericalHarmonic _correction;
void ReadMetadata(const std::string& name);
Math::real InternalT(real X, real Y, real Z,
real& deltaX, real& deltaY, real& deltaZ,
bool gradp, bool correct) const;
GravityModel(const GravityModel&) = delete; // copy constructor not allowed
// nor copy assignment
GravityModel& operator=(const GravityModel&) = delete;
enum captype {
CAP_NONE = 0U,
CAP_G = 1U<<0, // implies potentials W and V
CAP_T = 1U<<1,
CAP_DELTA = 1U<<2 | CAP_T, // delta implies T?
CAP_C = 1U<<3,
CAP_GAMMA0 = 1U<<4,
CAP_GAMMA = 1U<<5,
CAP_ALL = 0x3FU,
};
public:
/**
* Bit masks for the capabilities to be given to the GravityCircle object
* produced by Circle.
**********************************************************************/
enum mask {
/**
* No capabilities.
* @hideinitializer
**********************************************************************/
NONE = 0U,
/**
* Allow calls to GravityCircle::Gravity, GravityCircle::W, and
* GravityCircle::V.
* @hideinitializer
**********************************************************************/
GRAVITY = CAP_G,
/**
* Allow calls to GravityCircle::Disturbance and GravityCircle::T.
* @hideinitializer
**********************************************************************/
DISTURBANCE = CAP_DELTA,
/**
* Allow calls to GravityCircle::T(real lon) (i.e., computing the
* disturbing potential and not the gravity disturbance vector).
* @hideinitializer
**********************************************************************/
DISTURBING_POTENTIAL = CAP_T,
/**
* Allow calls to GravityCircle::SphericalAnomaly.
* @hideinitializer
**********************************************************************/
SPHERICAL_ANOMALY = CAP_DELTA | CAP_GAMMA,
/**
* Allow calls to GravityCircle::GeoidHeight.
* @hideinitializer
**********************************************************************/
GEOID_HEIGHT = CAP_T | CAP_C | CAP_GAMMA0,
/**
* All capabilities.
* @hideinitializer
**********************************************************************/
ALL = CAP_ALL,
};
/** \name Setting up the gravity model
**********************************************************************/
///@{
/**
* Construct a gravity model.
*
* @param[in] name the name of the model.
* @param[in] path (optional) directory for data file.
* @param[in] Nmax (optional) if non-negative, truncate the degree of the
* model this value.
* @param[in] Mmax (optional) if non-negative, truncate the order of the
* model this value.
* @exception GeographicErr if the data file cannot be found, is
* unreadable, or is corrupt, or if \e Mmax > \e Nmax.
* @exception std::bad_alloc if the memory necessary for storing the model
* can't be allocated.
*
* A filename is formed by appending ".egm" (World Gravity Model) to the
* name. If \e path is specified (and is non-empty), then the file is
* loaded from directory, \e path. Otherwise the path is given by
* DefaultGravityPath().
*
* This file contains the metadata which specifies the properties of the
* model. The coefficients for the spherical harmonic sums are obtained
* from a file obtained by appending ".cof" to metadata file (so the
* filename ends in ".egm.cof").
*
* If \e Nmax &ge; 0 and \e Mmax < 0, then \e Mmax is set to \e Nmax.
* After the model is loaded, the maximum degree and order of the model can
* be found by the Degree() and Order() methods.
**********************************************************************/
explicit GravityModel(const std::string& name,
const std::string& path = "",
int Nmax = -1, int Mmax = -1);
///@}
/** \name Compute gravity in geodetic coordinates
**********************************************************************/
///@{
/**
* Evaluate the gravity at an arbitrary point above (or below) the
* ellipsoid.
*
* @param[in] lat the geographic latitude (degrees).
* @param[in] lon the geographic longitude (degrees).
* @param[in] h the height above the ellipsoid (meters).
* @param[out] gx the easterly component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gy the northerly component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gz the upward component of the acceleration
* (m s<sup>&minus;2</sup>); this is usually negative.
* @return \e W the sum of the gravitational and centrifugal potentials
* (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* The function includes the effects of the earth's rotation.
**********************************************************************/
Math::real Gravity(real lat, real lon, real h,
real& gx, real& gy, real& gz) const;
/**
* Evaluate the gravity disturbance vector at an arbitrary point above (or
* below) the ellipsoid.
*
* @param[in] lat the geographic latitude (degrees).
* @param[in] lon the geographic longitude (degrees).
* @param[in] h the height above the ellipsoid (meters).
* @param[out] deltax the easterly component of the disturbance vector
* (m s<sup>&minus;2</sup>).
* @param[out] deltay the northerly component of the disturbance vector
* (m s<sup>&minus;2</sup>).
* @param[out] deltaz the upward component of the disturbance vector
* (m s<sup>&minus;2</sup>).
* @return \e T the corresponding disturbing potential
* (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real Disturbance(real lat, real lon, real h,
real& deltax, real& deltay, real& deltaz)
const;
/**
* Evaluate the geoid height.
*
* @param[in] lat the geographic latitude (degrees).
* @param[in] lon the geographic longitude (degrees).
* @return \e N the height of the geoid above the ReferenceEllipsoid()
* (meters).
*
* This calls NormalGravity::U for ReferenceEllipsoid(). Some
* approximations are made in computing the geoid height so that the
* results of the NGA codes are reproduced accurately. Details are given
* in \ref gravitygeoid.
**********************************************************************/
Math::real GeoidHeight(real lat, real lon) const;
/**
* Evaluate the components of the gravity anomaly vector using the
* spherical approximation.
*
* @param[in] lat the geographic latitude (degrees).
* @param[in] lon the geographic longitude (degrees).
* @param[in] h the height above the ellipsoid (meters).
* @param[out] Dg01 the gravity anomaly (m s<sup>&minus;2</sup>).
* @param[out] xi the northerly component of the deflection of the vertical
* (degrees).
* @param[out] eta the easterly component of the deflection of the vertical
* (degrees).
*
* The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used
* so that the results of the NGA codes are reproduced accurately.
* approximations used here. Details are given in \ref gravitygeoid.
**********************************************************************/
void SphericalAnomaly(real lat, real lon, real h,
real& Dg01, real& xi, real& eta) const;
///@}
/** \name Compute gravity in geocentric coordinates
**********************************************************************/
///@{
/**
* Evaluate the components of the acceleration due to gravity and the
* centrifugal acceleration in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @param[out] gX the \e X component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gY the \e Y component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gZ the \e Z component of the acceleration
* (m s<sup>&minus;2</sup>).
* @return \e W = \e V + &Phi; the sum of the gravitational and
* centrifugal potentials (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* This calls NormalGravity::U for ReferenceEllipsoid().
**********************************************************************/
Math::real W(real X, real Y, real Z,
real& gX, real& gY, real& gZ) const;
/**
* Evaluate the components of the acceleration due to gravity in geocentric
* coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @param[out] GX the \e X component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] GY the \e Y component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] GZ the \e Z component of the acceleration
* (m s<sup>&minus;2</sup>).
* @return \e V = \e W - &Phi; the gravitational potential
* (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real V(real X, real Y, real Z,
real& GX, real& GY, real& GZ) const;
/**
* Evaluate the components of the gravity disturbance in geocentric
* coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @param[out] deltaX the \e X component of the gravity disturbance
* (m s<sup>&minus;2</sup>).
* @param[out] deltaY the \e Y component of the gravity disturbance
* (m s<sup>&minus;2</sup>).
* @param[out] deltaZ the \e Z component of the gravity disturbance
* (m s<sup>&minus;2</sup>).
* @return \e T = \e W - \e U the disturbing potential (also called the
* anomalous potential) (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real T(real X, real Y, real Z,
real& deltaX, real& deltaY, real& deltaZ) const
{ return InternalT(X, Y, Z, deltaX, deltaY, deltaZ, true, true); }
/**
* Evaluate disturbing potential in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @return \e T = \e W - \e U the disturbing potential (also called the
* anomalous potential) (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real T(real X, real Y, real Z) const {
real dummy;
return InternalT(X, Y, Z, dummy, dummy, dummy, false, true);
}
/**
* Evaluate the components of the acceleration due to normal gravity and
* the centrifugal acceleration in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @param[out] gammaX the \e X component of the normal acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gammaY the \e Y component of the normal acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gammaZ the \e Z component of the normal acceleration
* (m s<sup>&minus;2</sup>).
* @return \e U = <i>V</i><sub>0</sub> + &Phi; the sum of the
* normal gravitational and centrifugal potentials
* (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* This calls NormalGravity::U for ReferenceEllipsoid().
**********************************************************************/
Math::real U(real X, real Y, real Z,
real& gammaX, real& gammaY, real& gammaZ) const
{ return _earth.U(X, Y, Z, gammaX, gammaY, gammaZ); }
/**
* Evaluate the centrifugal acceleration in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[out] fX the \e X component of the centrifugal acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] fY the \e Y component of the centrifugal acceleration
* (m s<sup>&minus;2</sup>).
* @return &Phi; the centrifugal potential (m<sup>2</sup>
* s<sup>&minus;2</sup>).
*
* This calls NormalGravity::Phi for ReferenceEllipsoid().
**********************************************************************/
Math::real Phi(real X, real Y, real& fX, real& fY) const
{ return _earth.Phi(X, Y, fX, fY); }
///@}
/** \name Compute gravity on a circle of constant latitude
**********************************************************************/
///@{
/**
* Create a GravityCircle object to allow the gravity field at many points
* with constant \e lat and \e h and varying \e lon to be computed
* efficiently.
*
* @param[in] lat latitude of the point (degrees).
* @param[in] h the height of the point above the ellipsoid (meters).
* @param[in] caps bitor'ed combination of GravityModel::mask values
* specifying the capabilities of the resulting GravityCircle object.
* @exception std::bad_alloc if the memory necessary for creating a
* GravityCircle can't be allocated.
* @return a GravityCircle object whose member functions computes the
* gravitational field at a particular values of \e lon.
*
* The GravityModel::mask values are
* - \e caps |= GravityModel::GRAVITY
* - \e caps |= GravityModel::DISTURBANCE
* - \e caps |= GravityModel::DISTURBING_POTENTIAL
* - \e caps |= GravityModel::SPHERICAL_ANOMALY
* - \e caps |= GravityModel::GEOID_HEIGHT
* .
* The default value of \e caps is GravityModel::ALL which turns on all the
* capabilities. If an unsupported function is invoked, it will return
* NaNs. Note that GravityModel::GEOID_HEIGHT will only be honored if \e h
* = 0.
*
* If the field at several points on a circle of latitude need to be
* calculated then creating a GravityCircle object and using its member
* functions will be substantially faster, especially for high-degree
* models. See \ref gravityparallel for an example of using GravityCircle
* (together with OpenMP) to speed up the computation of geoid heights.
**********************************************************************/
GravityCircle Circle(real lat, real h, unsigned caps = ALL) const;
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return the NormalGravity object for the reference ellipsoid.
**********************************************************************/
const NormalGravity& ReferenceEllipsoid() const { return _earth; }
/**
* @return the description of the gravity model, if available, in the data
* file; if absent, return "NONE".
**********************************************************************/
const std::string& Description() const { return _description; }
/**
* @return date of the model; if absent, return "UNKNOWN".
**********************************************************************/
const std::string& DateTime() const { return _date; }
/**
* @return full file name used to load the gravity model.
**********************************************************************/
const std::string& GravityFile() const { return _filename; }
/**
* @return "name" used to load the gravity model (from the first argument
* of the constructor, but this may be overridden by the model file).
**********************************************************************/
const std::string& GravityModelName() const { return _name; }
/**
* @return directory used to load the gravity model.
**********************************************************************/
const std::string& GravityModelDirectory() const { return _dir; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters).
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e GM the mass constant of the model (m<sup>3</sup>
* s<sup>&minus;2</sup>); this is the product of \e G the gravitational
* constant and \e M the mass of the earth (usually including the mass of
* the earth's atmosphere).
**********************************************************************/
Math::real MassConstant() const { return _GMmodel; }
/**
* @return \e GM the mass constant of the ReferenceEllipsoid()
* (m<sup>3</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real ReferenceMassConstant() const
{ return _earth.MassConstant(); }
/**
* @return &omega; the angular velocity of the model and the
* ReferenceEllipsoid() (rad s<sup>&minus;1</sup>).
**********************************************************************/
Math::real AngularVelocity() const
{ return _earth.AngularVelocity(); }
/**
* @return \e f the flattening of the ellipsoid.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* @return \e Nmax the maximum degree of the components of the model.
**********************************************************************/
int Degree() const { return _nmx; }
/**
* @return \e Mmax the maximum order of the components of the model.
**********************************************************************/
int Order() const { return _mmx; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* @return the default path for gravity model data files.
*
* This is the value of the environment variable
* GEOGRAPHICLIB_GRAVITY_PATH, if set; otherwise, it is
* $GEOGRAPHICLIB_DATA/gravity if the environment variable
* GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default
* (/usr/local/share/GeographicLib/gravity on non-Windows systems and
* C:/ProgramData/GeographicLib/gravity on Windows systems).
**********************************************************************/
static std::string DefaultGravityPath();
/**
* @return the default name for the gravity model.
*
* This is the value of the environment variable
* GEOGRAPHICLIB_GRAVITY_NAME, if set; otherwise, it is "egm96". The
* GravityModel class does not use this function; it is just provided as a
* convenience for a calling program when constructing a GravityModel
* object.
**********************************************************************/
static std::string DefaultGravityName();
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_GRAVITYMODEL_HPP

330
external/include/GeographicLib/LambertConformalConic.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,330 @@
/**
* \file LambertConformalConic.hpp
* \brief Header for GeographicLib::LambertConformalConic class
*
* Copyright (c) Charles Karney (2010-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP)
#define GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP 1
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Lambert conformal conic projection
*
* Implementation taken from the report,
* - J. P. Snyder,
* <a href="http://pubs.er.usgs.gov/usgspubs/pp/pp1395"> Map Projections: A
* Working Manual</a>, USGS Professional Paper 1395 (1987),
* pp. 107--109.
*
* This is a implementation of the equations in Snyder except that divided
* differences have been used to transform the expressions into ones which
* may be evaluated accurately and that Newton's method is used to invert the
* projection. In this implementation, the projection correctly becomes the
* Mercator projection or the polar stereographic projection when the
* standard latitude is the equator or a pole. The accuracy of the
* projections is about 10 nm (10 nanometers).
*
* The ellipsoid parameters, the standard parallels, and the scale on the
* standard parallels are set in the constructor. Internally, the case with
* two standard parallels is converted into a single standard parallel, the
* latitude of tangency (also the latitude of minimum scale), with a scale
* specified on this parallel. This latitude is also used as the latitude of
* origin which is returned by LambertConformalConic::OriginLatitude. The
* scale on the latitude of origin is given by
* LambertConformalConic::CentralScale. The case with two distinct standard
* parallels where one is a pole is singular and is disallowed. The central
* meridian (which is a trivial shift of the longitude) is specified as the
* \e lon0 argument of the LambertConformalConic::Forward and
* LambertConformalConic::Reverse functions.
*
* This class also returns the meridian convergence \e gamma and scale \e k.
* The meridian convergence is the bearing of grid north (the \e y axis)
* measured clockwise from true north.
*
* There is no provision in this
* class for specifying a false easting or false northing or a different
* latitude of origin. However these are can be simply included by the
* calling function. For example the Pennsylvania South state coordinate
* system (<a href="https://www.spatialreference.org/ref/epsg/3364/">
* EPSG:3364</a>) is obtained by:
* \include example-LambertConformalConic.cpp
*
* <a href="ConicProj.1.html">ConicProj</a> is a command-line utility
* providing access to the functionality of LambertConformalConic and
* AlbersEqualArea.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT LambertConformalConic {
private:
typedef Math::real real;
real eps_, epsx_, ahypover_;
real _a, _f, _fm, _e2, _es;
real _sign, _n, _nc, _t0nm1, _scale, _lat0, _k0;
real _scbet0, _tchi0, _scchi0, _psi0, _nrho0, _drhomax;
static const int numit_ = 5;
static real hyp(real x) {
using std::hypot;
return hypot(real(1), x);
}
// Divided differences
// Definition: Df(x,y) = (f(x)-f(y))/(x-y)
// See:
// W. M. Kahan and R. J. Fateman,
// Symbolic computation of divided differences,
// SIGSAM Bull. 33(3), 7-28 (1999)
// https://doi.org/10.1145/334714.334716
// http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
//
// General rules
// h(x) = f(g(x)): Dh(x,y) = Df(g(x),g(y))*Dg(x,y)
// h(x) = f(x)*g(x):
// Dh(x,y) = Df(x,y)*g(x) + Dg(x,y)*f(y)
// = Df(x,y)*g(y) + Dg(x,y)*f(x)
// = Df(x,y)*(g(x)+g(y))/2 + Dg(x,y)*(f(x)+f(y))/2
//
// hyp(x) = sqrt(1+x^2): Dhyp(x,y) = (x+y)/(hyp(x)+hyp(y))
static real Dhyp(real x, real y, real hx, real hy)
// hx = hyp(x)
{ return (x + y) / (hx + hy); }
// sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^2))
static real Dsn(real x, real y, real sx, real sy) {
// sx = x/hyp(x)
real t = x * y;
return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) :
(x - y != 0 ? (sx - sy) / (x - y) : 1);
}
// Dlog1p(x,y) = log1p((x-y)/(1+y))/(x-y)
static real Dlog1p(real x, real y) {
using std::log1p;
real t = x - y; if (t < 0) { t = -t; y = x; }
return t != 0 ? log1p(t / (1 + y)) / t : 1 / (1 + x);
}
// Dexp(x,y) = exp((x+y)/2) * 2*sinh((x-y)/2)/(x-y)
static real Dexp(real x, real y) {
using std::sinh; using std::exp;
real t = (x - y)/2;
return (t != 0 ? sinh(t)/t : 1) * exp((x + y)/2);
}
// Dsinh(x,y) = 2*sinh((x-y)/2)/(x-y) * cosh((x+y)/2)
// cosh((x+y)/2) = (c+sinh(x)*sinh(y)/c)/2
// c=sqrt((1+cosh(x))*(1+cosh(y)))
// cosh((x+y)/2) = sqrt( (sinh(x)*sinh(y) + cosh(x)*cosh(y) + 1)/2 )
static real Dsinh(real x, real y, real sx, real sy, real cx, real cy)
// sx = sinh(x), cx = cosh(x)
{
// real t = (x - y)/2, c = sqrt((1 + cx) * (1 + cy));
// return (t ? sinh(t)/t : real(1)) * (c + sx * sy / c) /2;
using std::sinh; using std::sqrt;
real t = (x - y)/2;
return (t != 0 ? sinh(t)/t : 1) * sqrt((sx * sy + cx * cy + 1) /2);
}
// Dasinh(x,y) = asinh((x-y)*(x+y)/(x*sqrt(1+y^2)+y*sqrt(1+x^2)))/(x-y)
// = asinh((x*sqrt(1+y^2)-y*sqrt(1+x^2)))/(x-y)
static real Dasinh(real x, real y, real hx, real hy) {
// hx = hyp(x)
using std::asinh;
real t = x - y;
return t != 0 ?
asinh(x*y > 0 ? t * (x + y) / (x*hy + y*hx) : x*hy - y*hx) / t :
1 / hx;
}
// Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y)
real Deatanhe(real x, real y) const {
real t = x - y, d = 1 - _e2 * x * y;
return t != 0 ? Math::eatanhe(t / d, _es) / t : _e2 / d;
}
void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1);
public:
/**
* Constructor with a single standard parallel.
*
* @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] stdlat standard parallel (degrees), the circle of tangency.
* @param[in] k0 scale on the standard parallel.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive.
* @exception GeographicErr if \e stdlat is not in [&minus;90&deg;,
* 90&deg;].
**********************************************************************/
LambertConformalConic(real a, real f, real stdlat, real k0);
/**
* Constructor with two standard parallels.
*
* @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] stdlat1 first standard parallel (degrees).
* @param[in] stdlat2 second standard parallel (degrees).
* @param[in] k1 scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e
* stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
**********************************************************************/
LambertConformalConic(real a, real f, real stdlat1, real stdlat2, real k1);
/**
* Constructor with two standard parallels specified by sines and cosines.
*
* @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] sinlat1 sine of first standard parallel.
* @param[in] coslat1 cosine of first standard parallel.
* @param[in] sinlat2 sine of second standard parallel.
* @param[in] coslat2 cosine of second standard parallel.
* @param[in] k1 scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e
* stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
*
* This allows parallels close to the poles to be specified accurately.
* This routine computes the latitude of origin and the scale at this
* latitude. In the case where \e lat1 and \e lat2 are different, the
* errors in this routines are as follows: if \e dlat = abs(\e lat2 &minus;
* \e lat1) &le; 160&deg; and max(abs(\e lat1), abs(\e lat2)) &le; 90
* &minus; min(0.0002, 2.2 &times; 10<sup>&minus;6</sup>(180 &minus; \e
* dlat), 6 &times 10<sup>&minus;8</sup> <i>dlat</i><sup>2</sup>) (in
* degrees), then the error in the latitude of origin is less than 4.5
* &times; 10<sup>&minus;14</sup>d and the relative error in the scale is
* less than 7 &times; 10<sup>&minus;15</sup>.
**********************************************************************/
LambertConformalConic(real a, real f,
real sinlat1, real coslat1,
real sinlat2, real coslat2,
real k1);
/**
* Set the scale for the projection.
*
* @param[in] lat (degrees).
* @param[in] k scale at latitude \e lat (default 1).
* @exception GeographicErr \e k is not positive.
* @exception GeographicErr if \e lat is not in [&minus;90&deg;,
* 90&deg;].
**********************************************************************/
void SetScale(real lat, real k = real(1));
/**
* Forward projection, from geographic to Lambert conformal conic.
*
* @param[in] lon0 central meridian longitude (degrees).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* The latitude origin is given by LambertConformalConic::LatitudeOrigin().
* No false easting or northing is added and \e lat should be in the range
* [&minus;90&deg;, 90&deg;]. The error in the projection is less than
* about 10 nm (10 nanometers), true distance, and the errors in the
* meridian convergence and scale are consistent with this. The values of
* \e x and \e y returned for points which project to infinity (i.e., one
* or both of the poles) will be large but finite.
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y, real& gamma, real& k) const;
/**
* Reverse projection, from Lambert conformal conic to geographic.
*
* @param[in] lon0 central meridian longitude (degrees).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* The latitude origin is given by LambertConformalConic::LatitudeOrigin().
* No false easting or northing is added. The value of \e lon returned is
* in the range [&minus;180&deg;, 180&deg;]. The error in the projection
* is less than about 10 nm (10 nanometers), true distance, and the errors
* in the meridian convergence and scale are consistent with this.
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon, real& gamma, real& k) const;
/**
* LambertConformalConic::Forward without returning the convergence and
* scale.
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y) const {
real gamma, k;
Forward(lon0, lat, lon, x, y, gamma, k);
}
/**
* LambertConformalConic::Reverse without returning the convergence and
* scale.
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon) const {
real gamma, k;
Reverse(lon0, x, y, lat, lon, gamma, k);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the
* value used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return latitude of the origin for the projection (degrees).
*
* This is the latitude of minimum scale and equals the \e stdlat in the
* 1-parallel constructor and lies between \e stdlat1 and \e stdlat2 in the
* 2-parallel constructors.
**********************************************************************/
Math::real OriginLatitude() const { return _lat0; }
/**
* @return central scale for the projection. This is the scale on the
* latitude of origin.
**********************************************************************/
Math::real CentralScale() const { return _k0; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of LambertConformalConic with the WGS84
* ellipsoid, \e stdlat = 0, and \e k0 = 1. This degenerates to the
* Mercator projection.
**********************************************************************/
static const LambertConformalConic& Mercator();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP

244
external/include/GeographicLib/LocalCartesian.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,244 @@
/**
* \file LocalCartesian.hpp
* \brief Header for GeographicLib::LocalCartesian class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_LOCALCARTESIAN_HPP)
#define GEOGRAPHICLIB_LOCALCARTESIAN_HPP 1
#include <GeographicLib/Geocentric.hpp>
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Local cartesian coordinates
*
* Convert between geodetic coordinates latitude = \e lat, longitude = \e
* lon, height = \e h (measured vertically from the surface of the ellipsoid)
* to local cartesian coordinates (\e x, \e y, \e z). The origin of local
* cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h
* = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis points
* due north. The plane \e z = - \e h0 is tangent to the ellipsoid.
*
* The conversions all take place via geocentric coordinates using a
* Geocentric object (by default Geocentric::WGS84()).
*
* Example of use:
* \include example-LocalCartesian.cpp
*
* <a href="CartConvert.1.html">CartConvert</a> is a command-line utility
* providing access to the functionality of Geocentric and LocalCartesian.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT LocalCartesian {
private:
typedef Math::real real;
static const size_t dim_ = 3;
static const size_t dim2_ = dim_ * dim_;
Geocentric _earth;
real _lat0, _lon0, _h0;
real _x0, _y0, _z0, _r[dim2_];
void IntForward(real lat, real lon, real h, real& x, real& y, real& z,
real M[dim2_]) const;
void IntReverse(real x, real y, real z, real& lat, real& lon, real& h,
real M[dim2_]) const;
void MatrixMultiply(real M[dim2_]) const;
public:
/**
* Constructor setting the origin.
*
* @param[in] lat0 latitude at origin (degrees).
* @param[in] lon0 longitude at origin (degrees).
* @param[in] h0 height above ellipsoid at origin (meters); default 0.
* @param[in] earth Geocentric object for the transformation; default
* Geocentric::WGS84().
*
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
LocalCartesian(real lat0, real lon0, real h0 = 0,
const Geocentric& earth = Geocentric::WGS84())
: _earth(earth)
{ Reset(lat0, lon0, h0); }
/**
* Default constructor.
*
* @param[in] earth Geocentric object for the transformation; default
* Geocentric::WGS84().
*
* Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0.
**********************************************************************/
explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84())
: _earth(earth)
{ Reset(real(0), real(0), real(0)); }
/**
* Reset the origin.
*
* @param[in] lat0 latitude at origin (degrees).
* @param[in] lon0 longitude at origin (degrees).
* @param[in] h0 height above ellipsoid at origin (meters); default 0.
*
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
void Reset(real lat0, real lon0, real h0 = 0);
/**
* Convert from geodetic to local cartesian coordinates.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] h height of point above the ellipsoid (meters).
* @param[out] x local cartesian coordinate (meters).
* @param[out] y local cartesian coordinate (meters).
* @param[out] z local cartesian coordinate (meters).
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
void Forward(real lat, real lon, real h, real& x, real& y, real& z)
const {
IntForward(lat, lon, h, x, y, z, NULL);
}
/**
* Convert from geodetic to local cartesian coordinates and return rotation
* matrix.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[in] h height of point above the ellipsoid (meters).
* @param[out] x local cartesian coordinate (meters).
* @param[out] y local cartesian coordinate (meters).
* @param[out] z local cartesian coordinate (meters).
* @param[out] M if the length of the vector is 9, fill with the rotation
* matrix in row-major order.
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;].
*
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
* express \e v as \e column vectors in one of two ways
* - in east, north, up coordinates (where the components are relative to a
* local coordinate system at (\e lat, \e lon, \e h)); call this
* representation \e v1.
* - in \e x, \e y, \e z coordinates (where the components are relative to
* the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
* representation \e v0.
* .
* Then we have \e v0 = \e M &sdot; \e v1.
**********************************************************************/
void Forward(real lat, real lon, real h, real& x, real& y, real& z,
std::vector<real>& M)
const {
if (M.end() == M.begin() + dim2_) {
real t[dim2_];
IntForward(lat, lon, h, x, y, z, t);
std::copy(t, t + dim2_, M.begin());
} else
IntForward(lat, lon, h, x, y, z, NULL);
}
/**
* Convert from local cartesian to geodetic coordinates.
*
* @param[in] x local cartesian coordinate (meters).
* @param[in] y local cartesian coordinate (meters).
* @param[in] z local cartesian coordinate (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] h height of point above the ellipsoid (meters).
*
* In general, there are multiple solutions and the result which minimizes
* |<i>h</i> |is returned, i.e., (<i>lat</i>, <i>lon</i>) corresponds to
* the closest point on the ellipsoid. The value of \e lon returned is in
* the range [&minus;180&deg;, 180&deg;].
**********************************************************************/
void Reverse(real x, real y, real z, real& lat, real& lon, real& h)
const {
IntReverse(x, y, z, lat, lon, h, NULL);
}
/**
* Convert from local cartesian to geodetic coordinates and return rotation
* matrix.
*
* @param[in] x local cartesian coordinate (meters).
* @param[in] y local cartesian coordinate (meters).
* @param[in] z local cartesian coordinate (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] h height of point above the ellipsoid (meters).
* @param[out] M if the length of the vector is 9, fill with the rotation
* matrix in row-major order.
*
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
* express \e v as \e column vectors in one of two ways
* - in east, north, up coordinates (where the components are relative to a
* local coordinate system at (\e lat, \e lon, \e h)); call this
* representation \e v1.
* - in \e x, \e y, \e z coordinates (where the components are relative to
* the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
* representation \e v0.
* .
* Then we have \e v1 = <i>M</i><sup>T</sup> &sdot; \e v0, where
* <i>M</i><sup>T</sup> is the transpose of \e M.
**********************************************************************/
void Reverse(real x, real y, real z, real& lat, real& lon, real& h,
std::vector<real>& M)
const {
if (M.end() == M.begin() + dim2_) {
real t[dim2_];
IntReverse(x, y, z, lat, lon, h, t);
std::copy(t, t + dim2_, M.begin());
} else
IntReverse(x, y, z, lat, lon, h, NULL);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return latitude of the origin (degrees).
**********************************************************************/
Math::real LatitudeOrigin() const { return _lat0; }
/**
* @return longitude of the origin (degrees).
**********************************************************************/
Math::real LongitudeOrigin() const { return _lon0; }
/**
* @return height of the origin (meters).
**********************************************************************/
Math::real HeightOrigin() const { return _h0; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value of \e a inherited from the Geocentric object used in the
* constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geocentric object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_LOCALCARTESIAN_HPP

361
external/include/GeographicLib/MGRS.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,361 @@
/**
* \file MGRS.hpp
* \brief Header for GeographicLib::MGRS class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_MGRS_HPP)
#define GEOGRAPHICLIB_MGRS_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/UTMUPS.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs string
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
/**
* \brief Convert between UTM/UPS and %MGRS
*
* MGRS is defined in Chapter 3 of
* - J. W. Hager, L. L. Fry, S. S. Jacks, D. R. Hill,
* <a href="https://web.archive.org/web/20161214054445/http://earth-info.nga.mil/GandG/publications/tm8358.1/pdf/TM8358_1.pdf">
* Datums, Ellipsoids, Grids, and Grid Reference Systems</a>,
* Defense Mapping Agency, Technical Manual TM8358.1 (1990).
* .
* This document has been updated by the two NGA documents
* - <a href="https://earth-info.nga.mil/php/download.php?file=coord-grids">
* Universal Grids and Grid Reference Systems</a>,
* NGA.STND.0037 (2014).
* - <a href="https://earth-info.nga.mil/php/download.php?file=coord-utmups">
* The Universal Grids and the Transverse Mercator and Polar Stereographic
* Map Projections</a>, NGA.SIG.0012 (2014).
*
* This implementation has the following properties:
* - The conversions are closed, i.e., output from Forward is legal input for
* Reverse and vice versa. Conversion in both directions preserve the
* UTM/UPS selection and the UTM zone.
* - Forward followed by Reverse and vice versa is approximately the
* identity. (This is affected in predictable ways by errors in
* determining the latitude band and by loss of precision in the MGRS
* coordinates.)
* - The trailing digits produced by Forward are consistent as the precision
* is varied. Specifically, the digits are obtained by operating on the
* easting with &lfloor;10<sup>6</sup> <i>x</i>&rfloor; and extracting the
* required digits from the resulting number (and similarly for the
* northing).
* - All MGRS coordinates truncate to legal 100 km blocks. All MGRS
* coordinates with a legal 100 km block prefix are legal (even though the
* latitude band letter may now belong to a neighboring band).
* - The range of UTM/UPS coordinates allowed for conversion to MGRS
* coordinates is the maximum consistent with staying within the letter
* ranges of the MGRS scheme.
* - All the transformations are implemented as static methods in the MGRS
* class.
*
* The <a href="http://www.nga.mil">NGA</a> software package
* <a href="https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_geotrans">geotrans</a>
* also provides conversions to and from MGRS. Version 3.0 (and earlier)
* suffers from some drawbacks:
* - Inconsistent rules are used to determine the whether a particular MGRS
* coordinate is legal. A more systematic approach is taken here.
* - The underlying projections are not very accurately implemented.
*
* Example of use:
* \include example-MGRS.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT MGRS {
private:
typedef Math::real real;
static const char* const hemispheres_;
static const char* const utmcols_[3];
static const char* const utmrow_;
static const char* const upscols_[4];
static const char* const upsrows_[2];
static const char* const latband_;
static const char* const upsband_;
static const char* const digits_;
static const int mineasting_[4];
static const int maxeasting_[4];
static const int minnorthing_[4];
static const int maxnorthing_[4];
enum {
base_ = 10,
// Top-level tiles are 10^5 m = 100 km on a side
tilelevel_ = 5,
// Period of UTM row letters
utmrowperiod_ = 20,
// Row letters are shifted by 5 for even zones
utmevenrowshift_ = 5,
// Maximum precision is um
maxprec_ = 5 + 6,
// For generating digits at maxprec
mult_ = 1000000,
};
static void CheckCoords(bool utmp, bool& northp, real& x, real& y);
static int UTMRow(int iband, int icol, int irow);
friend class UTMUPS; // UTMUPS::StandardZone calls LatitudeBand
// Return latitude band number [-10, 10) for the given latitude (degrees).
// The bands are reckoned in include their southern edges.
static int LatitudeBand(real lat) {
using std::floor;
int ilat = int(floor(lat));
return (std::max)(-10, (std::min)(9, (ilat + 80)/8 - 10));
}
// Return approximate latitude band number [-10, 10) for the given northing
// (meters). With this rule, each 100km tile would have a unique band
// letter corresponding to the latitude at the center of the tile. This
// function isn't currently used.
static int ApproxLatitudeBand(real y) {
// northing at tile center in units of tile = 100km
using std::floor; using std::abs;
real ya = floor( (std::min)(real(88), abs(y/tile_)) ) +
real(0.5);
// convert to lat (mult by 90/100) and then to band (divide by 8)
// the +1 fine tunes the boundary between bands 3 and 4
int b = int(floor( ((ya * 9 + 1) / 10) / 8 ));
// For the northern hemisphere we have
// band rows num
// N 0 0:8 9
// P 1 9:17 9
// Q 2 18:26 9
// R 3 27:34 8
// S 4 35:43 9
// T 5 44:52 9
// U 6 53:61 9
// V 7 62:70 9
// W 8 71:79 9
// X 9 80:94 15
return y >= 0 ? b : -(b + 1);
}
// UTMUPS access these enums
enum {
tile_ = 100000, // Size MGRS blocks
minutmcol_ = 1,
maxutmcol_ = 9,
minutmSrow_ = 10,
maxutmSrow_ = 100, // Also used for UTM S false northing
minutmNrow_ = 0, // Also used for UTM N false northing
maxutmNrow_ = 95,
minupsSind_ = 8, // These 4 ind's apply to easting and northing
maxupsSind_ = 32,
minupsNind_ = 13,
maxupsNind_ = 27,
upseasting_ = 20, // Also used for UPS false northing
utmeasting_ = 5, // UTM false easting
// Difference between S hemisphere northing and N hemisphere northing
utmNshift_ = (maxutmSrow_ - minutmNrow_) * tile_
};
MGRS(); // Disable constructor
public:
/**
* Convert UTM or UPS coordinate to an MGRS coordinate.
*
* @param[in] zone UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[in] prec precision relative to 100 km.
* @param[out] mgrs MGRS string.
* @exception GeographicErr if \e zone, \e x, or \e y is outside its
* allowed range.
* @exception GeographicErr if the memory for the MGRS string can't be
* allocated.
*
* \e prec specifies the precision of the MGRS string as follows:
* - \e prec = &minus;1 (min), only the grid zone is returned
* - \e prec = 0, 100 km
* - \e prec = 1, 10 km
* - \e prec = 2, 1 km
* - \e prec = 3, 100 m
* - \e prec = 4, 10 m
* - \e prec = 5, 1 m
* - \e prec = 6, 0.1 m
* - &hellip;
* - \e prec = 11 (max), 1 &mu;m
*
* UTM eastings are allowed to be in the range [100 km, 900 km], northings
* are allowed to be in in [0 km, 9500 km] for the northern hemisphere and
* in [1000 km, 10000 km] for the southern hemisphere. (However UTM
* northings can be continued across the equator. So the actual limits on
* the northings are [&minus;9000 km, 9500 km] for the "northern"
* hemisphere and [1000 km, 19500 km] for the "southern" hemisphere.)
*
* UPS eastings/northings are allowed to be in the range [1300 km, 2700 km]
* in the northern hemisphere and in [800 km, 3200 km] in the southern
* hemisphere.
*
* The ranges are 100 km more restrictive than for the conversion between
* geographic coordinates and UTM and UPS given by UTMUPS. These
* restrictions are dictated by the allowed letters in MGRS coordinates.
* The choice of 9500 km for the maximum northing for northern hemisphere
* and of 1000 km as the minimum northing for southern hemisphere provide
* at least 0.5 degree extension into standard UPS zones. The upper ends
* of the ranges for the UPS coordinates is dictated by requiring symmetry
* about the meridians 0E and 90E.
*
* All allowed UTM and UPS coordinates may now be converted to legal MGRS
* coordinates with the proviso that eastings and northings on the upper
* boundaries are silently reduced by about 4 nm (4 nanometers) to place
* them \e within the allowed range. (This includes reducing a southern
* hemisphere northing of 10000 km by 4 nm so that it is placed in latitude
* band M.) The UTM or UPS coordinates are truncated to requested
* precision to determine the MGRS coordinate. Thus in UTM zone 38n, the
* square area with easting in [444 km, 445 km) and northing in [3688 km,
* 3689 km) maps to MGRS coordinate 38SMB4488 (at \e prec = 2, 1 km),
* Khulani Sq., Baghdad.
*
* The UTM/UPS selection and the UTM zone is preserved in the conversion to
* MGRS coordinate. Thus for \e zone > 0, the MGRS coordinate begins with
* the zone number followed by one of [C--M] for the southern
* hemisphere and [N--X] for the northern hemisphere. For \e zone =
* 0, the MGRS coordinates begins with one of [AB] for the southern
* hemisphere and [XY] for the northern hemisphere.
*
* The conversion to the MGRS is exact for prec in [0, 5] except that a
* neighboring latitude band letter may be given if the point is within 5nm
* of a band boundary. For prec in [6, 11], the conversion is accurate to
* roundoff.
*
* If \e prec = &minus;1, then the "grid zone designation", e.g., 18T, is
* returned. This consists of the UTM zone number (absent for UPS) and the
* first letter of the MGRS string which labels the latitude band for UTM
* and the hemisphere for UPS.
*
* If \e x or \e y is NaN or if \e zone is UTMUPS::INVALID, the returned
* MGRS string is "INVALID".
*
* Return the result via a reference argument to avoid the overhead of
* allocating a potentially large number of small strings. If an error is
* thrown, then \e mgrs is unchanged.
**********************************************************************/
static void Forward(int zone, bool northp, real x, real y,
int prec, std::string& mgrs);
/**
* Convert UTM or UPS coordinate to an MGRS coordinate when the latitude is
* known.
*
* @param[in] zone UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[in] lat latitude (degrees).
* @param[in] prec precision relative to 100 km.
* @param[out] mgrs MGRS string.
* @exception GeographicErr if \e zone, \e x, or \e y is outside its
* allowed range.
* @exception GeographicErr if \e lat is inconsistent with the given UTM
* coordinates.
* @exception std::bad_alloc if the memory for \e mgrs can't be allocated.
*
* The latitude is ignored for \e zone = 0 (UPS); otherwise the latitude is
* used to determine the latitude band and this is checked for consistency
* using the same tests as Reverse.
**********************************************************************/
static void Forward(int zone, bool northp, real x, real y, real lat,
int prec, std::string& mgrs);
/**
* Convert a MGRS coordinate to UTM or UPS coordinates.
*
* @param[in] mgrs MGRS string.
* @param[out] zone UTM zone (zero means UPS).
* @param[out] northp hemisphere (true means north, false means south).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] prec precision relative to 100 km.
* @param[in] centerp if true (default), return center of the MGRS square,
* else return SW (lower left) corner.
* @exception GeographicErr if \e mgrs is illegal.
*
* All conversions from MGRS to UTM/UPS are permitted provided the MGRS
* coordinate is a possible result of a conversion in the other direction.
* (The leading 0 may be dropped from an input MGRS coordinate for UTM
* zones 1--9.) In addition, MGRS coordinates with a neighboring
* latitude band letter are permitted provided that some portion of the
* 100 km block is within the given latitude band. Thus
* - 38VLS and 38WLS are allowed (latitude 64N intersects the square
* 38[VW]LS); but 38VMS is not permitted (all of 38WMS is north of 64N)
* - 38MPE and 38NPF are permitted (they straddle the equator); but 38NPE
* and 38MPF are not permitted (the equator does not intersect either
* block).
* - Similarly ZAB and YZB are permitted (they straddle the prime
* meridian); but YAB and ZZB are not (the prime meridian does not
* intersect either block).
*
* The UTM/UPS selection and the UTM zone is preserved in the conversion
* from MGRS coordinate. The conversion is exact for prec in [0, 5]. With
* \e centerp = true, the conversion from MGRS to geographic and back is
* stable. This is not assured if \e centerp = false.
*
* If a "grid zone designation" (for example, 18T or A) is given, then some
* suitable (but essentially arbitrary) point within that grid zone is
* returned. The main utility of the conversion is to allow \e zone and \e
* northp to be determined. In this case, the \e centerp parameter is
* ignored and \e prec is set to &minus;1.
*
* If the first 3 characters of \e mgrs are "INV", then \e x and \e y are
* set to NaN, \e zone is set to UTMUPS::INVALID, and \e prec is set to
* &minus;2.
*
* If an exception is thrown, then the arguments are unchanged.
**********************************************************************/
static void Reverse(const std::string& mgrs,
int& zone, bool& northp, real& x, real& y,
int& prec, bool centerp = true);
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
*
* (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.)
**********************************************************************/
static Math::real EquatorialRadius() { return UTMUPS::EquatorialRadius(); }
/**
* @return \e f the flattening of the WGS84 ellipsoid.
*
* (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.)
**********************************************************************/
static Math::real Flattening() { return UTMUPS::Flattening(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
static Math::real MajorRadius() { return EquatorialRadius(); }
///@}
/**
* Perform some checks on the UTMUPS coordinates on this ellipsoid. Throw
* an error if any of the assumptions made in the MGRS class is not true.
* This check needs to be carried out if the ellipsoid parameters (or the
* UTM/UPS scales) are ever changed.
**********************************************************************/
static void Check();
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_MGRS_HPP

204
external/include/GeographicLib/MagneticCircle.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,204 @@
/**
* \file MagneticCircle.hpp
* \brief Header for GeographicLib::MagneticCircle class
*
* Copyright (c) Charles Karney (2011-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_MAGNETICCIRCLE_HPP)
#define GEOGRAPHICLIB_MAGNETICCIRCLE_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/CircularEngine.hpp>
namespace GeographicLib {
/**
* \brief Geomagnetic field on a circle of latitude
*
* Evaluate the earth's magnetic field on a circle of constant height and
* latitude. This uses a CircularEngine to pre-evaluate the inner sum of the
* spherical harmonic sum, allowing the values of the field at several
* different longitudes to be evaluated rapidly.
*
* Use MagneticModel::Circle to create a MagneticCircle object. (The
* constructor for this class is private.)
*
* Example of use:
* \include example-MagneticCircle.cpp
*
* <a href="MagneticField.1.html">MagneticField</a> is a command-line utility
* providing access to the functionality of MagneticModel and MagneticCircle.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT MagneticCircle {
private:
typedef Math::real real;
real _a, _f, _lat, _h, _t, _cphi, _sphi, _t1, _dt0;
bool _interpolate, _constterm;
CircularEngine _circ0, _circ1, _circ2;
MagneticCircle(real a, real f, real lat, real h, real t,
real cphi, real sphi, real t1, real dt0,
bool interpolate,
const CircularEngine& circ0, const CircularEngine& circ1)
: _a(a)
, _f(f)
, _lat(Math::LatFix(lat))
, _h(h)
, _t(t)
, _cphi(cphi)
, _sphi(sphi)
, _t1(t1)
, _dt0(dt0)
, _interpolate(interpolate)
, _constterm(false)
, _circ0(circ0)
, _circ1(circ1)
{}
MagneticCircle(real a, real f, real lat, real h, real t,
real cphi, real sphi, real t1, real dt0,
bool interpolate,
const CircularEngine& circ0, const CircularEngine& circ1,
const CircularEngine& circ2)
: _a(a)
, _f(f)
, _lat(lat)
, _h(h)
, _t(t)
, _cphi(cphi)
, _sphi(sphi)
, _t1(t1)
, _dt0(dt0)
, _interpolate(interpolate)
, _constterm(true)
, _circ0(circ0)
, _circ1(circ1)
, _circ2(circ2)
{}
void Field(real lon, bool diffp,
real& Bx, real& By, real& Bz,
real& Bxt, real& Byt, real& Bzt) const;
void FieldGeocentric(real slam, real clam,
real& BX, real& BY, real& BZ,
real& BXt, real& BYt, real& BZt) const;
friend class MagneticModel; // MagneticModel calls the private constructor
public:
/**
* A default constructor for the normal gravity. This sets up an
* uninitialized object which can be later replaced by the
* MagneticModel::Circle.
**********************************************************************/
MagneticCircle() : _a(-1) {}
/** \name Compute the magnetic field
**********************************************************************/
///@{
/**
* Evaluate the components of the geomagnetic field at a particular
* longitude.
*
* @param[in] lon longitude of the point (degrees).
* @param[out] Bx the easterly component of the magnetic field (nanotesla).
* @param[out] By the northerly component of the magnetic field
* (nanotesla).
* @param[out] Bz the vertical (up) component of the magnetic field
* (nanotesla).
**********************************************************************/
void operator()(real lon, real& Bx, real& By, real& Bz) const {
real dummy;
Field(lon, false, Bx, By, Bz, dummy, dummy, dummy);
}
/**
* Evaluate the components of the geomagnetic field and their time
* derivatives at a particular longitude.
*
* @param[in] lon longitude of the point (degrees).
* @param[out] Bx the easterly component of the magnetic field (nanotesla).
* @param[out] By the northerly component of the magnetic field
* (nanotesla).
* @param[out] Bz the vertical (up) component of the magnetic field
* (nanotesla).
* @param[out] Bxt the rate of change of \e Bx (nT/yr).
* @param[out] Byt the rate of change of \e By (nT/yr).
* @param[out] Bzt the rate of change of \e Bz (nT/yr).
**********************************************************************/
void operator()(real lon, real& Bx, real& By, real& Bz,
real& Bxt, real& Byt, real& Bzt) const {
Field(lon, true, Bx, By, Bz, Bxt, Byt, Bzt);
}
/**
* Evaluate the components of the geomagnetic field and their time
* derivatives at a particular longitude.
*
* @param[in] lon longitude of the point (degrees).
* @param[out] BX the \e X component of the magnetic field (nT).
* @param[out] BY the \e Y component of the magnetic field (nT).
* @param[out] BZ the \e Z component of the magnetic field (nT).
* @param[out] BXt the rate of change of \e BX (nT/yr).
* @param[out] BYt the rate of change of \e BY (nT/yr).
* @param[out] BZt the rate of change of \e BZ (nT/yr).
**********************************************************************/
void FieldGeocentric(real lon, real& BX, real& BY, real& BZ,
real& BXt, real& BYt, real& BZt) const;
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _a > 0; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the MagneticModel object used in the
* constructor.
**********************************************************************/
Math::real EquatorialRadius() const
{ return Init() ? _a : Math::NaN(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the MagneticModel object used in the constructor.
**********************************************************************/
Math::real Flattening() const
{ return Init() ? _f : Math::NaN(); }
/**
* @return the latitude of the circle (degrees).
**********************************************************************/
Math::real Latitude() const
{ return Init() ? _lat : Math::NaN(); }
/**
* @return the height of the circle (meters).
**********************************************************************/
Math::real Height() const
{ return Init() ? _h : Math::NaN(); }
/**
* @return the time (fractional years).
**********************************************************************/
Math::real Time() const
{ return Init() ? _t : Math::NaN(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_MAGNETICCIRCLE_HPP

406
external/include/GeographicLib/MagneticModel.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,406 @@
/**
* \file MagneticModel.hpp
* \brief Header for GeographicLib::MagneticModel class
*
* Copyright (c) Charles Karney (2011-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_MAGNETICMODEL_HPP)
#define GEOGRAPHICLIB_MAGNETICMODEL_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/Geocentric.hpp>
#include <GeographicLib/SphericalHarmonic.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
class MagneticCircle;
/**
* \brief Model of the earth's magnetic field
*
* Evaluate the earth's magnetic field according to a model. At present only
* internal magnetic fields are handled. These are due to the earth's code
* and crust; these vary slowly (over many years). Excluded are the effects
* of currents in the ionosphere and magnetosphere which have daily and
* annual variations.
*
* See \ref magnetic for details of how to install the magnetic models and
* the data format.
*
* See
* - General information:
* - http://geomag.org/models/index.html
* - WMM2010:
* - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml
* - https://ngdc.noaa.gov/geomag/WMM/data/WMM2010/WMM2010COF.zip
* - WMM2015 (deprecated):
* - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml
* - https://ngdc.noaa.gov/geomag/WMM/data/WMM2015/WMM2015COF.zip
* - WMM2015V2:
* - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml
* - https://ngdc.noaa.gov/geomag/WMM/data/WMM2015/WMM2015v2COF.zip
* - WMM2020:
* - https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml
* - https://ngdc.noaa.gov/geomag/WMM/data/WMM2020/WMM2020COF.zip
* - IGRF11:
* - https://ngdc.noaa.gov/IAGA/vmod/igrf.html
* - https://ngdc.noaa.gov/IAGA/vmod/igrf11coeffs.txt
* - https://ngdc.noaa.gov/IAGA/vmod/geomag70_linux.tar.gz
* - EMM2010:
* - https://ngdc.noaa.gov/geomag/EMM/index.html
* - https://ngdc.noaa.gov/geomag/EMM/data/geomag/EMM2010_Sph_Windows_Linux.zip
* - EMM2015:
* - https://ngdc.noaa.gov/geomag/EMM/index.html
* - https://www.ngdc.noaa.gov/geomag/EMM/data/geomag/EMM2015_Sph_Linux.zip
* - EMM2017:
* - https://ngdc.noaa.gov/geomag/EMM/index.html
* - https://www.ngdc.noaa.gov/geomag/EMM/data/geomag/EMM2017_Sph_Linux.zip
*
* Example of use:
* \include example-MagneticModel.cpp
*
* <a href="MagneticField.1.html">MagneticField</a> is a command-line utility
* providing access to the functionality of MagneticModel and MagneticCircle.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT MagneticModel {
private:
typedef Math::real real;
static const int idlength_ = 8;
std::string _name, _dir, _description, _date, _filename, _id;
real _t0, _dt0, _tmin, _tmax, _a, _hmin, _hmax;
int _Nmodels, _Nconstants, _nmx, _mmx;
SphericalHarmonic::normalization _norm;
Geocentric _earth;
std::vector< std::vector<real> > _G;
std::vector< std::vector<real> > _H;
std::vector<SphericalHarmonic> _harm;
void Field(real t, real lat, real lon, real h, bool diffp,
real& Bx, real& By, real& Bz,
real& Bxt, real& Byt, real& Bzt) const;
void ReadMetadata(const std::string& name);
// copy constructor not allowed
MagneticModel(const MagneticModel&) = delete;
// nor copy assignment
MagneticModel& operator=(const MagneticModel&) = delete;
public:
/** \name Setting up the magnetic model
**********************************************************************/
///@{
/**
* Construct a magnetic model.
*
* @param[in] name the name of the model.
* @param[in] path (optional) directory for data file.
* @param[in] earth (optional) Geocentric object for converting
* coordinates; default Geocentric::WGS84().
* @param[in] Nmax (optional) if non-negative, truncate the degree of the
* model this value.
* @param[in] Mmax (optional) if non-negative, truncate the order of the
* model this value.
* @exception GeographicErr if the data file cannot be found, is
* unreadable, or is corrupt, or if \e Mmax > \e Nmax.
* @exception std::bad_alloc if the memory necessary for storing the model
* can't be allocated.
*
* A filename is formed by appending ".wmm" (World Magnetic Model) to the
* name. If \e path is specified (and is non-empty), then the file is
* loaded from directory, \e path. Otherwise the path is given by the
* DefaultMagneticPath().
*
* This file contains the metadata which specifies the properties of the
* model. The coefficients for the spherical harmonic sums are obtained
* from a file obtained by appending ".cof" to metadata file (so the
* filename ends in ".wwm.cof").
*
* The model is not tied to a particular ellipsoidal model of the earth.
* The final earth argument to the constructor specifies an ellipsoid to
* allow geodetic coordinates to the transformed into the spherical
* coordinates used in the spherical harmonic sum.
*
* If \e Nmax &ge; 0 and \e Mmax < 0, then \e Mmax is set to \e Nmax.
* After the model is loaded, the maximum degree and order of the model can
* be found by the Degree() and Order() methods.
**********************************************************************/
explicit MagneticModel(const std::string& name,
const std::string& path = "",
const Geocentric& earth = Geocentric::WGS84(),
int Nmax = -1, int Mmax = -1);
///@}
/** \name Compute the magnetic field
**********************************************************************/
///@{
/**
* Evaluate the components of the geomagnetic field.
*
* @param[in] t the time (years).
* @param[in] lat latitude of the point (degrees).
* @param[in] lon longitude of the point (degrees).
* @param[in] h the height of the point above the ellipsoid (meters).
* @param[out] Bx the easterly component of the magnetic field (nanotesla).
* @param[out] By the northerly component of the magnetic field
* (nanotesla).
* @param[out] Bz the vertical (up) component of the magnetic field
* (nanotesla).
**********************************************************************/
void operator()(real t, real lat, real lon, real h,
real& Bx, real& By, real& Bz) const {
real dummy;
Field(t, lat, lon, h, false, Bx, By, Bz, dummy, dummy, dummy);
}
/**
* Evaluate the components of the geomagnetic field and their time
* derivatives
*
* @param[in] t the time (years).
* @param[in] lat latitude of the point (degrees).
* @param[in] lon longitude of the point (degrees).
* @param[in] h the height of the point above the ellipsoid (meters).
* @param[out] Bx the easterly component of the magnetic field (nanotesla).
* @param[out] By the northerly component of the magnetic field
* (nanotesla).
* @param[out] Bz the vertical (up) component of the magnetic field
* (nanotesla).
* @param[out] Bxt the rate of change of \e Bx (nT/yr).
* @param[out] Byt the rate of change of \e By (nT/yr).
* @param[out] Bzt the rate of change of \e Bz (nT/yr).
**********************************************************************/
void operator()(real t, real lat, real lon, real h,
real& Bx, real& By, real& Bz,
real& Bxt, real& Byt, real& Bzt) const {
Field(t, lat, lon, h, true, Bx, By, Bz, Bxt, Byt, Bzt);
}
/**
* Create a MagneticCircle object to allow the geomagnetic field at many
* points with constant \e lat, \e h, and \e t and varying \e lon to be
* computed efficiently.
*
* @param[in] t the time (years).
* @param[in] lat latitude of the point (degrees).
* @param[in] h the height of the point above the ellipsoid (meters).
* @exception std::bad_alloc if the memory necessary for creating a
* MagneticCircle can't be allocated.
* @return a MagneticCircle object whose MagneticCircle::operator()(real
* lon) member function computes the field at particular values of \e
* lon.
*
* If the field at several points on a circle of latitude need to be
* calculated then creating a MagneticCircle and using its member functions
* will be substantially faster, especially for high-degree models.
**********************************************************************/
MagneticCircle Circle(real t, real lat, real h) const;
/**
* Compute the magnetic field in geocentric coordinate.
*
* @param[in] t the time (years).
* @param[in] X geocentric coordinate (meters).
* @param[in] Y geocentric coordinate (meters).
* @param[in] Z geocentric coordinate (meters).
* @param[out] BX the \e X component of the magnetic field (nT).
* @param[out] BY the \e Y component of the magnetic field (nT).
* @param[out] BZ the \e Z component of the magnetic field (nT).
* @param[out] BXt the rate of change of \e BX (nT/yr).
* @param[out] BYt the rate of change of \e BY (nT/yr).
* @param[out] BZt the rate of change of \e BZ (nT/yr).
**********************************************************************/
void FieldGeocentric(real t, real X, real Y, real Z,
real& BX, real& BY, real& BZ,
real& BXt, real& BYt, real& BZt) const;
/**
* Compute various quantities dependent on the magnetic field.
*
* @param[in] Bx the \e x (easterly) component of the magnetic field (nT).
* @param[in] By the \e y (northerly) component of the magnetic field (nT).
* @param[in] Bz the \e z (vertical, up positive) component of the magnetic
* field (nT).
* @param[out] H the horizontal magnetic field (nT).
* @param[out] F the total magnetic field (nT).
* @param[out] D the declination of the field (degrees east of north).
* @param[out] I the inclination of the field (degrees down from
* horizontal).
**********************************************************************/
static void FieldComponents(real Bx, real By, real Bz,
real& H, real& F, real& D, real& I) {
real Ht, Ft, Dt, It;
FieldComponents(Bx, By, Bz, real(0), real(1), real(0),
H, F, D, I, Ht, Ft, Dt, It);
}
/**
* Compute various quantities dependent on the magnetic field and its rate
* of change.
*
* @param[in] Bx the \e x (easterly) component of the magnetic field (nT).
* @param[in] By the \e y (northerly) component of the magnetic field (nT).
* @param[in] Bz the \e z (vertical, up positive) component of the magnetic
* field (nT).
* @param[in] Bxt the rate of change of \e Bx (nT/yr).
* @param[in] Byt the rate of change of \e By (nT/yr).
* @param[in] Bzt the rate of change of \e Bz (nT/yr).
* @param[out] H the horizontal magnetic field (nT).
* @param[out] F the total magnetic field (nT).
* @param[out] D the declination of the field (degrees east of north).
* @param[out] I the inclination of the field (degrees down from
* horizontal).
* @param[out] Ht the rate of change of \e H (nT/yr).
* @param[out] Ft the rate of change of \e F (nT/yr).
* @param[out] Dt the rate of change of \e D (degrees/yr).
* @param[out] It the rate of change of \e I (degrees/yr).
**********************************************************************/
static void FieldComponents(real Bx, real By, real Bz,
real Bxt, real Byt, real Bzt,
real& H, real& F, real& D, real& I,
real& Ht, real& Ft, real& Dt, real& It);
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return the description of the magnetic model, if available, from the
* Description file in the data file; if absent, return "NONE".
**********************************************************************/
const std::string& Description() const { return _description; }
/**
* @return date of the model, if available, from the ReleaseDate field in
* the data file; if absent, return "UNKNOWN".
**********************************************************************/
const std::string& DateTime() const { return _date; }
/**
* @return full file name used to load the magnetic model.
**********************************************************************/
const std::string& MagneticFile() const { return _filename; }
/**
* @return "name" used to load the magnetic model (from the first argument
* of the constructor, but this may be overridden by the model file).
**********************************************************************/
const std::string& MagneticModelName() const { return _name; }
/**
* @return directory used to load the magnetic model.
**********************************************************************/
const std::string& MagneticModelDirectory() const { return _dir; }
/**
* @return the minimum height above the ellipsoid (in meters) for which
* this MagneticModel should be used.
*
* Because the model will typically provide useful results
* slightly outside the range of allowed heights, no check of \e t
* argument is made by MagneticModel::operator()() or
* MagneticModel::Circle.
**********************************************************************/
Math::real MinHeight() const { return _hmin; }
/**
* @return the maximum height above the ellipsoid (in meters) for which
* this MagneticModel should be used.
*
* Because the model will typically provide useful results
* slightly outside the range of allowed heights, no check of \e t
* argument is made by MagneticModel::operator()() or
* MagneticModel::Circle.
**********************************************************************/
Math::real MaxHeight() const { return _hmax; }
/**
* @return the minimum time (in years) for which this MagneticModel should
* be used.
*
* Because the model will typically provide useful results
* slightly outside the range of allowed times, no check of \e t
* argument is made by MagneticModel::operator()() or
* MagneticModel::Circle.
**********************************************************************/
Math::real MinTime() const { return _tmin; }
/**
* @return the maximum time (in years) for which this MagneticModel should
* be used.
*
* Because the model will typically provide useful results
* slightly outside the range of allowed times, no check of \e t
* argument is made by MagneticModel::operator()() or
* MagneticModel::Circle.
**********************************************************************/
Math::real MaxTime() const { return _tmax; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value of \e a inherited from the Geocentric object used in the
* constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geocentric object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* @return \e Nmax the maximum degree of the components of the model.
**********************************************************************/
int Degree() const { return _nmx; }
/**
* @return \e Mmax the maximum order of the components of the model.
**********************************************************************/
int Order() const { return _mmx; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* @return the default path for magnetic model data files.
*
* This is the value of the environment variable
* GEOGRAPHICLIB_MAGNETIC_PATH, if set; otherwise, it is
* $GEOGRAPHICLIB_DATA/magnetic if the environment variable
* GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default
* (/usr/local/share/GeographicLib/magnetic on non-Windows systems and
* C:/ProgramData/GeographicLib/magnetic on Windows systems).
**********************************************************************/
static std::string DefaultMagneticPath();
/**
* @return the default name for the magnetic model.
*
* This is the value of the environment variable
* GEOGRAPHICLIB_MAGNETIC_NAME, if set; otherwise, it is "wmm2020". The
* MagneticModel class does not use this function; it is just provided as a
* convenience for a calling program when constructing a MagneticModel
* object.
**********************************************************************/
static std::string DefaultMagneticName();
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_MAGNETICMODEL_HPP

684
external/include/GeographicLib/Math.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,684 @@
/**
* \file Math.hpp
* \brief Header for GeographicLib::Math class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
// Constants.hpp includes Math.hpp. Place this include outside Math.hpp's
// include guard to enforce this ordering.
#include <GeographicLib/Constants.hpp>
#if !defined(GEOGRAPHICLIB_MATH_HPP)
#define GEOGRAPHICLIB_MATH_HPP 1
#if !defined(GEOGRAPHICLIB_WORDS_BIGENDIAN)
# define GEOGRAPHICLIB_WORDS_BIGENDIAN 0
#endif
#if !defined(GEOGRAPHICLIB_HAVE_LONG_DOUBLE)
# define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0
#endif
#if !defined(GEOGRAPHICLIB_PRECISION)
/**
* The precision of floating point numbers used in %GeographicLib. 1 means
* float (single precision); 2 (the default) means double; 3 means long double;
* 4 is reserved for quadruple precision. Nearly all the testing has been
* carried out with doubles and that's the recommended configuration. In order
* for long double to be used, GEOGRAPHICLIB_HAVE_LONG_DOUBLE needs to be
* defined. Note that with Microsoft Visual Studio, long double is the same as
* double.
**********************************************************************/
# define GEOGRAPHICLIB_PRECISION 2
#endif
#include <cmath>
#include <algorithm>
#include <limits>
#if GEOGRAPHICLIB_PRECISION == 4
#include <boost/version.hpp>
#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions.hpp>
#elif GEOGRAPHICLIB_PRECISION == 5
#include <mpreal.h>
#endif
#if GEOGRAPHICLIB_PRECISION > 3
// volatile keyword makes no sense for multiprec types
#define GEOGRAPHICLIB_VOLATILE
// Signal a convergence failure with multiprec types by throwing an exception
// at loop exit.
#define GEOGRAPHICLIB_PANIC \
(throw GeographicLib::GeographicErr("Convergence failure"), false)
#else
#define GEOGRAPHICLIB_VOLATILE volatile
// Ignore convergence failures with standard floating points types by allowing
// loop to exit cleanly.
#define GEOGRAPHICLIB_PANIC false
#endif
namespace GeographicLib {
/**
* \brief Mathematical functions needed by %GeographicLib
*
* Define mathematical functions in order to localize system dependencies and
* to provide generic versions of the functions. In addition define a real
* type to be used by %GeographicLib.
*
* Example of use:
* \include example-Math.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Math {
private:
void dummy(); // Static check for GEOGRAPHICLIB_PRECISION
Math(); // Disable constructor
public:
#if GEOGRAPHICLIB_HAVE_LONG_DOUBLE
/**
* The extended precision type for real numbers, used for some testing.
* This is long double on computers with this type; otherwise it is double.
**********************************************************************/
typedef long double extended;
#else
typedef double extended;
#endif
#if GEOGRAPHICLIB_PRECISION == 2
/**
* The real type for %GeographicLib. Nearly all the testing has been done
* with \e real = double. However, the algorithms should also work with
* float and long double (where available). (<b>CAUTION</b>: reasonable
* accuracy typically cannot be obtained using floats.)
**********************************************************************/
typedef double real;
#elif GEOGRAPHICLIB_PRECISION == 1
typedef float real;
#elif GEOGRAPHICLIB_PRECISION == 3
typedef extended real;
#elif GEOGRAPHICLIB_PRECISION == 4
typedef boost::multiprecision::float128 real;
#elif GEOGRAPHICLIB_PRECISION == 5
typedef mpfr::mpreal real;
#else
typedef double real;
#endif
/**
* @return the number of bits of precision in a real number.
**********************************************************************/
static int digits();
/**
* Set the binary precision of a real number.
*
* @param[in] ndigits the number of bits of precision.
* @return the resulting number of bits of precision.
*
* This only has an effect when GEOGRAPHICLIB_PRECISION = 5. See also
* Utility::set_digits for caveats about when this routine should be
* called.
**********************************************************************/
static int set_digits(int ndigits);
/**
* @return the number of decimal digits of precision in a real number.
**********************************************************************/
static int digits10();
/**
* Number of additional decimal digits of precision for real relative to
* double (0 for float).
**********************************************************************/
static int extra_digits();
/**
* true if the machine is big-endian.
**********************************************************************/
static const bool bigendian = GEOGRAPHICLIB_WORDS_BIGENDIAN;
/**
* @tparam T the type of the returned value.
* @return &pi;.
**********************************************************************/
template<typename T = real> static T pi() {
using std::atan2;
static const T pi = atan2(T(0), T(-1));
return pi;
}
/**
* @tparam T the type of the returned value.
* @return the number of radians in a degree.
**********************************************************************/
template<typename T = real> static T degree() {
static const T degree = pi<T>() / 180;
return degree;
}
/**
* Square a number.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return <i>x</i><sup>2</sup>.
**********************************************************************/
template<typename T> static T sq(T x)
{ return x * x; }
/**
* The hypotenuse function avoiding underflow and overflow.
*
* @tparam T the type of the arguments and the returned value.
* @param[in] x
* @param[in] y
* @return sqrt(<i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>).
*
* \deprecated Use std::hypot(x, y).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::hypot(x, y)")
static T hypot(T x, T y);
/**
* exp(\e x) &minus; 1 accurate near \e x = 0.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return exp(\e x) &minus; 1.
*
* \deprecated Use std::expm1(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::expm1(x)")
static T expm1(T x);
/**
* log(1 + \e x) accurate near \e x = 0.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return log(1 + \e x).
*
* \deprecated Use std::log1p(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::log1p(x)")
static T log1p(T x);
/**
* The inverse hyperbolic sine function.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return asinh(\e x).
*
* \deprecated Use std::asinh(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::asinh(x)")
static T asinh(T x);
/**
* The inverse hyperbolic tangent function.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return atanh(\e x).
*
* \deprecated Use std::atanh(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::atanh(x)")
static T atanh(T x);
/**
* Copy the sign.
*
* @tparam T the type of the argument.
* @param[in] x gives the magitude of the result.
* @param[in] y gives the sign of the result.
* @return value with the magnitude of \e x and with the sign of \e y.
*
* This routine correctly handles the case \e y = &minus;0, returning
* &minus|<i>x</i>|.
*
* \deprecated Use std::copysign(x, y).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::copysign(x, y)")
static T copysign(T x, T y);
/**
* The cube root function.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return the real cube root of \e x.
*
* \deprecated Use std::cbrt(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::cbrt(x)")
static T cbrt(T x);
/**
* The remainder function.
*
* @tparam T the type of the arguments and the returned value.
* @param[in] x
* @param[in] y
* @return the remainder of \e x/\e y in the range [&minus;\e y/2, \e y/2].
*
* \deprecated Use std::remainder(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::remainder(x)")
static T remainder(T x, T y);
/**
* The remquo function.
*
* @tparam T the type of the arguments and the returned value.
* @param[in] x
* @param[in] y
* @param[out] n the low 3 bits of the quotient
* @return the remainder of \e x/\e y in the range [&minus;\e y/2, \e y/2].
*
* \deprecated Use std::remquo(x, y, n).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::remquo(x, y, n)")
static T remquo(T x, T y, int* n);
/**
* The round function.
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return \e x round to the nearest integer (ties round away from 0).
*
* \deprecated Use std::round(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::round(x)")
static T round(T x);
/**
* The lround function.
*
* @tparam T the type of the argument.
* @param[in] x
* @return \e x round to the nearest integer as a long int (ties round away
* from 0).
*
* If the result does not fit in a long int, the return value is undefined.
*
* \deprecated Use std::lround(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::lround(x)")
static long lround(T x);
/**
* Fused multiply and add.
*
* @tparam T the type of the arguments and the returned value.
* @param[in] x
* @param[in] y
* @param[in] z
* @return <i>xy</i> + <i>z</i>, correctly rounded (on those platforms with
* support for the <code>fma</code> instruction).
*
* On platforms without the <code>fma</code> instruction, no attempt is
* made to improve on the result of a rounded multiplication followed by a
* rounded addition.
*
* \deprecated Use std::fma(x, y, z).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::fma(x, y, z)")
static T fma(T x, T y, T z);
/**
* Normalize a two-vector.
*
* @tparam T the type of the argument and the returned value.
* @param[in,out] x on output set to <i>x</i>/hypot(<i>x</i>, <i>y</i>).
* @param[in,out] y on output set to <i>y</i>/hypot(<i>x</i>, <i>y</i>).
**********************************************************************/
template<typename T> static void norm(T& x, T& y) {
#if defined(_MSC_VER) && defined(_M_IX86)
// hypot for Visual Studio (A=win32) fails monotonicity, e.g., with
// x = 0.6102683302836215
// y1 = 0.7906090004346522
// y2 = y1 + 1e-16
// the test
// hypot(x, y2) >= hypot(x, y1)
// fails. Reported 2021-03-14:
// https://developercommunity.visualstudio.com/t/1369259
// See also:
// https://bugs.python.org/issue43088
using std::sqrt; T h = sqrt(x * x + y * y);
#else
using std::hypot; T h = hypot(x, y);
#endif
x /= h; y /= h;
}
/**
* The error-free sum of two numbers.
*
* @tparam T the type of the argument and the returned value.
* @param[in] u
* @param[in] v
* @param[out] t the exact error given by (\e u + \e v) - \e s.
* @return \e s = round(\e u + \e v).
*
* See D. E. Knuth, TAOCP, Vol 2, 4.2.2, Theorem B. (Note that \e t can be
* the same as one of the first two arguments.)
**********************************************************************/
template<typename T> static T sum(T u, T v, T& t);
/**
* Evaluate a polynomial.
*
* @tparam T the type of the arguments and returned value.
* @param[in] N the order of the polynomial.
* @param[in] p the coefficient array (of size \e N + 1).
* @param[in] x the variable.
* @return the value of the polynomial.
*
* Evaluate <i>y</i> = &sum;<sub><i>n</i>=0..<i>N</i></sub>
* <i>p</i><sub><i>n</i></sub> <i>x</i><sup><i>N</i>&minus;<i>n</i></sup>.
* Return 0 if \e N &lt; 0. Return <i>p</i><sub>0</sub>, if \e N = 0 (even
* if \e x is infinite or a nan). The evaluation uses Horner's method.
**********************************************************************/
template<typename T> static T polyval(int N, const T p[], T x) {
// This used to employ Math::fma; but that's too slow and it seemed not to
// improve the accuracy noticeably. This might change when there's direct
// hardware support for fma.
T y = N < 0 ? 0 : *p++;
while (--N >= 0) y = y * x + *p++;
return y;
}
/**
* Normalize an angle.
*
* @tparam T the type of the argument and returned value.
* @param[in] x the angle in degrees.
* @return the angle reduced to the range (&minus;180&deg;, 180&deg;].
*
* The range of \e x is unrestricted.
**********************************************************************/
template<typename T> static T AngNormalize(T x) {
using std::remainder;
x = remainder(x, T(360)); return x != -180 ? x : 180;
}
/**
* Normalize a latitude.
*
* @tparam T the type of the argument and returned value.
* @param[in] x the angle in degrees.
* @return x if it is in the range [&minus;90&deg;, 90&deg;], otherwise
* return NaN.
**********************************************************************/
template<typename T> static T LatFix(T x)
{ using std::abs; return abs(x) > 90 ? NaN<T>() : x; }
/**
* The exact difference of two angles reduced to
* (&minus;180&deg;, 180&deg;].
*
* @tparam T the type of the arguments and returned value.
* @param[in] x the first angle in degrees.
* @param[in] y the second angle in degrees.
* @param[out] e the error term in degrees.
* @return \e d, the truncated value of \e y &minus; \e x.
*
* This computes \e z = \e y &minus; \e x exactly, reduced to
* (&minus;180&deg;, 180&deg;]; and then sets \e z = \e d + \e e where \e d
* is the nearest representable number to \e z and \e e is the truncation
* error. If \e d = &minus;180, then \e e &gt; 0; If \e d = 180, then \e e
* &le; 0.
**********************************************************************/
template<typename T> static T AngDiff(T x, T y, T& e) {
using std::remainder;
T t, d = AngNormalize(sum(remainder(-x, T(360)),
remainder( y, T(360)), t));
// Here y - x = d + t (mod 360), exactly, where d is in (-180,180] and
// abs(t) <= eps (eps = 2^-45 for doubles). The only case where the
// addition of t takes the result outside the range (-180,180] is d = 180
// and t > 0. The case, d = -180 + eps, t = -eps, can't happen, since
// sum would have returned the exact result in such a case (i.e., given t
// = 0).
return sum(d == 180 && t > 0 ? -180 : d, t, e);
}
/**
* Difference of two angles reduced to [&minus;180&deg;, 180&deg;]
*
* @tparam T the type of the arguments and returned value.
* @param[in] x the first angle in degrees.
* @param[in] y the second angle in degrees.
* @return \e y &minus; \e x, reduced to the range [&minus;180&deg;,
* 180&deg;].
*
* The result is equivalent to computing the difference exactly, reducing
* it to (&minus;180&deg;, 180&deg;] and rounding the result. Note that
* this prescription allows &minus;180&deg; to be returned (e.g., if \e x
* is tiny and negative and \e y = 180&deg;).
**********************************************************************/
template<typename T> static T AngDiff(T x, T y)
{ T e; return AngDiff(x, y, e); }
/**
* Coarsen a value close to zero.
*
* @tparam T the type of the argument and returned value.
* @param[in] x
* @return the coarsened value.
*
* The makes the smallest gap in \e x = 1/16 &minus; nextafter(1/16, 0) =
* 1/2<sup>57</sup> for reals = 0.7 pm on the earth if \e x is an angle in
* degrees. (This is about 1000 times more resolution than we get with
* angles around 90&deg;.) We use this to avoid having to deal with near
* singular cases when \e x is non-zero but tiny (e.g.,
* 10<sup>&minus;200</sup>). This converts &minus;0 to +0; however tiny
* negative numbers get converted to &minus;0.
**********************************************************************/
template<typename T> static T AngRound(T x);
/**
* Evaluate the sine and cosine function with the argument in degrees
*
* @tparam T the type of the arguments.
* @param[in] x in degrees.
* @param[out] sinx sin(<i>x</i>).
* @param[out] cosx cos(<i>x</i>).
*
* The results obey exactly the elementary properties of the trigonometric
* functions, e.g., sin 9&deg; = cos 81&deg; = &minus; sin 123456789&deg;.
* If x = &minus;0, then \e sinx = &minus;0; this is the only case where
* &minus;0 is returned.
**********************************************************************/
template<typename T> static void sincosd(T x, T& sinx, T& cosx);
/**
* Evaluate the sine function with the argument in degrees
*
* @tparam T the type of the argument and the returned value.
* @param[in] x in degrees.
* @return sin(<i>x</i>).
**********************************************************************/
template<typename T> static T sind(T x);
/**
* Evaluate the cosine function with the argument in degrees
*
* @tparam T the type of the argument and the returned value.
* @param[in] x in degrees.
* @return cos(<i>x</i>).
**********************************************************************/
template<typename T> static T cosd(T x);
/**
* Evaluate the tangent function with the argument in degrees
*
* @tparam T the type of the argument and the returned value.
* @param[in] x in degrees.
* @return tan(<i>x</i>).
*
* If \e x = &plusmn;90&deg;, then a suitably large (but finite) value is
* returned.
**********************************************************************/
template<typename T> static T tand(T x);
/**
* Evaluate the atan2 function with the result in degrees
*
* @tparam T the type of the arguments and the returned value.
* @param[in] y
* @param[in] x
* @return atan2(<i>y</i>, <i>x</i>) in degrees.
*
* The result is in the range (&minus;180&deg; 180&deg;]. N.B.,
* atan2d(&plusmn;0, &minus;1) = +180&deg;; atan2d(&minus;&epsilon;,
* &minus;1) = &minus;180&deg;, for &epsilon; positive and tiny;
* atan2d(&plusmn;0, +1) = &plusmn;0&deg;.
**********************************************************************/
template<typename T> static T atan2d(T y, T x);
/**
* Evaluate the atan function with the result in degrees
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return atan(<i>x</i>) in degrees.
**********************************************************************/
template<typename T> static T atand(T x);
/**
* Evaluate <i>e</i> atanh(<i>e x</i>)
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @param[in] es the signed eccentricity = sign(<i>e</i><sup>2</sup>)
* sqrt(|<i>e</i><sup>2</sup>|)
* @return <i>e</i> atanh(<i>e x</i>)
*
* If <i>e</i><sup>2</sup> is negative (<i>e</i> is imaginary), the
* expression is evaluated in terms of atan.
**********************************************************************/
template<typename T> static T eatanhe(T x, T es);
/**
* tan&chi; in terms of tan&phi;
*
* @tparam T the type of the argument and the returned value.
* @param[in] tau &tau; = tan&phi;
* @param[in] es the signed eccentricity = sign(<i>e</i><sup>2</sup>)
* sqrt(|<i>e</i><sup>2</sup>|)
* @return &tau;&prime; = tan&chi;
*
* See Eqs. (7--9) of
* C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-011-0445-3">
* Transverse Mercator with an accuracy of a few nanometers,</a>
* J. Geodesy 85(8), 475--485 (Aug. 2011)
* (preprint
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>).
**********************************************************************/
template<typename T> static T taupf(T tau, T es);
/**
* tan&phi; in terms of tan&chi;
*
* @tparam T the type of the argument and the returned value.
* @param[in] taup &tau;&prime; = tan&chi;
* @param[in] es the signed eccentricity = sign(<i>e</i><sup>2</sup>)
* sqrt(|<i>e</i><sup>2</sup>|)
* @return &tau; = tan&phi;
*
* See Eqs. (19--21) of
* C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-011-0445-3">
* Transverse Mercator with an accuracy of a few nanometers,</a>
* J. Geodesy 85(8), 475--485 (Aug. 2011)
* (preprint
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>).
**********************************************************************/
template<typename T> static T tauf(T taup, T es);
/**
* Test for finiteness.
*
* @tparam T the type of the argument.
* @param[in] x
* @return true if number is finite, false if NaN or infinite.
*
* \deprecated Use std::isfinite(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::isfinite(x)")
static bool isfinite(T x);
/**
* The NaN (not a number)
*
* @tparam T the type of the returned value.
* @return NaN if available, otherwise return the max real of type T.
**********************************************************************/
template<typename T = real> static T NaN();
/**
* Test for NaN.
*
* @tparam T the type of the argument.
* @param[in] x
* @return true if argument is a NaN.
*
* \deprecated Use std::isnan(x).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use std::isnan(x)")
static bool isnan(T x);
/**
* Infinity
*
* @tparam T the type of the returned value.
* @return infinity if available, otherwise return the max real.
**********************************************************************/
template<typename T = real> static T infinity();
/**
* Swap the bytes of a quantity
*
* @tparam T the type of the argument and the returned value.
* @param[in] x
* @return x with its bytes swapped.
**********************************************************************/
template<typename T> static T swab(T x) {
union {
T r;
unsigned char c[sizeof(T)];
} b;
b.r = x;
for (int i = sizeof(T)/2; i--; )
std::swap(b.c[i], b.c[sizeof(T) - 1 - i]);
return b.r;
}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_MATH_HPP

837
external/include/GeographicLib/NearestNeighbor.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,837 @@
/**
* \file NearestNeighbor.hpp
* \brief Header for GeographicLib::NearestNeighbor class
*
* Copyright (c) Charles Karney (2016-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_NEARESTNEIGHBOR_HPP)
#define GEOGRAPHICLIB_NEARESTNEIGHBOR_HPP 1
#include <algorithm> // for nth_element, max_element, etc.
#include <vector>
#include <queue> // for priority_queue
#include <utility> // for swap + pair
#include <cstring>
#include <limits>
#include <cmath>
#include <iostream>
#include <sstream>
// Only for GeographicLib::GeographicErr
#include <GeographicLib/Constants.hpp>
#if defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION) && \
GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
#endif
#if defined(_MSC_VER)
// Squelch warnings about constant conditional expressions
# pragma warning (push)
# pragma warning (disable: 4127)
#endif
namespace GeographicLib {
/**
* \brief Nearest-neighbor calculations
*
* This class solves the nearest-neighbor problm using a vantage-point tree
* as described in \ref nearest.
*
* This class is templated so that it can handle arbitrary metric spaces as
* follows:
*
* @tparam dist_t the type used for measuring distances; it can be a real or
* signed integer type; in typical geodetic applications, \e dist_t might
* be <code>double</code>.
* @tparam pos_t the type for specifying the positions of points; geodetic
* application might bundled the latitude and longitude into a
* <code>std::pair<dist_t, dist_t></code>.
* @tparam distfun_t the type of a function object which takes takes two
* positions (of type \e pos_t) and returns the distance (of type \e
* dist_t); in geodetic applications, this might be a class which is
* constructed with a Geodesic object and which implements a member
* function with a signature <code>dist_t operator() (const pos_t&, const
* pos_t&) const</code>, which returns the geodesic distance between two
* points.
*
* \note The distance measure must satisfy the triangle inequality, \f$
* d(a,c) \le d(a,b) + d(b,c) \f$ for all points \e a, \e b, \e c. The
* geodesic distance (given by Geodesic::Inverse) does, while the great
* ellipse distance and the rhumb line distance <i>do not</i>. If you use
* the ordinary Euclidean distance, i.e., \f$ \sqrt{(x_a-x_b)^2 +
* (y_a-y_b)^2} \f$ for two dimensions, don't be tempted to leave out the
* square root in the interests of "efficiency"; the squared distance does
* not satisfy the triangle inequality!
*
* \note This is a "header-only" implementation and, as such, depends in a
* minimal way on the rest of GeographicLib (the only dependency is through
* the use of GeographicLib::GeographicErr for handling compile-time and
* run-time exceptions). Therefore, it is easy to extract this class from
* the rest of GeographicLib and use it as a stand-alone facility.
*
* The \e dist_t type must support numeric_limits queries (specifically:
* is_signed, is_integer, max(), digits).
*
* The NearestNeighbor object is constructed with a vector of points (type \e
* pos_t) and a distance function (type \e distfun_t). However the object
* does \e not store the points. When querying the object with Search(),
* it's necessary to supply the same vector of points and the same distance
* function.
*
* There's no capability in this implementation to add or remove points from
* the set. Instead Initialize() should be called to re-initialize the
* object with the modified vector of points.
*
* Because of the overhead in constructing a NearestNeighbor object for a
* large set of points, functions Save() and Load() are provided to save the
* object to an external file. operator<<(), operator>>() and <a
* href="https://www.boost.org/libs/serialization/doc"> Boost
* serialization</a> can also be used to save and restore a NearestNeighbor
* object. This is illustrated in the example.
*
* Example of use:
* \include example-NearestNeighbor.cpp
**********************************************************************/
template <typename dist_t, typename pos_t, class distfun_t>
class NearestNeighbor {
// For tracking changes to the I/O format
static const int version = 1;
// This is what we get "free"; but if sizeof(dist_t) = 1 (unlikely), allow
// 4 slots (and this accommodates the default value bucket = 4).
static const int maxbucket =
(2 + ((4 * sizeof(dist_t)) / sizeof(int) >= 2 ?
(4 * sizeof(dist_t)) / sizeof(int) : 2));
public:
/**
* Default constructor for NearestNeighbor.
*
* This is equivalent to specifying an empty set of points.
**********************************************************************/
NearestNeighbor() : _numpoints(0), _bucket(0), _cost(0) {}
/**
* Constructor for NearestNeighbor.
*
* @param[in] pts a vector of points to include in the set.
* @param[in] dist the distance function object.
* @param[in] bucket the size of the buckets at the leaf nodes; this must
* lie in [0, 2 + 4*sizeof(dist_t)/sizeof(int)] (default 4).
* @exception GeographicErr if the value of \e bucket is out of bounds or
* the size of \e pts is too big for an int.
* @exception std::bad_alloc if memory for the tree can't be allocated.
*
* \e pts may contain coincident points (i.e., the distance between them
* vanishes); these are treated as distinct.
*
* The choice of \e bucket is a tradeoff between space and efficiency. A
* larger \e bucket decreases the size of the NearestNeighbor object which
* scales as pts.size() / max(1, bucket) and reduces the number of distance
* calculations to construct the object by log2(bucket) * pts.size().
* However each search then requires about bucket additional distance
* calculations.
*
* \warning The distances computed by \e dist must satisfy the standard
* metric conditions. If not, the results are undefined. Neither the data
* in \e pts nor the query points should contain NaNs or infinities because
* such data violates the metric conditions.
*
* \warning The same arguments \e pts and \e dist must be provided
* to the Search() function.
**********************************************************************/
NearestNeighbor(const std::vector<pos_t>& pts, const distfun_t& dist,
int bucket = 4) {
Initialize(pts, dist, bucket);
}
/**
* Initialize or re-initialize NearestNeighbor.
*
* @param[in] pts a vector of points to include in the tree.
* @param[in] dist the distance function object.
* @param[in] bucket the size of the buckets at the leaf nodes; this must
* lie in [0, 2 + 4*sizeof(dist_t)/sizeof(int)] (default 4).
* @exception GeographicErr if the value of \e bucket is out of bounds or
* the size of \e pts is too big for an int.
* @exception std::bad_alloc if memory for the tree can't be allocated.
*
* See also the documentation on the constructor.
*
* If an exception is thrown, the state of the NearestNeighbor is
* unchanged.
**********************************************************************/
void Initialize(const std::vector<pos_t>& pts, const distfun_t& dist,
int bucket = 4) {
static_assert(std::numeric_limits<dist_t>::is_signed,
"dist_t must be a signed type");
if (!( 0 <= bucket && bucket <= maxbucket ))
throw GeographicLib::GeographicErr
("bucket must lie in [0, 2 + 4*sizeof(dist_t)/sizeof(int)]");
if (pts.size() > size_t(std::numeric_limits<int>::max()))
throw GeographicLib::GeographicErr("pts array too big");
// the pair contains distance+id
std::vector<item> ids(pts.size());
for (int k = int(ids.size()); k--;)
ids[k] = std::make_pair(dist_t(0), k);
int cost = 0;
std::vector<Node> tree;
init(pts, dist, bucket, tree, ids, cost,
0, int(ids.size()), int(ids.size()/2));
_tree.swap(tree);
_numpoints = int(pts.size());
_bucket = bucket;
_mc = _sc = 0;
_cost = cost; _c1 = _k = _cmax = 0;
_cmin = std::numeric_limits<int>::max();
}
/**
* Search the NearestNeighbor.
*
* @param[in] pts the vector of points used for initialization.
* @param[in] dist the distance function object used for initialization.
* @param[in] query the query point.
* @param[out] ind a vector of indices to the closest points found.
* @param[in] k the number of points to search for (default = 1).
* @param[in] maxdist only return points with distances of \e maxdist or
* less from \e query (default is the maximum \e dist_t).
* @param[in] mindist only return points with distances of more than
* \e mindist from \e query (default = &minus;1).
* @param[in] exhaustive whether to do an exhaustive search (default true).
* @param[in] tol the tolerance on the results (default 0).
* @return the distance to the closest point found (&minus;1 if no points
* are found).
* @exception GeographicErr if \e pts has a different size from that used
* to construct the object.
*
* The indices returned in \e ind are sorted by distance from \e query
* (closest first).
*
* The simplest invocation is with just the 4 non-optional arguments. This
* returns the closest distance and the index to the closest point in
* <i>ind</i><sub>0</sub>. If there are several points equally close, then
* <i>ind</i><sub>0</sub> gives the index of an arbirary one of them. If
* there's no closest point (because the set of points is empty), then \e
* ind is empty and &minus;1 is returned.
*
* With \e exhaustive = true and \e tol = 0 (their default values), this
* finds the indices of \e k closest neighbors to \e query whose distances
* to \e query are in (\e mindist, \e maxdist]. If \e mindist and \e
* maxdist have their default values, then these bounds have no effect. If
* \e query is one of the points in the tree, then set \e mindist = 0 to
* prevent this point (and other coincident points) from being returned.
*
* If \e exhaustive = false, exit as soon as \e k results satisfying the
* distance criteria are found. If less than \e k results are returned
* then the search was exhaustive even if \e exhaustive = false.
*
* If \e tol is positive, do an approximate search; in this case the
* results are to be interpreted as follows: if the <i>k</i>'th distance is
* \e dk, then all results with distances less than or equal \e dk &minus;
* \e tol are correct; all others are suspect &mdash; there may be other
* closer results with distances greater or equal to \e dk &minus; \e tol.
* If less than \e k results are found, then the search is exact.
*
* \e mindist should be used to exclude a "small" neighborhood of the query
* point (relative to the average spacing of the data). If \e mindist is
* large, the efficiency of the search deteriorates.
*
* \note Only the shortest distance is returned (as as the function value).
* The distances to other points (indexed by <i>ind</i><sub><i>j</i></sub>
* for \e j > 0) can be found by invoking \e dist again.
*
* \warning The arguments \e pts and \e dist must be identical to those
* used to initialize the NearestNeighbor; if not, this function will
* return some meaningless result (however, if the size of \e pts is wrong,
* this function throw an exception).
*
* \warning The query point cannot be a NaN or infinite because then the
* metric conditions are violated.
**********************************************************************/
dist_t Search(const std::vector<pos_t>& pts, const distfun_t& dist,
const pos_t& query,
std::vector<int>& ind,
int k = 1,
dist_t maxdist = std::numeric_limits<dist_t>::max(),
dist_t mindist = -1,
bool exhaustive = true,
dist_t tol = 0) const {
if (_numpoints != int(pts.size()))
throw GeographicLib::GeographicErr("pts array has wrong size");
std::priority_queue<item> results;
if (_numpoints > 0 && k > 0 && maxdist > mindist) {
// distance to the kth closest point so far
dist_t tau = maxdist;
// first is negative of how far query is outside boundary of node
// +1 if on boundary or inside
// second is node index
std::priority_queue<item> todo;
todo.push(std::make_pair(dist_t(1), int(_tree.size()) - 1));
int c = 0;
while (!todo.empty()) {
int n = todo.top().second;
dist_t d = -todo.top().first;
todo.pop();
dist_t tau1 = tau - tol;
// compare tau and d again since tau may have become smaller.
if (!( n >= 0 && tau1 >= d )) continue;
const Node& current = _tree[n];
dist_t dst = 0; // to suppress warning about uninitialized variable
bool exitflag = false, leaf = current.index < 0;
for (int i = 0; i < (leaf ? _bucket : 1); ++i) {
int index = leaf ? current.leaves[i] : current.index;
if (index < 0) break;
dst = dist(pts[index], query);
++c;
if (dst > mindist && dst <= tau) {
if (int(results.size()) == k) results.pop();
results.push(std::make_pair(dst, index));
if (int(results.size()) == k) {
if (exhaustive)
tau = results.top().first;
else {
exitflag = true;
break;
}
if (tau <= tol) {
exitflag = true;
break;
}
}
}
}
if (exitflag) break;
if (current.index < 0) continue;
tau1 = tau - tol;
for (int l = 0; l < 2; ++l) {
if (current.data.child[l] >= 0 &&
dst + current.data.upper[l] >= mindist) {
if (dst < current.data.lower[l]) {
d = current.data.lower[l] - dst;
if (tau1 >= d)
todo.push(std::make_pair(-d, current.data.child[l]));
} else if (dst > current.data.upper[l]) {
d = dst - current.data.upper[l];
if (tau1 >= d)
todo.push(std::make_pair(-d, current.data.child[l]));
} else
todo.push(std::make_pair(dist_t(1), current.data.child[l]));
}
}
}
++_k;
_c1 += c;
double omc = _mc;
_mc += (c - omc) / _k;
_sc += (c - omc) * (c - _mc);
if (c > _cmax) _cmax = c;
if (c < _cmin) _cmin = c;
}
dist_t d = -1;
ind.resize(results.size());
for (int i = int(ind.size()); i--;) {
ind[i] = int(results.top().second);
if (i == 0) d = results.top().first;
results.pop();
}
return d;
}
/**
* @return the total number of points in the set.
**********************************************************************/
int NumPoints() const { return _numpoints; }
/**
* Write the object to an I/O stream.
*
* @param[in,out] os the stream to write to.
* @param[in] bin if true (the default) save in binary mode.
* @exception std::bad_alloc if memory for the string representation of the
* object can't be allocated.
*
* The counters tracking the statistics of searches are not saved; however
* the initializtion cost is saved. The format of the binary saves is \e
* not portable.
*
* \note <a href="https://www.boost.org/libs/serialization/doc">
* Boost serialization</a> can also be used to save and restore a
* NearestNeighbor object. This requires that the
* GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION macro be defined.
**********************************************************************/
void Save(std::ostream& os, bool bin = true) const {
int realspec = std::numeric_limits<dist_t>::digits *
(std::numeric_limits<dist_t>::is_integer ? -1 : 1);
if (bin) {
char id[] = "NearestNeighbor_";
os.write(id, 16);
int buf[6];
buf[0] = version;
buf[1] = realspec;
buf[2] = _bucket;
buf[3] = _numpoints;
buf[4] = int(_tree.size());
buf[5] = _cost;
os.write(reinterpret_cast<const char *>(buf), 6 * sizeof(int));
for (int i = 0; i < int(_tree.size()); ++i) {
const Node& node = _tree[i];
os.write(reinterpret_cast<const char *>(&node.index), sizeof(int));
if (node.index >= 0) {
os.write(reinterpret_cast<const char *>(node.data.lower),
2 * sizeof(dist_t));
os.write(reinterpret_cast<const char *>(node.data.upper),
2 * sizeof(dist_t));
os.write(reinterpret_cast<const char *>(node.data.child),
2 * sizeof(int));
} else {
os.write(reinterpret_cast<const char *>(node.leaves),
_bucket * sizeof(int));
}
}
} else {
std::stringstream ostring;
// Ensure enough precision for type dist_t. With C++11, max_digits10
// can be used instead.
if (!std::numeric_limits<dist_t>::is_integer) {
static const int prec
= int(std::ceil(std::numeric_limits<dist_t>::digits *
std::log10(2.0) + 1));
ostring.precision(prec);
}
ostring << version << " " << realspec << " " << _bucket << " "
<< _numpoints << " " << _tree.size() << " " << _cost;
for (int i = 0; i < int(_tree.size()); ++i) {
const Node& node = _tree[i];
ostring << "\n" << node.index;
if (node.index >= 0) {
for (int l = 0; l < 2; ++l)
ostring << " " << node.data.lower[l] << " " << node.data.upper[l]
<< " " << node.data.child[l];
} else {
for (int l = 0; l < _bucket; ++l)
ostring << " " << node.leaves[l];
}
}
os << ostring.str();
}
}
/**
* Read the object from an I/O stream.
*
* @param[in,out] is the stream to read from
* @param[in] bin if true (the default) load in binary mode.
* @exception GeographicErr if the state read from \e is is illegal.
* @exception std::bad_alloc if memory for the tree can't be allocated.
*
* The counters tracking the statistics of searches are reset by this
* operation. Binary data must have been saved on a machine with the same
* architecture. If an exception is thrown, the state of the
* NearestNeighbor is unchanged.
*
* \note <a href="https://www.boost.org/libs/serialization/doc">
* Boost serialization</a> can also be used to save and restore a
* NearestNeighbor object. This requires that the
* GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION macro be defined.
*
* \warning The same arguments \e pts and \e dist used for
* initialization must be provided to the Search() function.
**********************************************************************/
void Load(std::istream& is, bool bin = true) {
int version1, realspec, bucket, numpoints, treesize, cost;
if (bin) {
char id[17];
is.read(id, 16);
id[16] = '\0';
if (!(std::strcmp(id, "NearestNeighbor_") == 0))
throw GeographicLib::GeographicErr("Bad ID");
is.read(reinterpret_cast<char *>(&version1), sizeof(int));
is.read(reinterpret_cast<char *>(&realspec), sizeof(int));
is.read(reinterpret_cast<char *>(&bucket), sizeof(int));
is.read(reinterpret_cast<char *>(&numpoints), sizeof(int));
is.read(reinterpret_cast<char *>(&treesize), sizeof(int));
is.read(reinterpret_cast<char *>(&cost), sizeof(int));
} else {
if (!( is >> version1 >> realspec >> bucket >> numpoints >> treesize
>> cost ))
throw GeographicLib::GeographicErr("Bad header");
}
if (!( version1 == version ))
throw GeographicLib::GeographicErr("Incompatible version");
if (!( realspec == std::numeric_limits<dist_t>::digits *
(std::numeric_limits<dist_t>::is_integer ? -1 : 1) ))
throw GeographicLib::GeographicErr("Different dist_t types");
if (!( 0 <= bucket && bucket <= maxbucket ))
throw GeographicLib::GeographicErr("Bad bucket size");
if (!( 0 <= treesize && treesize <= numpoints ))
throw
GeographicLib::GeographicErr("Bad number of points or tree size");
if (!( 0 <= cost ))
throw GeographicLib::GeographicErr("Bad value for cost");
std::vector<Node> tree;
tree.reserve(treesize);
for (int i = 0; i < treesize; ++i) {
Node node;
if (bin) {
is.read(reinterpret_cast<char *>(&node.index), sizeof(int));
if (node.index >= 0) {
is.read(reinterpret_cast<char *>(node.data.lower),
2 * sizeof(dist_t));
is.read(reinterpret_cast<char *>(node.data.upper),
2 * sizeof(dist_t));
is.read(reinterpret_cast<char *>(node.data.child),
2 * sizeof(int));
} else {
is.read(reinterpret_cast<char *>(node.leaves),
bucket * sizeof(int));
for (int l = bucket; l < maxbucket; ++l)
node.leaves[l] = 0;
}
} else {
if (!( is >> node.index ))
throw GeographicLib::GeographicErr("Bad index");
if (node.index >= 0) {
for (int l = 0; l < 2; ++l) {
if (!( is >> node.data.lower[l] >> node.data.upper[l]
>> node.data.child[l] ))
throw GeographicLib::GeographicErr("Bad node data");
}
} else {
// Must be at least one valid leaf followed by a sequence end
// markers (-1).
for (int l = 0; l < bucket; ++l) {
if (!( is >> node.leaves[l] ))
throw GeographicLib::GeographicErr("Bad leaf data");
}
for (int l = bucket; l < maxbucket; ++l)
node.leaves[l] = 0;
}
}
node.Check(numpoints, treesize, bucket);
tree.push_back(node);
}
_tree.swap(tree);
_numpoints = numpoints;
_bucket = bucket;
_mc = _sc = 0;
_cost = cost; _c1 = _k = _cmax = 0;
_cmin = std::numeric_limits<int>::max();
}
/**
* Write the object to stream \e os as text.
*
* @param[in,out] os the output stream.
* @param[in] t the NearestNeighbor object to be saved.
* @exception std::bad_alloc if memory for the string representation of the
* object can't be allocated.
**********************************************************************/
friend std::ostream& operator<<(std::ostream& os, const NearestNeighbor& t)
{ t.Save(os, false); return os; }
/**
* Read the object from stream \e is as text.
*
* @param[in,out] is the input stream.
* @param[out] t the NearestNeighbor object to be loaded.
* @exception GeographicErr if the state read from \e is is illegal.
* @exception std::bad_alloc if memory for the tree can't be allocated.
**********************************************************************/
friend std::istream& operator>>(std::istream& is, NearestNeighbor& t)
{ t.Load(is, false); return is; }
/**
* Swap with another NearestNeighbor object.
*
* @param[in,out] t the NearestNeighbor object to swap with.
**********************************************************************/
void swap(NearestNeighbor& t) {
std::swap(_numpoints, t._numpoints);
std::swap(_bucket, t._bucket);
std::swap(_cost, t._cost);
_tree.swap(t._tree);
std::swap(_mc, t._mc);
std::swap(_sc, t._sc);
std::swap(_c1, t._c1);
std::swap(_k, t._k);
std::swap(_cmin, t._cmin);
std::swap(_cmax, t._cmax);
}
/**
* The accumulated statistics on the searches so far.
*
* @param[out] setupcost the cost of initializing the NearestNeighbor.
* @param[out] numsearches the number of calls to Search().
* @param[out] searchcost the total cost of the calls to Search().
* @param[out] mincost the minimum cost of a Search().
* @param[out] maxcost the maximum cost of a Search().
* @param[out] mean the mean cost of a Search().
* @param[out] sd the standard deviation in the cost of a Search().
*
* Here "cost" measures the number of distance calculations needed. Note
* that the accumulation of statistics is \e not thread safe.
**********************************************************************/
void Statistics(int& setupcost, int& numsearches, int& searchcost,
int& mincost, int& maxcost,
double& mean, double& sd) const {
setupcost = _cost; numsearches = _k; searchcost = _c1;
mincost = _cmin; maxcost = _cmax;
mean = _mc; sd = std::sqrt(_sc / (_k - 1));
}
/**
* Reset the counters for the accumulated statistics on the searches so
* far.
**********************************************************************/
void ResetStatistics() const {
_mc = _sc = 0;
_c1 = _k = _cmax = 0;
_cmin = std::numeric_limits<int>::max();
}
private:
// Package up a dist_t and an int. We will want to sort on the dist_t so
// put it first.
typedef std::pair<dist_t, int> item;
// \cond SKIP
class Node {
public:
struct bounds {
dist_t lower[2], upper[2]; // bounds on inner/outer distances
int child[2];
};
union {
bounds data;
int leaves[maxbucket];
};
int index;
Node()
: index(-1)
{
for (int i = 0; i < 2; ++i) {
data.lower[i] = data.upper[i] = 0;
data.child[i] = -1;
}
}
// Sanity check on a Node
void Check(int numpoints, int treesize, int bucket) const {
if (!( -1 <= index && index < numpoints ))
throw GeographicLib::GeographicErr("Bad index");
if (index >= 0) {
if (!( -1 <= data.child[0] && data.child[0] < treesize &&
-1 <= data.child[1] && data.child[1] < treesize ))
throw GeographicLib::GeographicErr("Bad child pointers");
if (!( 0 <= data.lower[0] && data.lower[0] <= data.upper[0] &&
data.upper[0] <= data.lower[1] &&
data.lower[1] <= data.upper[1] ))
throw GeographicLib::GeographicErr("Bad bounds");
} else {
// Must be at least one valid leaf followed by a sequence end markers
// (-1).
bool start = true;
for (int l = 0; l < bucket; ++l) {
if (!( (start ?
((l == 0 ? 0 : -1) <= leaves[l] && leaves[l] < numpoints) :
leaves[l] == -1) ))
throw GeographicLib::GeographicErr("Bad leaf data");
start = leaves[l] >= 0;
}
for (int l = bucket; l < maxbucket; ++l) {
if (leaves[l] != 0)
throw GeographicLib::GeographicErr("Bad leaf data");
}
}
}
#if defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION) && \
GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION
friend class boost::serialization::access;
template<class Archive>
void save(Archive& ar, const unsigned int) const {
ar & boost::serialization::make_nvp("index", index);
if (index < 0)
ar & boost::serialization::make_nvp("leaves", leaves);
else
ar & boost::serialization::make_nvp("lower", data.lower)
& boost::serialization::make_nvp("upper", data.upper)
& boost::serialization::make_nvp("child", data.child);
}
template<class Archive>
void load(Archive& ar, const unsigned int) {
ar & boost::serialization::make_nvp("index", index);
if (index < 0)
ar & boost::serialization::make_nvp("leaves", leaves);
else
ar & boost::serialization::make_nvp("lower", data.lower)
& boost::serialization::make_nvp("upper", data.upper)
& boost::serialization::make_nvp("child", data.child);
}
template<class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{ boost::serialization::split_member(ar, *this, file_version); }
#endif
};
// \endcond
#if defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION) && \
GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION
friend class boost::serialization::access;
template<class Archive> void save(Archive& ar, const unsigned) const {
int realspec = std::numeric_limits<dist_t>::digits *
(std::numeric_limits<dist_t>::is_integer ? -1 : 1);
// Need to use version1, otherwise load error in debug mode on Linux:
// undefined reference to GeographicLib::NearestNeighbor<...>::version.
int version1 = version;
ar & boost::serialization::make_nvp("version", version1)
& boost::serialization::make_nvp("realspec", realspec)
& boost::serialization::make_nvp("bucket", _bucket)
& boost::serialization::make_nvp("numpoints", _numpoints)
& boost::serialization::make_nvp("cost", _cost)
& boost::serialization::make_nvp("tree", _tree);
}
template<class Archive> void load(Archive& ar, const unsigned) {
int version1, realspec, bucket, numpoints, cost;
ar & boost::serialization::make_nvp("version", version1);
if (version1 != version)
throw GeographicLib::GeographicErr("Incompatible version");
std::vector<Node> tree;
ar & boost::serialization::make_nvp("realspec", realspec);
if (!( realspec == std::numeric_limits<dist_t>::digits *
(std::numeric_limits<dist_t>::is_integer ? -1 : 1) ))
throw GeographicLib::GeographicErr("Different dist_t types");
ar & boost::serialization::make_nvp("bucket", bucket);
if (!( 0 <= bucket && bucket <= maxbucket ))
throw GeographicLib::GeographicErr("Bad bucket size");
ar & boost::serialization::make_nvp("numpoints", numpoints)
& boost::serialization::make_nvp("cost", cost)
& boost::serialization::make_nvp("tree", tree);
if (!( 0 <= int(tree.size()) && int(tree.size()) <= numpoints ))
throw
GeographicLib::GeographicErr("Bad number of points or tree size");
for (int i = 0; i < int(tree.size()); ++i)
tree[i].Check(numpoints, int(tree.size()), bucket);
_tree.swap(tree);
_numpoints = numpoints;
_bucket = bucket;
_mc = _sc = 0;
_cost = cost; _c1 = _k = _cmax = 0;
_cmin = std::numeric_limits<int>::max();
}
template<class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{ boost::serialization::split_member(ar, *this, file_version); }
#endif
int _numpoints, _bucket, _cost;
std::vector<Node> _tree;
// Counters to track stastistics on the cost of searches
mutable double _mc, _sc;
mutable int _c1, _k, _cmin, _cmax;
int init(const std::vector<pos_t>& pts, const distfun_t& dist, int bucket,
std::vector<Node>& tree, std::vector<item>& ids, int& cost,
int l, int u, int vp) {
if (u == l)
return -1;
Node node;
if (u - l > (bucket == 0 ? 1 : bucket)) {
// choose a vantage point and move it to the start
int i = vp;
std::swap(ids[l], ids[i]);
int m = (u + l + 1) / 2;
for (int k = l + 1; k < u; ++k) {
ids[k].first = dist(pts[ids[l].second], pts[ids[k].second]);
++cost;
}
// partition around the median distance
std::nth_element(ids.begin() + l + 1,
ids.begin() + m,
ids.begin() + u);
node.index = ids[l].second;
if (m > l + 1) { // node.child[0] is possibly empty
typename std::vector<item>::iterator
t = std::min_element(ids.begin() + l + 1, ids.begin() + m);
node.data.lower[0] = t->first;
t = std::max_element(ids.begin() + l + 1, ids.begin() + m);
node.data.upper[0] = t->first;
// Use point with max distance as vantage point; this point act as a
// "corner" point and leads to a good partition.
node.data.child[0] = init(pts, dist, bucket, tree, ids, cost,
l + 1, m, int(t - ids.begin()));
}
typename std::vector<item>::iterator
t = std::max_element(ids.begin() + m, ids.begin() + u);
node.data.lower[1] = ids[m].first;
node.data.upper[1] = t->first;
// Use point with max distance as vantage point here too
node.data.child[1] = init(pts, dist, bucket, tree, ids, cost,
m, u, int(t - ids.begin()));
} else {
if (bucket == 0)
node.index = ids[l].second;
else {
node.index = -1;
// Sort the bucket entries so that the tree is independent of the
// implementation of nth_element.
std::sort(ids.begin() + l, ids.begin() + u);
for (int i = l; i < u; ++i)
node.leaves[i-l] = ids[i].second;
for (int i = u - l; i < bucket; ++i)
node.leaves[i] = -1;
for (int i = bucket; i < maxbucket; ++i)
node.leaves[i] = 0;
}
}
tree.push_back(node);
return int(tree.size()) - 1;
}
};
} // namespace GeographicLib
namespace std {
/**
* Swap two GeographicLib::NearestNeighbor objects.
*
* @tparam dist_t the type used for measuring distances.
* @tparam pos_t the type for specifying the positions of points.
* @tparam distfun_t the type for a function object which calculates
* distances between points.
* @param[in,out] a the first GeographicLib::NearestNeighbor to swap.
* @param[in,out] b the second GeographicLib::NearestNeighbor to swap.
**********************************************************************/
template <typename dist_t, typename pos_t, class distfun_t>
void swap(GeographicLib::NearestNeighbor<dist_t, pos_t, distfun_t>& a,
GeographicLib::NearestNeighbor<dist_t, pos_t, distfun_t>& b) {
a.swap(b);
}
} // namespace std
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_NEARESTNEIGHBOR_HPP

400
external/include/GeographicLib/NormalGravity.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,400 @@
/**
* \file NormalGravity.hpp
* \brief Header for GeographicLib::NormalGravity class
*
* Copyright (c) Charles Karney (2011-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_NORMALGRAVITY_HPP)
#define GEOGRAPHICLIB_NORMALGRAVITY_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/Geocentric.hpp>
namespace GeographicLib {
/**
* \brief The normal gravity of the earth
*
* "Normal" gravity refers to an idealization of the earth which is modeled
* as an rotating ellipsoid. The eccentricity of the ellipsoid, the rotation
* speed, and the distribution of mass within the ellipsoid are such that the
* ellipsoid is a "level ellipoid", a surface of constant potential
* (gravitational plus centrifugal). The acceleration due to gravity is
* therefore perpendicular to the surface of the ellipsoid.
*
* Because the distribution of mass within the ellipsoid is unspecified, only
* the potential exterior to the ellipsoid is well defined. In this class,
* the mass is assumed to be to concentrated on a "focal disc" of radius,
* (<i>a</i><sup>2</sup> &minus; <i>b</i><sup>2</sup>)<sup>1/2</sup>, where
* \e a is the equatorial radius of the ellipsoid and \e b is its polar
* semi-axis. In the case of an oblate ellipsoid, the mass is concentrated
* on a "focal rod" of length 2(<i>b</i><sup>2</sup> &minus;
* <i>a</i><sup>2</sup>)<sup>1/2</sup>. As a result the potential is well
* defined everywhere.
*
* There is a closed solution to this problem which is implemented here.
* Series "approximations" are only used to evaluate certain combinations of
* elementary functions where use of the closed expression results in a loss
* of accuracy for small arguments due to cancellation of the leading terms.
* However these series include sufficient terms to give full machine
* precision.
*
* Although the formulation used in this class applies to ellipsoids with
* arbitrary flattening, in practice, its use should be limited to about
* <i>b</i>/\e a &isin; [0.01, 100] or \e f &isin; [&minus;99, 0.99].
*
* Definitions:
* - <i>V</i><sub>0</sub>, the gravitational contribution to the normal
* potential;
* - &Phi;, the rotational contribution to the normal potential;
* - \e U = <i>V</i><sub>0</sub> + &Phi;, the total potential;
* - <b>&Gamma;</b> = &nabla;<i>V</i><sub>0</sub>, the acceleration due to
* mass of the earth;
* - <b>f</b> = &nabla;&Phi;, the centrifugal acceleration;
* - <b>&gamma;</b> = &nabla;\e U = <b>&Gamma;</b> + <b>f</b>, the normal
* acceleration;
* - \e X, \e Y, \e Z, geocentric coordinates;
* - \e x, \e y, \e z, local cartesian coordinates used to denote the east,
* north and up directions.
*
* References:
* - C. Somigliana, Teoria generale del campo gravitazionale dell'ellissoide
* di rotazione, Mem. Soc. Astron. Ital, <b>4</b>, 541--599 (1929).
* - W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San
* Francisco, 1967), Secs. 1-19, 2-7, 2-8 (2-9, 2-10), 6-2 (6-3).
* - B. Hofmann-Wellenhof, H. Moritz, Physical Geodesy (Second edition,
* Springer, 2006) https://doi.org/10.1007/978-3-211-33545-1
* - H. Moritz, Geodetic Reference System 1980, J. Geodesy 54(3), 395-405
* (1980) https://doi.org/10.1007/BF02521480
*
* For more information on normal gravity see \ref normalgravity.
*
* Example of use:
* \include example-NormalGravity.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT NormalGravity {
private:
static const int maxit_ = 20;
typedef Math::real real;
friend class GravityModel;
real _a, _GM, _omega, _f, _J2, _omega2, _aomega2;
real _e2, _ep2, _b, _E, _U0, _gammae, _gammap, _Q0, _k, _fstar;
Geocentric _earth;
static real atanzz(real x, bool alt) {
// This routine obeys the identity
// atanzz(x, alt) = atanzz(-x/(1+x), !alt)
//
// Require x >= -1. Best to call with alt, s.t. x >= 0; this results in
// a call to atan, instead of asin, or to asinh, instead of atanh.
using std::sqrt; using std::abs; using std::atan; using std::asin;
using std::asinh; using std::atanh;
real z = sqrt(abs(x));
return x == 0 ? 1 :
(alt ?
(!(x < 0) ? asinh(z) : asin(z)) / sqrt(abs(x) / (1 + x)) :
(!(x < 0) ? atan(z) : atanh(z)) / z);
}
static real atan7series(real x);
static real atan5series(real x);
static real Qf(real x, bool alt);
static real Hf(real x, bool alt);
static real QH3f(real x, bool alt);
real Jn(int n) const;
void Initialize(real a, real GM, real omega, real f_J2, bool geometricp);
public:
/** \name Setting up the normal gravity
**********************************************************************/
///@{
/**
* Constructor for the normal gravity.
*
* @param[in] a equatorial radius (meters).
* @param[in] GM mass constant of the ellipsoid
* (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \e G
* the gravitational constant and \e M the mass of the earth (usually
* including the mass of the earth's atmosphere).
* @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>).
* @param[in] f_J2 either the flattening of the ellipsoid \e f or the
* the dynamical form factor \e J2.
* @param[out] geometricp if true (the default), then \e f_J2 denotes the
* flattening, else it denotes the dynamical form factor \e J2.
* @exception if \e a is not positive or if the other parameters do not
* obey the restrictions given below.
*
* The shape of the ellipsoid can be given in one of two ways:
* - geometrically (\e geomtricp = true), the ellipsoid is defined by the
* flattening \e f = (\e a &minus; \e b) / \e a, where \e a and \e b are
* the equatorial radius and the polar semi-axis. The parameters should
* obey \e a &gt; 0, \e f &lt; 1. There are no restrictions on \e GM or
* \e omega, in particular, \e GM need not be positive.
* - physically (\e geometricp = false), the ellipsoid is defined by the
* dynamical form factor <i>J</i><sub>2</sub> = (\e C &minus; \e A) /
* <i>Ma</i><sup>2</sup>, where \e A and \e C are the equatorial and
* polar moments of inertia and \e M is the mass of the earth. The
* parameters should obey \e a &gt; 0, \e GM &gt; 0 and \e J2 &lt; 1/3
* &minus; (<i>omega</i><sup>2</sup><i>a</i><sup>3</sup>/<i>GM</i>)
* 8/(45&pi;). There is no restriction on \e omega.
**********************************************************************/
NormalGravity(real a, real GM, real omega, real f_J2,
bool geometricp = true);
/**
* A default constructor for the normal gravity. This sets up an
* uninitialized object and is used by GravityModel which constructs this
* object before it has read in the parameters for the reference ellipsoid.
**********************************************************************/
NormalGravity() : _a(-1) {}
///@}
/** \name Compute the gravity
**********************************************************************/
///@{
/**
* Evaluate the gravity on the surface of the ellipsoid.
*
* @param[in] lat the geographic latitude (degrees).
* @return &gamma; the acceleration due to gravity, positive downwards
* (m s<sup>&minus;2</sup>).
*
* Due to the axial symmetry of the ellipsoid, the result is independent of
* the value of the longitude. This acceleration is perpendicular to the
* surface of the ellipsoid. It includes the effects of the earth's
* rotation.
**********************************************************************/
Math::real SurfaceGravity(real lat) const;
/**
* Evaluate the gravity at an arbitrary point above (or below) the
* ellipsoid.
*
* @param[in] lat the geographic latitude (degrees).
* @param[in] h the height above the ellipsoid (meters).
* @param[out] gammay the northerly component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gammaz the upward component of the acceleration
* (m s<sup>&minus;2</sup>); this is usually negative.
* @return \e U the corresponding normal potential
* (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* Due to the axial symmetry of the ellipsoid, the result is independent of
* the value of the longitude and the easterly component of the
* acceleration vanishes, \e gammax = 0. The function includes the effects
* of the earth's rotation. When \e h = 0, this function gives \e gammay =
* 0 and the returned value matches that of NormalGravity::SurfaceGravity.
**********************************************************************/
Math::real Gravity(real lat, real h, real& gammay, real& gammaz)
const;
/**
* Evaluate the components of the acceleration due to gravity and the
* centrifugal acceleration in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @param[out] gammaX the \e X component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gammaY the \e Y component of the acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] gammaZ the \e Z component of the acceleration
* (m s<sup>&minus;2</sup>).
* @return \e U = <i>V</i><sub>0</sub> + &Phi; the sum of the
* gravitational and centrifugal potentials
* (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* The acceleration given by <b>&gamma;</b> = &nabla;\e U =
* &nabla;<i>V</i><sub>0</sub> + &nabla;&Phi; = <b>&Gamma;</b> + <b>f</b>.
**********************************************************************/
Math::real U(real X, real Y, real Z,
real& gammaX, real& gammaY, real& gammaZ) const;
/**
* Evaluate the components of the acceleration due to the gravitational
* force in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[in] Z geocentric coordinate of point (meters).
* @param[out] GammaX the \e X component of the acceleration due to the
* gravitational force (m s<sup>&minus;2</sup>).
* @param[out] GammaY the \e Y component of the acceleration due to the
* @param[out] GammaZ the \e Z component of the acceleration due to the
* gravitational force (m s<sup>&minus;2</sup>).
* @return <i>V</i><sub>0</sub> the gravitational potential
* (m<sup>2</sup> s<sup>&minus;2</sup>).
*
* This function excludes the centrifugal acceleration and is appropriate
* to use for space applications. In terrestrial applications, the
* function NormalGravity::U (which includes this effect) should usually be
* used.
**********************************************************************/
Math::real V0(real X, real Y, real Z,
real& GammaX, real& GammaY, real& GammaZ) const;
/**
* Evaluate the centrifugal acceleration in geocentric coordinates.
*
* @param[in] X geocentric coordinate of point (meters).
* @param[in] Y geocentric coordinate of point (meters).
* @param[out] fX the \e X component of the centrifugal acceleration
* (m s<sup>&minus;2</sup>).
* @param[out] fY the \e Y component of the centrifugal acceleration
* (m s<sup>&minus;2</sup>).
* @return &Phi; the centrifugal potential (m<sup>2</sup>
* s<sup>&minus;2</sup>).
*
* &Phi; is independent of \e Z, thus \e fZ = 0. This function
* NormalGravity::U sums the results of NormalGravity::V0 and
* NormalGravity::Phi.
**********************************************************************/
Math::real Phi(real X, real Y, real& fX, real& fY) const;
///@}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return true if the object has been initialized.
**********************************************************************/
bool Init() const { return _a > 0; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const
{ return Init() ? _a : Math::NaN(); }
/**
* @return \e GM the mass constant of the ellipsoid
* (m<sup>3</sup> s<sup>&minus;2</sup>). This is the value used in the
* constructor.
**********************************************************************/
Math::real MassConstant() const
{ return Init() ? _GM : Math::NaN(); }
/**
* @return <i>J</i><sub><i>n</i></sub> the dynamical form factors of the
* ellipsoid.
*
* If \e n = 2 (the default), this is the value of <i>J</i><sub>2</sub>
* used in the constructor. Otherwise it is the zonal coefficient of the
* Legendre harmonic sum of the normal gravitational potential. Note that
* <i>J</i><sub><i>n</i></sub> = 0 if \e n is odd. In most gravity
* applications, fully normalized Legendre functions are used and the
* corresponding coefficient is <i>C</i><sub><i>n</i>0</sub> =
* &minus;<i>J</i><sub><i>n</i></sub> / sqrt(2 \e n + 1).
**********************************************************************/
Math::real DynamicalFormFactor(int n = 2) const
{ return Init() ? ( n == 2 ? _J2 : Jn(n)) : Math::NaN(); }
/**
* @return &omega; the angular velocity of the ellipsoid (rad
* s<sup>&minus;1</sup>). This is the value used in the constructor.
**********************************************************************/
Math::real AngularVelocity() const
{ return Init() ? _omega : Math::NaN(); }
/**
* @return <i>f</i> the flattening of the ellipsoid (\e a &minus; \e b)/\e
* a.
**********************************************************************/
Math::real Flattening() const
{ return Init() ? _f : Math::NaN(); }
/**
* @return &gamma;<sub>e</sub> the normal gravity at equator (m
* s<sup>&minus;2</sup>).
**********************************************************************/
Math::real EquatorialGravity() const
{ return Init() ? _gammae : Math::NaN(); }
/**
* @return &gamma;<sub>p</sub> the normal gravity at poles (m
* s<sup>&minus;2</sup>).
**********************************************************************/
Math::real PolarGravity() const
{ return Init() ? _gammap : Math::NaN(); }
/**
* @return <i>f*</i> the gravity flattening (&gamma;<sub>p</sub> &minus;
* &gamma;<sub>e</sub>) / &gamma;<sub>e</sub>.
**********************************************************************/
Math::real GravityFlattening() const
{ return Init() ? _fstar : Math::NaN(); }
/**
* @return <i>U</i><sub>0</sub> the constant normal potential for the
* surface of the ellipsoid (m<sup>2</sup> s<sup>&minus;2</sup>).
**********************************************************************/
Math::real SurfacePotential() const
{ return Init() ? _U0 : Math::NaN(); }
/**
* @return the Geocentric object used by this instance.
**********************************************************************/
const Geocentric& Earth() const { return _earth; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of NormalGravity for the WGS84 ellipsoid.
**********************************************************************/
static const NormalGravity& WGS84();
/**
* A global instantiation of NormalGravity for the GRS80 ellipsoid.
**********************************************************************/
static const NormalGravity& GRS80();
/**
* Compute the flattening from the dynamical form factor.
*
* @param[in] a equatorial radius (meters).
* @param[in] GM mass constant of the ellipsoid
* (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \e G
* the gravitational constant and \e M the mass of the earth (usually
* including the mass of the earth's atmosphere).
* @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>).
* @param[in] J2 the dynamical form factor.
* @return \e f the flattening of the ellipsoid.
*
* This routine requires \e a &gt; 0, \e GM &gt; 0, \e J2 &lt; 1/3 &minus;
* <i>omega</i><sup>2</sup><i>a</i><sup>3</sup>/<i>GM</i> 8/(45&pi;). A
* NaN is returned if these conditions do not hold. The restriction to
* positive \e GM is made because for negative \e GM two solutions are
* possible.
**********************************************************************/
static Math::real J2ToFlattening(real a, real GM, real omega, real J2);
/**
* Compute the dynamical form factor from the flattening.
*
* @param[in] a equatorial radius (meters).
* @param[in] GM mass constant of the ellipsoid
* (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \e G
* the gravitational constant and \e M the mass of the earth (usually
* including the mass of the earth's atmosphere).
* @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>).
* @param[in] f the flattening of the ellipsoid.
* @return \e J2 the dynamical form factor.
*
* This routine requires \e a &gt; 0, \e GM &ne; 0, \e f &lt; 1. The
* values of these parameters are not checked.
**********************************************************************/
static Math::real FlatteningToJ2(real a, real GM, real omega, real f);
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_NORMALGRAVITY_HPP

255
external/include/GeographicLib/OSGB.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,255 @@
/**
* \file OSGB.hpp
* \brief Header for GeographicLib::OSGB class
*
* Copyright (c) Charles Karney (2010-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_OSGB_HPP)
#define GEOGRAPHICLIB_OSGB_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/TransverseMercator.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs string
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
/**
* \brief Ordnance Survey grid system for Great Britain
*
* The class implements the coordinate system used by the Ordnance Survey for
* maps of Great Britain and conversions to the grid reference system.
*
* See
* - <a href="http://www.ordnancesurvey.co.uk/docs/support/guide-coordinate-systems-great-britain.pdf">
* A guide to coordinate systems in Great Britain</a>
* - <a href="http://www.ordnancesurvey.co.uk/docs/support/national-grid.pdf">
* Guide to the National Grid</a>
*
* \warning the latitudes and longitudes for the Ordnance Survey grid
* system do not use the WGS84 datum. Do not use the values returned by this
* class in the UTMUPS, MGRS, or Geoid classes without first converting the
* datum (and vice versa).
*
* Example of use:
* \include example-OSGB.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT OSGB {
private:
typedef Math::real real;
static const char* const letters_;
static const char* const digits_;
static const TransverseMercator& OSGBTM();
enum {
base_ = 10,
tile_ = 100000,
tilelevel_ = 5,
tilegrid_ = 5,
tileoffx_ = 2 * tilegrid_,
tileoffy_ = 1 * tilegrid_,
minx_ = - tileoffx_ * tile_,
miny_ = - tileoffy_ * tile_,
maxx_ = (tilegrid_*tilegrid_ - tileoffx_) * tile_,
maxy_ = (tilegrid_*tilegrid_ - tileoffy_) * tile_,
// Maximum precision is um
maxprec_ = 5 + 6,
};
static real computenorthoffset();
static void CheckCoords(real x, real y);
OSGB(); // Disable constructor
public:
/**
* Forward projection, from geographic to OSGB coordinates.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
static void Forward(real lat, real lon,
real& x, real& y, real& gamma, real& k) {
OSGBTM().Forward(OriginLongitude(), lat, lon, x, y, gamma, k);
x += FalseEasting();
y += computenorthoffset();
}
/**
* Reverse projection, from OSGB coordinates to geographic.
*
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* The value of \e lon returned is in the range [&minus;180&deg;,
* 180&deg;].
**********************************************************************/
static void Reverse(real x, real y,
real& lat, real& lon, real& gamma, real& k) {
x -= FalseEasting();
y -= computenorthoffset();
OSGBTM().Reverse(OriginLongitude(), x, y, lat, lon, gamma, k);
}
/**
* OSGB::Forward without returning the convergence and scale.
**********************************************************************/
static void Forward(real lat, real lon, real& x, real& y) {
real gamma, k;
Forward(lat, lon, x, y, gamma, k);
}
/**
* OSGB::Reverse without returning the convergence and scale.
**********************************************************************/
static void Reverse(real x, real y, real& lat, real& lon) {
real gamma, k;
Reverse(x, y, lat, lon, gamma, k);
}
/**
* Convert OSGB coordinates to a grid reference.
*
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[in] prec precision relative to 100 km.
* @param[out] gridref National Grid reference.
* @exception GeographicErr if \e prec, \e x, or \e y is outside its
* allowed range.
* @exception std::bad_alloc if the memory for \e gridref can't be
* allocatied.
*
* \e prec specifies the precision of the grid reference string as follows:
* - prec = 0 (min), 100km
* - prec = 1, 10km
* - prec = 2, 1km
* - prec = 3, 100m
* - prec = 4, 10m
* - prec = 5, 1m
* - prec = 6, 0.1m
* - prec = 11 (max), 1&mu;m
*
* The easting must be in the range [&minus;1000 km, 1500 km) and the
* northing must be in the range [&minus;500 km, 2000 km). These bounds
* are consistent with rules for the letter designations for the grid
* system.
*
* If \e x or \e y is NaN, the returned grid reference is "INVALID".
**********************************************************************/
static void GridReference(real x, real y, int prec, std::string& gridref);
/**
* Convert OSGB coordinates to a grid reference.
*
* @param[in] gridref National Grid reference.
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] prec precision relative to 100 km.
* @param[in] centerp if true (default), return center of the grid square,
* else return SW (lower left) corner.
* @exception GeographicErr if \e gridref is illegal.
*
* The grid reference must be of the form: two letters (not including I)
* followed by an even number of digits (up to 22).
*
* If the first 2 characters of \e gridref are "IN", then \e x and \e y are
* set to NaN and \e prec is set to &minus;2.
**********************************************************************/
static void GridReference(const std::string& gridref,
real& x, real& y, int& prec,
bool centerp = true);
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the Airy 1830 ellipsoid (meters).
*
* This is 20923713 ft converted to meters using the rule 1 ft =
* 10<sup>9.48401603&minus;10</sup> m. The Airy 1830 value is returned
* because the OSGB projection is based on this ellipsoid. The conversion
* factor from feet to meters is the one used for the 1936 retriangulation
* of Britain; see Section A.1 (p. 37) of <i>A guide to coordinate systems
* in Great Britain</i>, v2.2 (Dec. 2013).
**********************************************************************/
static Math::real EquatorialRadius() {
// result is about 6377563.3960320664406 m
using std::pow;
return pow(real(10), real(48401603 - 100000000) / 100000000)
* real(20923713);
}
/**
* @return \e f the inverse flattening of the Airy 1830 ellipsoid.
*
* For the Airy 1830 ellipsoid, \e a = 20923713 ft and \e b = 20853810 ft;
* thus the flattening = (20923713 &minus; 20853810)/20923713 =
* 7767/2324857 = 1/299.32496459... (The Airy 1830 value is returned
* because the OSGB projection is based on this ellipsoid.)
**********************************************************************/
static Math::real Flattening()
{ return real(20923713 - 20853810) / real(20923713); }
/**
* @return \e k0 central scale for the OSGB projection (0.9996012717...).
*
* C. J. Mugnier, Grids &amp; Datums, PE&amp;RS, Oct. 2003, states that
* this is defined as 10<sup>9.9998268&minus;10</sup>.
**********************************************************************/
static Math::real CentralScale() {
using std::pow;
return pow(real(10), real(9998268 - 10000000) / 10000000);
}
/**
* @return latitude of the origin for the OSGB projection (49 degrees).
**********************************************************************/
static Math::real OriginLatitude() { return real(49); }
/**
* @return longitude of the origin for the OSGB projection (&minus;2
* degrees).
**********************************************************************/
static Math::real OriginLongitude() { return real(-2); }
/**
* @return false northing the OSGB projection (&minus;100000 meters).
**********************************************************************/
static Math::real FalseNorthing() { return real(-100000); }
/**
* @return false easting the OSGB projection (400000 meters).
**********************************************************************/
static Math::real FalseEasting() { return real(400000); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
static Math::real MajorRadius() { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_OSGB_HPP

160
external/include/GeographicLib/PolarStereographic.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,160 @@
/**
* \file PolarStereographic.hpp
* \brief Header for GeographicLib::PolarStereographic class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP)
#define GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP 1
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Polar stereographic projection
*
* Implementation taken from the report,
* - J. P. Snyder,
* <a href="http://pubs.er.usgs.gov/usgspubs/pp/pp1395"> Map Projections: A
* Working Manual</a>, USGS Professional Paper 1395 (1987),
* pp. 160--163.
*
* This is a straightforward implementation of the equations in Snyder except
* that Newton's method is used to invert the projection.
*
* This class also returns the meridian convergence \e gamma and scale \e k.
* The meridian convergence is the bearing of grid north (the \e y axis)
* measured clockwise from true north.
*
* Example of use:
* \include example-PolarStereographic.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT PolarStereographic {
private:
typedef Math::real real;
real _a, _f, _e2, _es, _e2m, _c;
real _k0;
public:
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] k0 central scale factor.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive.
**********************************************************************/
PolarStereographic(real a, real f, real k0);
/**
* Set the scale for the projection.
*
* @param[in] lat (degrees) assuming \e northp = true.
* @param[in] k scale at latitude \e lat (default 1).
* @exception GeographicErr \e k is not positive.
* @exception GeographicErr if \e lat is not in (&minus;90&deg;,
* 90&deg;].
**********************************************************************/
void SetScale(real lat, real k = real(1));
/**
* Forward projection, from geographic to polar stereographic.
*
* @param[in] northp the pole which is the center of projection (true means
* north, false means south).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* No false easting or northing is added. \e lat should be in the range
* (&minus;90&deg;, 90&deg;] for \e northp = true and in the range
* [&minus;90&deg;, 90&deg;) for \e northp = false.
**********************************************************************/
void Forward(bool northp, real lat, real lon,
real& x, real& y, real& gamma, real& k) const;
/**
* Reverse projection, from polar stereographic to geographic.
*
* @param[in] northp the pole which is the center of projection (true means
* north, false means south).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* No false easting or northing is added. The value of \e lon returned is
* in the range [&minus;180&deg;, 180&deg;].
**********************************************************************/
void Reverse(bool northp, real x, real y,
real& lat, real& lon, real& gamma, real& k) const;
/**
* PolarStereographic::Forward without returning the convergence and scale.
**********************************************************************/
void Forward(bool northp, real lat, real lon,
real& x, real& y) const {
real gamma, k;
Forward(northp, lat, lon, x, y, gamma, k);
}
/**
* PolarStereographic::Reverse without returning the convergence and scale.
**********************************************************************/
void Reverse(bool northp, real x, real y,
real& lat, real& lon) const {
real gamma, k;
Reverse(northp, x, y, lat, lon, gamma, k);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the value used in
* the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* The central scale for the projection. This is the value of \e k0 used
* in the constructor and is the scale at the pole unless overridden by
* PolarStereographic::SetScale.
**********************************************************************/
Math::real CentralScale() const { return _k0; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of PolarStereographic with the WGS84 ellipsoid
* and the UPS scale factor. However, unlike UPS, no false easting or
* northing is added.
**********************************************************************/
static const PolarStereographic& UPS();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP

325
external/include/GeographicLib/PolygonArea.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,325 @@
/**
* \file PolygonArea.hpp
* \brief Header for GeographicLib::PolygonAreaT class
*
* Copyright (c) Charles Karney (2010-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_POLYGONAREA_HPP)
#define GEOGRAPHICLIB_POLYGONAREA_HPP 1
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/GeodesicExact.hpp>
#include <GeographicLib/Rhumb.hpp>
#include <GeographicLib/Accumulator.hpp>
namespace GeographicLib {
/**
* \brief Polygon areas
*
* This computes the area of a polygon whose edges are geodesics using the
* method given in Section 6 of
* - C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-012-0578-z">
* Algorithms for geodesics</a>,
* J. Geodesy <b>87</b>, 43--55 (2013);
* DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
* 10.1007/s00190-012-0578-z</a>;
* addenda:
* <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
* geod-addenda.html</a>.
*
* Arbitrarily complex polygons are allowed. In the case self-intersecting
* of polygons the area is accumulated "algebraically", e.g., the areas of
* the 2 loops in a figure-8 polygon will partially cancel.
*
* This class lets you add vertices and edges one at a time to the polygon.
* The sequence must start with a vertex and thereafter vertices and edges
* can be added in any order. Any vertex after the first creates a new edge
* which is the \e shortest geodesic from the previous vertex. In some
* cases there may be two or many such shortest geodesics and the area is
* then not uniquely defined. In this case, either add an intermediate
* vertex or add the edge \e as an edge (by defining its direction and
* length).
*
* The area and perimeter are accumulated at two times the standard floating
* point precision to guard against the loss of accuracy with many-sided
* polygons. At any point you can ask for the perimeter and area so far.
* There's an option to treat the points as defining a polyline instead of a
* polygon; in that case, only the perimeter is computed.
*
* This is a templated class to allow it to be used with Geodesic,
* GeodesicExact, and Rhumb. GeographicLib::PolygonArea,
* GeographicLib::PolygonAreaExact, and GeographicLib::PolygonAreaRhumb are
* typedefs for these cases.
*
* For GeographicLib::PolygonArea (edges defined by Geodesic), an upper bound
* on the error is about 0.1 m<sup>2</sup> per vertex. However this is a
* wildly pessimistic estimate in most cases. A more realistic estimate of
* the error is given by a test involving 10<sup>7</sup> approximately
* regular polygons on the WGS84 ellipsoid. The centers and the orientations
* of the polygons were uniformly distributed, the number of vertices was
* log-uniformly distributed in [3, 300], and the center to vertex distance
* log-uniformly distributed in [0.1 m, 9000 km].
*
* Using double precision (the standard precision for GeographicLib), the
* maximum error in the perimeter was 200 nm, and the maximum error in the
* area was<pre>
* 0.0013 m^2 for perimeter < 10 km
* 0.0070 m^2 for perimeter < 100 km
* 0.070 m^2 for perimeter < 1000 km
* 0.11 m^2 for all perimeters
* </pre>
* The errors are given in terms of the perimeter, because it is expected
* that the errors depend mainly on the number of edges and the edge lengths.
*
* Using long doubles (GEOGRPAHICLIB_PRECISION = 3), the maximum error in the
* perimeter was 200 pm, and the maximum error in the area was<pre>
* 0.7 mm^2 for perim < 10 km
* 3.2 mm^2 for perimeter < 100 km
* 21 mm^2 for perimeter < 1000 km
* 45 mm^2 for all perimeters
* </pre>
*
* @tparam GeodType the geodesic class to use.
*
* Example of use:
* \include example-PolygonArea.cpp
*
* <a href="Planimeter.1.html">Planimeter</a> is a command-line utility
* providing access to the functionality of PolygonAreaT.
**********************************************************************/
template <class GeodType = Geodesic>
class PolygonAreaT {
private:
typedef Math::real real;
GeodType _earth;
real _area0; // Full ellipsoid area
bool _polyline; // Assume polyline (don't close and skip area)
unsigned _mask;
unsigned _num;
int _crossings;
Accumulator<> _areasum, _perimetersum;
real _lat0, _lon0, _lat1, _lon1;
static int transit(real lon1, real lon2) {
// Return 1 or -1 if crossing prime meridian in east or west direction.
// Otherwise return zero.
// Compute lon12 the same way as Geodesic::Inverse.
lon1 = Math::AngNormalize(lon1);
lon2 = Math::AngNormalize(lon2);
real lon12 = Math::AngDiff(lon1, lon2);
// Treat 0 as negative in these tests. This balances +/- 180 being
// treated as positive, i.e., +180.
int cross =
lon1 <= 0 && lon2 > 0 && lon12 > 0 ? 1 :
(lon2 <= 0 && lon1 > 0 && lon12 < 0 ? -1 : 0);
return cross;
}
// an alternate version of transit to deal with longitudes in the direct
// problem.
static int transitdirect(real lon1, real lon2) {
// Compute exactly the parity of
// int(ceil(lon2 / 360)) - int(ceil(lon1 / 360))
using std::remainder;
lon1 = remainder(lon1, real(720));
lon2 = remainder(lon2, real(720));
return ( (lon2 <= 0 && lon2 > -360 ? 1 : 0) -
(lon1 <= 0 && lon1 > -360 ? 1 : 0) );
}
void Remainder(Accumulator<>& a) const { a.remainder(_area0); }
void Remainder(real& a) const {
using std::remainder;
a = remainder(a, _area0);
}
template <typename T>
void AreaReduce(T& area, int crossings, bool reverse, bool sign) const;
public:
/**
* Constructor for PolygonAreaT.
*
* @param[in] earth the Geodesic object to use for geodesic calculations.
* @param[in] polyline if true that treat the points as defining a polyline
* instead of a polygon (default = false).
**********************************************************************/
PolygonAreaT(const GeodType& earth, bool polyline = false)
: _earth(earth)
, _area0(_earth.EllipsoidArea())
, _polyline(polyline)
, _mask(GeodType::LATITUDE | GeodType::LONGITUDE | GeodType::DISTANCE |
(_polyline ? GeodType::NONE :
GeodType::AREA | GeodType::LONG_UNROLL))
{ Clear(); }
/**
* Clear PolygonAreaT, allowing a new polygon to be started.
**********************************************************************/
void Clear() {
_num = 0;
_crossings = 0;
_areasum = 0;
_perimetersum = 0;
_lat0 = _lon0 = _lat1 = _lon1 = Math::NaN();
}
/**
* Add a point to the polygon or polyline.
*
* @param[in] lat the latitude of the point (degrees).
* @param[in] lon the longitude of the point (degrees).
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
void AddPoint(real lat, real lon);
/**
* Add an edge to the polygon or polyline.
*
* @param[in] azi azimuth at current point (degrees).
* @param[in] s distance from current point to next point (meters).
*
* This does nothing if no points have been added yet. Use
* PolygonAreaT::CurrentPoint to determine the position of the new vertex.
**********************************************************************/
void AddEdge(real azi, real s);
/**
* Return the results so far.
*
* @param[in] reverse if true then clockwise (instead of counter-clockwise)
* traversal counts as a positive area.
* @param[in] sign if true then return a signed result for the area if
* the polygon is traversed in the "wrong" direction instead of returning
* the area for the rest of the earth.
* @param[out] perimeter the perimeter of the polygon or length of the
* polyline (meters).
* @param[out] area the area of the polygon (meters<sup>2</sup>); only set
* if \e polyline is false in the constructor.
* @return the number of points.
*
* More points can be added to the polygon after this call.
**********************************************************************/
unsigned Compute(bool reverse, bool sign,
real& perimeter, real& area) const;
/**
* Return the results assuming a tentative final test point is added;
* however, the data for the test point is not saved. This lets you report
* a running result for the perimeter and area as the user moves the mouse
* cursor. Ordinary floating point arithmetic is used to accumulate the
* data for the test point; thus the area and perimeter returned are less
* accurate than if PolygonAreaT::AddPoint and PolygonAreaT::Compute are
* used.
*
* @param[in] lat the latitude of the test point (degrees).
* @param[in] lon the longitude of the test point (degrees).
* @param[in] reverse if true then clockwise (instead of counter-clockwise)
* traversal counts as a positive area.
* @param[in] sign if true then return a signed result for the area if
* the polygon is traversed in the "wrong" direction instead of returning
* the area for the rest of the earth.
* @param[out] perimeter the approximate perimeter of the polygon or length
* of the polyline (meters).
* @param[out] area the approximate area of the polygon
* (meters<sup>2</sup>); only set if polyline is false in the
* constructor.
* @return the number of points.
*
* \e lat should be in the range [&minus;90&deg;, 90&deg;].
**********************************************************************/
unsigned TestPoint(real lat, real lon, bool reverse, bool sign,
real& perimeter, real& area) const;
/**
* Return the results assuming a tentative final test point is added via an
* azimuth and distance; however, the data for the test point is not saved.
* This lets you report a running result for the perimeter and area as the
* user moves the mouse cursor. Ordinary floating point arithmetic is used
* to accumulate the data for the test point; thus the area and perimeter
* returned are less accurate than if PolygonAreaT::AddEdge and
* PolygonAreaT::Compute are used.
*
* @param[in] azi azimuth at current point (degrees).
* @param[in] s distance from current point to final test point (meters).
* @param[in] reverse if true then clockwise (instead of counter-clockwise)
* traversal counts as a positive area.
* @param[in] sign if true then return a signed result for the area if
* the polygon is traversed in the "wrong" direction instead of returning
* the area for the rest of the earth.
* @param[out] perimeter the approximate perimeter of the polygon or length
* of the polyline (meters).
* @param[out] area the approximate area of the polygon
* (meters<sup>2</sup>); only set if polyline is false in the
* constructor.
* @return the number of points.
**********************************************************************/
unsigned TestEdge(real azi, real s, bool reverse, bool sign,
real& perimeter, real& area) const;
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geodesic object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _earth.Flattening(); }
/**
* Report the previous vertex added to the polygon or polyline.
*
* @param[out] lat the latitude of the point (degrees).
* @param[out] lon the longitude of the point (degrees).
*
* If no points have been added, then NaNs are returned. Otherwise, \e lon
* will be in the range [&minus;180&deg;, 180&deg;].
**********************************************************************/
void CurrentPoint(real& lat, real& lon) const
{ lat = _lat1; lon = _lon1; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
};
/**
* @relates PolygonAreaT
*
* Polygon areas using Geodesic. This should be used if the flattening is
* small.
**********************************************************************/
typedef PolygonAreaT<Geodesic> PolygonArea;
/**
* @relates PolygonAreaT
*
* Polygon areas using GeodesicExact. (But note that the implementation of
* areas in GeodesicExact uses a high order series and this is only accurate
* for modest flattenings.)
**********************************************************************/
typedef PolygonAreaT<GeodesicExact> PolygonAreaExact;
/**
* @relates PolygonAreaT
*
* Polygon areas using Rhumb.
**********************************************************************/
typedef PolygonAreaT<Rhumb> PolygonAreaRhumb;
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_POLYGONAREA_HPP

621
external/include/GeographicLib/Rhumb.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,621 @@
/**
* \file Rhumb.hpp
* \brief Header for GeographicLib::Rhumb and GeographicLib::RhumbLine classes
*
* Copyright (c) Charles Karney (2014-2021) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_RHUMB_HPP)
#define GEOGRAPHICLIB_RHUMB_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/Ellipsoid.hpp>
#if !defined(GEOGRAPHICLIB_RHUMBAREA_ORDER)
/**
* The order of the series approximation used in rhumb area calculations.
* GEOGRAPHICLIB_RHUMBAREA_ORDER can be set to any integer in [4, 8].
**********************************************************************/
# define GEOGRAPHICLIB_RHUMBAREA_ORDER \
(GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
(GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
#endif
namespace GeographicLib {
class RhumbLine;
template <class T> class PolygonAreaT;
/**
* \brief Solve of the direct and inverse rhumb problems.
*
* The path of constant azimuth between two points on a ellipsoid at (\e
* lat1, \e lon1) and (\e lat2, \e lon2) is called the rhumb line (also
* called the loxodrome). Its length is \e s12 and its azimuth is \e azi12.
* (The azimuth is the heading measured clockwise from north.)
*
* Given \e lat1, \e lon1, \e azi12, and \e s12, we can determine \e lat2,
* and \e lon2. This is the \e direct rhumb problem and its solution is
* given by the function Rhumb::Direct.
*
* Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi12
* and \e s12. This is the \e inverse rhumb problem, whose solution is given
* by Rhumb::Inverse. This finds the shortest such rhumb line, i.e., the one
* that wraps no more than half way around the earth. If the end points are
* on opposite meridians, there are two shortest rhumb lines and the
* east-going one is chosen.
*
* These routines also optionally calculate the area under the rhumb line, \e
* S12. This is the area, measured counter-clockwise, of the rhumb line
* quadrilateral with corners (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>),
* (0,<i>lon2</i>), and (<i>lat2</i>,<i>lon2</i>).
*
* Note that rhumb lines may be appreciably longer (up to 50%) than the
* corresponding Geodesic. For example the distance between London Heathrow
* and Tokyo Narita via the rhumb line is 11400 km which is 18% longer than
* the geodesic distance 9600 km.
*
* For more information on rhumb lines see \ref rhumb.
*
* Example of use:
* \include example-Rhumb.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Rhumb {
private:
typedef Math::real real;
friend class RhumbLine;
template <class T> friend class PolygonAreaT;
Ellipsoid _ell;
bool _exact;
real _c2;
static const int tm_maxord = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER;
static const int maxpow_ = GEOGRAPHICLIB_RHUMBAREA_ORDER;
// _R[0] unused
real _R[maxpow_ + 1];
static real gd(real x)
{ using std::atan; using std::sinh; return atan(sinh(x)); }
// Use divided differences to determine (mu2 - mu1) / (psi2 - psi1)
// accurately
//
// Definition: Df(x,y,d) = (f(x) - f(y)) / (x - y)
// See:
// W. M. Kahan and R. J. Fateman,
// Symbolic computation of divided differences,
// SIGSAM Bull. 33(3), 7-28 (1999)
// https://doi.org/10.1145/334714.334716
// http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
static real Dlog(real x, real y) {
using std::sqrt; using std::asinh;
real t = x - y;
// Change
//
// atanh(t / (x + y))
//
// to
//
// asinh(t / (2 * sqrt(x*y)))
//
// to avoid taking atanh(1) when x is large and y is 1. N.B., this
// routine is invoked with positive x and y, so no need to guard against
// taking the sqrt of a negative quantity. This fixes bogus results for
// the area being returning when an endpoint is at a pole.
return t != 0 ? 2 * asinh(t / (2 * sqrt(x*y))) / t : 1 / x;
}
// N.B., x and y are in degrees
static real Dtan(real x, real y) {
real d = x - y, tx = Math::tand(x), ty = Math::tand(y), txy = tx * ty;
return d != 0 ?
(2 * txy > -1 ? (1 + txy) * Math::tand(d) : tx - ty) /
(d * Math::degree()) :
1 + txy;
}
static real Datan(real x, real y) {
using std::atan;
real d = x - y, xy = x * y;
return d != 0 ?
(2 * xy > -1 ? atan( d / (1 + xy) ) : atan(x) - atan(y)) / d :
1 / (1 + xy);
}
static real Dsin(real x, real y) {
using std::sin; using std::cos;
real d = (x - y) / 2;
return cos((x + y)/2) * (d != 0 ? sin(d) / d : 1);
}
static real Dsinh(real x, real y) {
using std::sinh; using std::cosh;
real d = (x - y) / 2;
return cosh((x + y) / 2) * (d != 0 ? sinh(d) / d : 1);
}
static real Dcosh(real x, real y) {
using std::sinh;
real d = (x - y) / 2;
return sinh((x + y) / 2) * (d != 0 ? sinh(d) / d : 1);
}
static real Dasinh(real x, real y) {
using std::asinh; using std::hypot;
real d = x - y,
hx = hypot(real(1), x), hy = hypot(real(1), y);
return d != 0 ?
asinh(x*y > 0 ? d * (x + y) / (x*hy + y*hx) : x*hy - y*hx) / d :
1 / hx;
}
static real Dgd(real x, real y) {
using std::sinh;
return Datan(sinh(x), sinh(y)) * Dsinh(x, y);
}
// N.B., x and y are the tangents of the angles
static real Dgdinv(real x, real y)
{ return Dasinh(x, y) / Datan(x, y); }
// Copied from LambertConformalConic...
// Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y)
real Deatanhe(real x, real y) const {
real t = x - y, d = 1 - _ell._e2 * x * y;
return t != 0 ? Math::eatanhe(t / d, _ell._es) / t : _ell._e2 / d;
}
// (E(x) - E(y)) / (x - y) -- E = incomplete elliptic integral of 2nd kind
real DE(real x, real y) const;
// (mux - muy) / (phix - phiy) using elliptic integrals
real DRectifying(real latx, real laty) const;
// (psix - psiy) / (phix - phiy)
real DIsometric(real latx, real laty) const;
// (sum(c[j]*sin(2*j*x),j=1..n) - sum(c[j]*sin(2*j*x),j=1..n)) / (x - y)
static real SinCosSeries(bool sinp,
real x, real y, const real c[], int n);
// (mux - muy) / (chix - chiy) using Krueger's series
real DConformalToRectifying(real chix, real chiy) const;
// (chix - chiy) / (mux - muy) using Krueger's series
real DRectifyingToConformal(real mux, real muy) const;
// (mux - muy) / (psix - psiy)
// N.B., psix and psiy are in degrees
real DIsometricToRectifying(real psix, real psiy) const;
// (psix - psiy) / (mux - muy)
real DRectifyingToIsometric(real mux, real muy) const;
real MeanSinXi(real psi1, real psi2) const;
// The following two functions (with lots of ignored arguments) mimic the
// interface to the corresponding Geodesic function. These are needed by
// PolygonAreaT.
void GenDirect(real lat1, real lon1, real azi12,
bool, real s12, unsigned outmask,
real& lat2, real& lon2, real&, real&, real&, real&, real&,
real& S12) const {
GenDirect(lat1, lon1, azi12, s12, outmask, lat2, lon2, S12);
}
void GenInverse(real lat1, real lon1, real lat2, real lon2,
unsigned outmask, real& s12, real& azi12,
real&, real& , real& , real& , real& S12) const {
GenInverse(lat1, lon1, lat2, lon2, outmask, s12, azi12, S12);
}
public:
/**
* Bit masks for what calculations to do. They specify which results to
* return in the general routines Rhumb::GenDirect and Rhumb::GenInverse
* routines. RhumbLine::mask is a duplication of this enum.
**********************************************************************/
enum mask {
/**
* No output.
* @hideinitializer
**********************************************************************/
NONE = 0U,
/**
* Calculate latitude \e lat2.
* @hideinitializer
**********************************************************************/
LATITUDE = 1U<<7,
/**
* Calculate longitude \e lon2.
* @hideinitializer
**********************************************************************/
LONGITUDE = 1U<<8,
/**
* Calculate azimuth \e azi12.
* @hideinitializer
**********************************************************************/
AZIMUTH = 1U<<9,
/**
* Calculate distance \e s12.
* @hideinitializer
**********************************************************************/
DISTANCE = 1U<<10,
/**
* Calculate area \e S12.
* @hideinitializer
**********************************************************************/
AREA = 1U<<14,
/**
* Unroll \e lon2 in the direct calculation.
* @hideinitializer
**********************************************************************/
LONG_UNROLL = 1U<<15,
/**
* Calculate everything. (LONG_UNROLL is not included in this mask.)
* @hideinitializer
**********************************************************************/
ALL = 0x7F80U,
};
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] exact if true (the default) use an addition theorem for
* elliptic integrals to compute divided differences; otherwise use
* series expansion (accurate for |<i>f</i>| < 0.01).
* @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* positive.
*
* See \ref rhumb, for a detailed description of the \e exact parameter.
**********************************************************************/
Rhumb(real a, real f, bool exact = true);
/**
* Solve the direct rhumb problem returning also the area.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi12 azimuth of the rhumb line (degrees).
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The value of
* \e lon2 returned is in the range [&minus;180&deg;, 180&deg;].
*
* If point 1 is a pole, the cosine of its latitude is taken to be
* 1/&epsilon;<sup>2</sup> (where &epsilon; is 2<sup>-52</sup>). This
* position, which is extremely close to the actual pole, allows the
* calculation to be carried out in finite terms. If \e s12 is large
* enough that the rhumb line crosses a pole, the longitude of point 2
* is indeterminate (a NaN is returned for \e lon2 and \e S12).
**********************************************************************/
void Direct(real lat1, real lon1, real azi12, real s12,
real& lat2, real& lon2, real& S12) const {
GenDirect(lat1, lon1, azi12, s12,
LATITUDE | LONGITUDE | AREA, lat2, lon2, S12);
}
/**
* Solve the direct rhumb problem without the area.
**********************************************************************/
void Direct(real lat1, real lon1, real azi12, real s12,
real& lat2, real& lon2) const {
real t;
GenDirect(lat1, lon1, azi12, s12, LATITUDE | LONGITUDE, lat2, lon2, t);
}
/**
* The general direct rhumb problem. Rhumb::Direct is defined in terms
* of this function.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi12 azimuth of the rhumb line (degrees).
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[in] outmask a bitor'ed combination of Rhumb::mask values
* specifying which of the following parameters should be set.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
*
* The Rhumb::mask values possible for \e outmask are
* - \e outmask |= Rhumb::LATITUDE for the latitude \e lat2;
* - \e outmask |= Rhumb::LONGITUDE for the latitude \e lon2;
* - \e outmask |= Rhumb::AREA for the area \e S12;
* - \e outmask |= Rhumb::ALL for all of the above;
* - \e outmask |= Rhumb::LONG_UNROLL to unroll \e lon2 instead of wrapping
* it into the range [&minus;180&deg;, 180&deg;].
* .
* With the Rhumb::LONG_UNROLL bit set, the quantity \e lon2 &minus;
* \e lon1 indicates how many times and in what sense the rhumb line
* encircles the ellipsoid.
**********************************************************************/
void GenDirect(real lat1, real lon1, real azi12, real s12,
unsigned outmask, real& lat2, real& lon2, real& S12) const;
/**
* Solve the inverse rhumb problem returning also the area.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[out] s12 rhumb distance between point 1 and point 2 (meters).
* @param[out] azi12 azimuth of the rhumb line (degrees).
* @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
*
* The shortest rhumb line is found. If the end points are on opposite
* meridians, there are two shortest rhumb lines and the east-going one is
* chosen. \e lat1 and \e lat2 should be in the range [&minus;90&deg;,
* 90&deg;]. The value of \e azi12 returned is in the range
* [&minus;180&deg;, 180&deg;].
*
* If either point is a pole, the cosine of its latitude is taken to be
* 1/&epsilon;<sup>2</sup> (where &epsilon; is 2<sup>-52</sup>). This
* position, which is extremely close to the actual pole, allows the
* calculation to be carried out in finite terms.
**********************************************************************/
void Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi12, real& S12) const {
GenInverse(lat1, lon1, lat2, lon2,
DISTANCE | AZIMUTH | AREA, s12, azi12, S12);
}
/**
* Solve the inverse rhumb problem without the area.
**********************************************************************/
void Inverse(real lat1, real lon1, real lat2, real lon2,
real& s12, real& azi12) const {
real t;
GenInverse(lat1, lon1, lat2, lon2, DISTANCE | AZIMUTH, s12, azi12, t);
}
/**
* The general inverse rhumb problem. Rhumb::Inverse is defined in terms
* of this function.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] lat2 latitude of point 2 (degrees).
* @param[in] lon2 longitude of point 2 (degrees).
* @param[in] outmask a bitor'ed combination of Rhumb::mask values
* specifying which of the following parameters should be set.
* @param[out] s12 rhumb distance between point 1 and point 2 (meters).
* @param[out] azi12 azimuth of the rhumb line (degrees).
* @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
*
* The Rhumb::mask values possible for \e outmask are
* - \e outmask |= Rhumb::DISTANCE for the latitude \e s12;
* - \e outmask |= Rhumb::AZIMUTH for the latitude \e azi12;
* - \e outmask |= Rhumb::AREA for the area \e S12;
* - \e outmask |= Rhumb::ALL for all of the above;
**********************************************************************/
void GenInverse(real lat1, real lon1, real lat2, real lon2,
unsigned outmask,
real& s12, real& azi12, real& S12) const;
/**
* Set up to compute several points on a single rhumb line.
*
* @param[in] lat1 latitude of point 1 (degrees).
* @param[in] lon1 longitude of point 1 (degrees).
* @param[in] azi12 azimuth of the rhumb line (degrees).
* @return a RhumbLine object.
*
* \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
*
* If point 1 is a pole, the cosine of its latitude is taken to be
* 1/&epsilon;<sup>2</sup> (where &epsilon; is 2<sup>-52</sup>). This
* position, which is extremely close to the actual pole, allows the
* calculation to be carried out in finite terms.
**********************************************************************/
RhumbLine Line(real lat1, real lon1, real azi12) const;
/** \name Inspector functions.
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _ell.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the
* value used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _ell.Flattening(); }
/**
* @return total area of ellipsoid in meters<sup>2</sup>. The area of a
* polygon encircling a pole can be found by adding
* Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the
* polygon.
**********************************************************************/
Math::real EllipsoidArea() const { return _ell.Area(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of Rhumb with the parameters for the WGS84
* ellipsoid.
**********************************************************************/
static const Rhumb& WGS84();
};
/**
* \brief Find a sequence of points on a single rhumb line.
*
* RhumbLine facilitates the determination of a series of points on a single
* rhumb line. The starting point (\e lat1, \e lon1) and the azimuth \e
* azi12 are specified in the call to Rhumb::Line which returns a RhumbLine
* object. RhumbLine.Position returns the location of point 2 (and,
* optionally, the corresponding area, \e S12) a distance \e s12 along the
* rhumb line.
*
* There is no public constructor for this class. (Use Rhumb::Line to create
* an instance.) The Rhumb object used to create a RhumbLine must stay in
* scope as long as the RhumbLine.
*
* Example of use:
* \include example-RhumbLine.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT RhumbLine {
private:
typedef Math::real real;
friend class Rhumb;
const Rhumb& _rh;
bool _exact; // TODO: RhumbLine::_exact is unused; retire
real _lat1, _lon1, _azi12, _salp, _calp, _mu1, _psi1, _r1;
// copy assignment not allowed
RhumbLine& operator=(const RhumbLine&) = delete;
RhumbLine(const Rhumb& rh, real lat1, real lon1, real azi12,
bool exact);
public:
/**
* Construction is via default copy constructor.
**********************************************************************/
RhumbLine(const RhumbLine&) = default;
/**
* This is a duplication of Rhumb::mask.
**********************************************************************/
enum mask {
/**
* No output.
* @hideinitializer
**********************************************************************/
NONE = Rhumb::NONE,
/**
* Calculate latitude \e lat2.
* @hideinitializer
**********************************************************************/
LATITUDE = Rhumb::LATITUDE,
/**
* Calculate longitude \e lon2.
* @hideinitializer
**********************************************************************/
LONGITUDE = Rhumb::LONGITUDE,
/**
* Calculate azimuth \e azi12.
* @hideinitializer
**********************************************************************/
AZIMUTH = Rhumb::AZIMUTH,
/**
* Calculate distance \e s12.
* @hideinitializer
**********************************************************************/
DISTANCE = Rhumb::DISTANCE,
/**
* Calculate area \e S12.
* @hideinitializer
**********************************************************************/
AREA = Rhumb::AREA,
/**
* Unroll \e lon2 in the direct calculation.
* @hideinitializer
**********************************************************************/
LONG_UNROLL = Rhumb::LONG_UNROLL,
/**
* Calculate everything. (LONG_UNROLL is not included in this mask.)
* @hideinitializer
**********************************************************************/
ALL = Rhumb::ALL,
};
/**
* Compute the position of point 2 which is a distance \e s12 (meters) from
* point 1. The area is also computed.
*
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
*
* The value of \e lon2 returned is in the range [&minus;180&deg;,
* 180&deg;].
*
* If \e s12 is large enough that the rhumb line crosses a pole, the
* longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
* \e S12).
**********************************************************************/
void Position(real s12, real& lat2, real& lon2, real& S12) const {
GenPosition(s12, LATITUDE | LONGITUDE | AREA, lat2, lon2, S12);
}
/**
* Compute the position of point 2 which is a distance \e s12 (meters) from
* point 1. The area is not computed.
**********************************************************************/
void Position(real s12, real& lat2, real& lon2) const {
real t;
GenPosition(s12, LATITUDE | LONGITUDE, lat2, lon2, t);
}
/**
* The general position routine. RhumbLine::Position is defined in term so
* this function.
*
* @param[in] s12 distance between point 1 and point 2 (meters); it can be
* negative.
* @param[in] outmask a bitor'ed combination of RhumbLine::mask values
* specifying which of the following parameters should be set.
* @param[out] lat2 latitude of point 2 (degrees).
* @param[out] lon2 longitude of point 2 (degrees).
* @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
*
* The RhumbLine::mask values possible for \e outmask are
* - \e outmask |= RhumbLine::LATITUDE for the latitude \e lat2;
* - \e outmask |= RhumbLine::LONGITUDE for the latitude \e lon2;
* - \e outmask |= RhumbLine::AREA for the area \e S12;
* - \e outmask |= RhumbLine::ALL for all of the above;
* - \e outmask |= RhumbLine::LONG_UNROLL to unroll \e lon2 instead of
* wrapping it into the range [&minus;180&deg;, 180&deg;].
* .
* With the RhumbLine::LONG_UNROLL bit set, the quantity \e lon2 &minus; \e
* lon1 indicates how many times and in what sense the rhumb line encircles
* the ellipsoid.
*
* If \e s12 is large enough that the rhumb line crosses a pole, the
* longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
* \e S12).
**********************************************************************/
void GenPosition(real s12, unsigned outmask,
real& lat2, real& lon2, real& S12) const;
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e lat1 the latitude of point 1 (degrees).
**********************************************************************/
Math::real Latitude() const { return _lat1; }
/**
* @return \e lon1 the longitude of point 1 (degrees).
**********************************************************************/
Math::real Longitude() const { return _lon1; }
/**
* @return \e azi12 the azimuth of the rhumb line (degrees).
**********************************************************************/
Math::real Azimuth() const { return _azi12; }
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Rhumb object used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _rh.EquatorialRadius(); }
/**
* @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Rhumb object used in the constructor.
**********************************************************************/
Math::real Flattening() const { return _rh.Flattening(); }
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_RHUMB_HPP

384
external/include/GeographicLib/SphericalEngine.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,384 @@
/**
* \file SphericalEngine.hpp
* \brief Header for GeographicLib::SphericalEngine class
*
* Copyright (c) Charles Karney (2011-2019) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_SPHERICALENGINE_HPP)
#define GEOGRAPHICLIB_SPHERICALENGINE_HPP 1
#include <vector>
#include <istream>
#include <GeographicLib/Constants.hpp>
#if defined(_MSC_VER)
// Squelch warnings about dll vs vector
# pragma warning (push)
# pragma warning (disable: 4251)
#endif
namespace GeographicLib {
class CircularEngine;
/**
* \brief The evaluation engine for SphericalHarmonic
*
* This serves as the backend to SphericalHarmonic, SphericalHarmonic1, and
* SphericalHarmonic2. Typically end-users will not have to access this
* class directly.
*
* See SphericalEngine.cpp for more information on the implementation.
*
* Example of use:
* \include example-SphericalEngine.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT SphericalEngine {
private:
typedef Math::real real;
// CircularEngine needs access to sqrttable, scale
friend class CircularEngine;
// Return the table of the square roots of integers
static std::vector<real>& sqrttable();
// An internal scaling of the coefficients to avoid overflow in
// intermediate calculations.
static real scale() {
using std::pow;
static const real
// Need extra real because, since C++11, pow(float, int) returns double
s = real(pow(real(std::numeric_limits<real>::radix),
-3 * (std::numeric_limits<real>::max_exponent < (1<<14) ?
std::numeric_limits<real>::max_exponent : (1<<14))
/ 5));
return s;
}
// Move latitudes near the pole off the axis by this amount.
static real eps() {
using std::sqrt;
return std::numeric_limits<real>::epsilon() *
sqrt(std::numeric_limits<real>::epsilon());
}
SphericalEngine(); // Disable constructor
public:
/**
* Supported normalizations for associated Legendre polynomials.
**********************************************************************/
enum normalization {
/**
* Fully normalized associated Legendre polynomials. See
* SphericalHarmonic::FULL for documentation.
*
* @hideinitializer
**********************************************************************/
FULL = 0,
/**
* Schmidt semi-normalized associated Legendre polynomials. See
* SphericalHarmonic::SCHMIDT for documentation.
*
* @hideinitializer
**********************************************************************/
SCHMIDT = 1,
};
/**
* \brief Package up coefficients for SphericalEngine
*
* This packages up the \e C, \e S coefficients and information about how
* the coefficients are stored into a single structure. This allows a
* vector of type SphericalEngine::coeff to be passed to
* SphericalEngine::Value. This class also includes functions to aid
* indexing into \e C and \e S.
*
* The storage layout of the coefficients is documented in
* SphericalHarmonic and SphericalHarmonic::SphericalHarmonic.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT coeff {
private:
int _Nx, _nmx, _mmx;
std::vector<real>::const_iterator _Cnm;
std::vector<real>::const_iterator _Snm;
public:
/**
* A default constructor
**********************************************************************/
coeff() : _Nx(-1) , _nmx(-1) , _mmx(-1) {}
/**
* The general constructor.
*
* @param[in] C a vector of coefficients for the cosine terms.
* @param[in] S a vector of coefficients for the sine terms.
* @param[in] N the degree giving storage layout for \e C and \e S.
* @param[in] nmx the maximum degree to be used.
* @param[in] mmx the maximum order to be used.
* @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy
* \e N &ge; \e nmx &ge; \e mmx &ge; &minus;1.
* @exception GeographicErr if \e C or \e S is not big enough to hold the
* coefficients.
* @exception std::bad_alloc if the memory for the square root table
* can't be allocated.
**********************************************************************/
coeff(const std::vector<real>& C,
const std::vector<real>& S,
int N, int nmx, int mmx)
: _Nx(N)
, _nmx(nmx)
, _mmx(mmx)
, _Cnm(C.begin())
, _Snm(S.begin())
{
if (!((_Nx >= _nmx && _nmx >= _mmx && _mmx >= 0) ||
// If mmx = -1 then the sums are empty so require nmx = -1 also.
(_nmx == -1 && _mmx == -1)))
throw GeographicErr("Bad indices for coeff");
if (!(index(_nmx, _mmx) < int(C.size()) &&
index(_nmx, _mmx) < int(S.size()) + (_Nx + 1)))
throw GeographicErr("Arrays too small in coeff");
SphericalEngine::RootTable(_nmx);
}
/**
* The constructor for full coefficient vectors.
*
* @param[in] C a vector of coefficients for the cosine terms.
* @param[in] S a vector of coefficients for the sine terms.
* @param[in] N the maximum degree and order.
* @exception GeographicErr if \e N does not satisfy \e N &ge; &minus;1.
* @exception GeographicErr if \e C or \e S is not big enough to hold the
* coefficients.
* @exception std::bad_alloc if the memory for the square root table
* can't be allocated.
**********************************************************************/
coeff(const std::vector<real>& C,
const std::vector<real>& S,
int N)
: _Nx(N)
, _nmx(N)
, _mmx(N)
, _Cnm(C.begin())
, _Snm(S.begin())
{
if (!(_Nx >= -1))
throw GeographicErr("Bad indices for coeff");
if (!(index(_nmx, _mmx) < int(C.size()) &&
index(_nmx, _mmx) < int(S.size()) + (_Nx + 1)))
throw GeographicErr("Arrays too small in coeff");
SphericalEngine::RootTable(_nmx);
}
/**
* @return \e N the degree giving storage layout for \e C and \e S.
**********************************************************************/
int N() const { return _Nx; }
/**
* @return \e nmx the maximum degree to be used.
**********************************************************************/
int nmx() const { return _nmx; }
/**
* @return \e mmx the maximum order to be used.
**********************************************************************/
int mmx() const { return _mmx; }
/**
* The one-dimensional index into \e C and \e S.
*
* @param[in] n the degree.
* @param[in] m the order.
* @return the one-dimensional index.
**********************************************************************/
int index(int n, int m) const
{ return m * _Nx - m * (m - 1) / 2 + n; }
/**
* An element of \e C.
*
* @param[in] k the one-dimensional index.
* @return the value of the \e C coefficient.
**********************************************************************/
Math::real Cv(int k) const { return *(_Cnm + k); }
/**
* An element of \e S.
*
* @param[in] k the one-dimensional index.
* @return the value of the \e S coefficient.
**********************************************************************/
Math::real Sv(int k) const { return *(_Snm + (k - (_Nx + 1))); }
/**
* An element of \e C with checking.
*
* @param[in] k the one-dimensional index.
* @param[in] n the requested degree.
* @param[in] m the requested order.
* @param[in] f a multiplier.
* @return the value of the \e C coefficient multiplied by \e f in \e n
* and \e m are in range else 0.
**********************************************************************/
Math::real Cv(int k, int n, int m, real f) const
{ return m > _mmx || n > _nmx ? 0 : *(_Cnm + k) * f; }
/**
* An element of \e S with checking.
*
* @param[in] k the one-dimensional index.
* @param[in] n the requested degree.
* @param[in] m the requested order.
* @param[in] f a multiplier.
* @return the value of the \e S coefficient multiplied by \e f in \e n
* and \e m are in range else 0.
**********************************************************************/
Math::real Sv(int k, int n, int m, real f) const
{ return m > _mmx || n > _nmx ? 0 : *(_Snm + (k - (_Nx + 1))) * f; }
/**
* The size of the coefficient vector for the cosine terms.
*
* @param[in] N the maximum degree.
* @param[in] M the maximum order.
* @return the size of the vector of cosine terms as stored in column
* major order.
**********************************************************************/
static int Csize(int N, int M)
{ return (M + 1) * (2 * N - M + 2) / 2; }
/**
* The size of the coefficient vector for the sine terms.
*
* @param[in] N the maximum degree.
* @param[in] M the maximum order.
* @return the size of the vector of cosine terms as stored in column
* major order.
**********************************************************************/
static int Ssize(int N, int M)
{ return Csize(N, M) - (N + 1); }
/**
* Load coefficients from a binary stream.
*
* @param[in] stream the input stream.
* @param[in,out] N The maximum degree of the coefficients.
* @param[in,out] M The maximum order of the coefficients.
* @param[out] C The vector of cosine coefficients.
* @param[out] S The vector of sine coefficients.
* @param[in] truncate if false (the default) then \e N and \e M are
* determined by the values in the binary stream; otherwise, the input
* values of \e N and \e M are used to truncate the coefficients read
* from the stream at the given degree and order.
* @exception GeographicErr if \e N and \e M do not satisfy \e N &ge;
* \e M &ge; &minus;1.
* @exception GeographicErr if there's an error reading the data.
* @exception std::bad_alloc if the memory for \e C or \e S can't be
* allocated.
*
* \e N and \e M are read as 4-byte ints. \e C and \e S are resized to
* accommodate all the coefficients (with the \e m = 0 coefficients for
* \e S excluded) and the data for these coefficients read as 8-byte
* doubles. The coefficients are stored in column major order. The
* bytes in the stream should use little-endian ordering. IEEE floating
* point is assumed for the coefficients.
**********************************************************************/
static void readcoeffs(std::istream& stream, int& N, int& M,
std::vector<real>& C, std::vector<real>& S,
bool truncate = false);
};
/**
* Evaluate a spherical harmonic sum and its gradient.
*
* @tparam gradp should the gradient be calculated.
* @tparam norm the normalization for the associated Legendre polynomials.
* @tparam L the number of terms in the coefficients.
* @param[in] c an array of coeff objects.
* @param[in] f array of coefficient multipliers. f[0] should be 1.
* @param[in] x the \e x component of the cartesian position.
* @param[in] y the \e y component of the cartesian position.
* @param[in] z the \e z component of the cartesian position.
* @param[in] a the normalizing radius.
* @param[out] gradx the \e x component of the gradient.
* @param[out] grady the \e y component of the gradient.
* @param[out] gradz the \e z component of the gradient.
* @result the spherical harmonic sum.
*
* See the SphericalHarmonic class for the definition of the sum. The
* coefficients used by this function are, for example, c[0].Cv + f[1] *
* c[1].Cv + ... + f[L&minus;1] * c[L&minus;1].Cv. (Note that f[0] is \e
* not used.) The upper limits on the sum are determined by c[0].nmx() and
* c[0].mmx(); these limits apply to \e all the components of the
* coefficients. The parameters \e gradp, \e norm, and \e L are template
* parameters, to allow more optimization to be done at compile time.
*
* Clenshaw summation is used which permits the evaluation of the sum
* without the need to allocate temporary arrays. Thus this function never
* throws an exception.
**********************************************************************/
template<bool gradp, normalization norm, int L>
static Math::real Value(const coeff c[], const real f[],
real x, real y, real z, real a,
real& gradx, real& grady, real& gradz);
/**
* Create a CircularEngine object
*
* @tparam gradp should the gradient be calculated.
* @tparam norm the normalization for the associated Legendre polynomials.
* @tparam L the number of terms in the coefficients.
* @param[in] c an array of coeff objects.
* @param[in] f array of coefficient multipliers. f[0] should be 1.
* @param[in] p the radius of the circle = sqrt(<i>x</i><sup>2</sup> +
* <i>y</i><sup>2</sup>).
* @param[in] z the height of the circle.
* @param[in] a the normalizing radius.
* @exception std::bad_alloc if the memory for the CircularEngine can't be
* allocated.
* @result the CircularEngine object.
*
* If you need to evaluate the spherical harmonic sum for several points
* with constant \e f, \e p = sqrt(<i>x</i><sup>2</sup> +
* <i>y</i><sup>2</sup>), \e z, and \e a, it is more efficient to construct
* call SphericalEngine::Circle to give a CircularEngine object and then
* call CircularEngine::operator()() with arguments <i>x</i>/\e p and
* <i>y</i>/\e p.
**********************************************************************/
template<bool gradp, normalization norm, int L>
static CircularEngine Circle(const coeff c[], const real f[],
real p, real z, real a);
/**
* Check that the static table of square roots is big enough and enlarge it
* if necessary.
*
* @param[in] N the maximum degree to be used in SphericalEngine.
* @exception std::bad_alloc if the memory for the square root table can't
* be allocated.
*
* Typically, there's no need for an end-user to call this routine, because
* the constructors for SphericalEngine::coeff do so. However, since this
* updates a static table, there's a possible race condition in a
* multi-threaded environment. Because this routine does nothing if the
* table is already large enough, one way to avoid race conditions is to
* call this routine at program start up (when it's still single threaded),
* supplying the largest degree that your program will use. E.g., \code
GeographicLib::SphericalEngine::RootTable(2190);
\endcode
* suffices to accommodate extant magnetic and gravity models.
**********************************************************************/
static void RootTable(int N);
/**
* Clear the static table of square roots and release the memory. Call
* this only when you are sure you no longer will be using SphericalEngine.
* Your program will crash if you call SphericalEngine after calling this
* routine.
*
* \warning It's safest not to call this routine at all. (The space used
* by the table is modest.)
**********************************************************************/
static void ClearRootTable() {
std::vector<real> temp(0);
sqrttable().swap(temp);
}
};
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_SPHERICALENGINE_HPP

356
external/include/GeographicLib/SphericalHarmonic.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,356 @@
/**
* \file SphericalHarmonic.hpp
* \brief Header for GeographicLib::SphericalHarmonic class
*
* Copyright (c) Charles Karney (2011-2019) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC_HPP)
#define GEOGRAPHICLIB_SPHERICALHARMONIC_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/SphericalEngine.hpp>
#include <GeographicLib/CircularEngine.hpp>
namespace GeographicLib {
/**
* \brief Spherical harmonic series
*
* This class evaluates the spherical harmonic sum \verbatim
V(x, y, z) = sum(n = 0..N)[ q^(n+1) * sum(m = 0..n)[
(C[n,m] * cos(m*lambda) + S[n,m] * sin(m*lambda)) *
P[n,m](cos(theta)) ] ]
\endverbatim
* where
* - <i>p</i><sup>2</sup> = <i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>,
* - <i>r</i><sup>2</sup> = <i>p</i><sup>2</sup> + <i>z</i><sup>2</sup>,
* - \e q = <i>a</i>/<i>r</i>,
* - &theta; = atan2(\e p, \e z) = the spherical \e colatitude,
* - &lambda; = atan2(\e y, \e x) = the longitude.
* - P<sub><i>nm</i></sub>(\e t) is the associated Legendre polynomial of
* degree \e n and order \e m.
*
* Two normalizations are supported for P<sub><i>nm</i></sub>
* - fully normalized denoted by SphericalHarmonic::FULL.
* - Schmidt semi-normalized denoted by SphericalHarmonic::SCHMIDT.
*
* Clenshaw summation is used for the sums over both \e n and \e m. This
* allows the computation to be carried out without the need for any
* temporary arrays. See SphericalEngine.cpp for more information on the
* implementation.
*
* References:
* - C. W. Clenshaw,
* <a href="https://doi.org/10.1090/S0025-5718-1955-0071856-0">
* A note on the summation of Chebyshev series</a>,
* %Math. Tables Aids Comput. 9(51), 118--120 (1955).
* - R. E. Deakin, Derivatives of the earth's potentials, Geomatics
* Research Australasia 68, 31--60, (June 1998).
* - W. A. Heiskanen and H. Moritz, Physical Geodesy, (Freeman, San
* Francisco, 1967). (See Sec. 1-14, for a definition of Pbar.)
* - S. A. Holmes and W. E. Featherstone,
* <a href="https://doi.org/10.1007/s00190-002-0216-2">
* A unified approach to the Clenshaw summation and the recursive
* computation of very high degree and order normalised associated Legendre
* functions</a>, J. Geodesy 76(5), 279--299 (2002).
* - C. C. Tscherning and K. Poder,
* <a href="http://cct.gfy.ku.dk/publ_cct/cct80.pdf">
* Some geodetic applications of Clenshaw summation</a>,
* Boll. Geod. Sci. Aff. 41(4), 349--375 (1982).
*
* Example of use:
* \include example-SphericalHarmonic.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT SphericalHarmonic {
public:
/**
* Supported normalizations for the associated Legendre polynomials.
**********************************************************************/
enum normalization {
/**
* Fully normalized associated Legendre polynomials.
*
* These are defined by
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(\e z)
* = (&minus;1)<sup><i>m</i></sup>
* sqrt(\e k (2\e n + 1) (\e n &minus; \e m)! / (\e n + \e m)!)
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers
* function (also known as the Legendre function on the cut or the
* associated Legendre polynomial) https://dlmf.nist.gov/14.7.E10 and
* \e k = 1 for \e m = 0 and \e k = 2 otherwise.
*
* The mean squared value of
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cos&theta;)
* cos(<i>m</i>&lambda;) and
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cos&theta;)
* sin(<i>m</i>&lambda;) over the sphere is 1.
*
* @hideinitializer
**********************************************************************/
FULL = SphericalEngine::FULL,
/**
* Schmidt semi-normalized associated Legendre polynomials.
*
* These are defined by
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(\e z)
* = (&minus;1)<sup><i>m</i></sup>
* sqrt(\e k (\e n &minus; \e m)! / (\e n + \e m)!)
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers
* function (also known as the Legendre function on the cut or the
* associated Legendre polynomial) https://dlmf.nist.gov/14.7.E10 and
* \e k = 1 for \e m = 0 and \e k = 2 otherwise.
*
* The mean squared value of
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cos&theta;)
* cos(<i>m</i>&lambda;) and
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cos&theta;)
* sin(<i>m</i>&lambda;) over the sphere is 1/(2\e n + 1).
*
* @hideinitializer
**********************************************************************/
SCHMIDT = SphericalEngine::SCHMIDT,
};
private:
typedef Math::real real;
SphericalEngine::coeff _c[1];
real _a;
unsigned _norm;
public:
/**
* Constructor with a full set of coefficients specified.
*
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the maximum degree and order of the sum
* @param[in] a the reference radius appearing in the definition of the
* sum.
* @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic::FULL (the default) or
* SphericalHarmonic::SCHMIDT.
* @exception GeographicErr if \e N does not satisfy \e N &ge; &minus;1.
* @exception GeographicErr if \e C or \e S is not big enough to hold the
* coefficients.
*
* The coefficients <i>C</i><sub><i>nm</i></sub> and
* <i>S</i><sub><i>nm</i></sub> are stored in the one-dimensional vectors
* \e C and \e S which must contain (\e N + 1)(\e N + 2)/2 and \e N (\e N +
* 1)/2 elements, respectively, stored in "column-major" order. Thus for
* \e N = 3, the order would be:
* <i>C</i><sub>00</sub>,
* <i>C</i><sub>10</sub>,
* <i>C</i><sub>20</sub>,
* <i>C</i><sub>30</sub>,
* <i>C</i><sub>11</sub>,
* <i>C</i><sub>21</sub>,
* <i>C</i><sub>31</sub>,
* <i>C</i><sub>22</sub>,
* <i>C</i><sub>32</sub>,
* <i>C</i><sub>33</sub>.
* In general the (\e n,\e m) element is at index \e m \e N &minus; \e m
* (\e m &minus; 1)/2 + \e n. The layout of \e S is the same except that
* the first column is omitted (since the \e m = 0 terms never contribute
* to the sum) and the 0th element is <i>S</i><sub>11</sub>
*
* The class stores <i>pointers</i> to the first elements of \e C and \e S.
* These arrays should not be altered or destroyed during the lifetime of a
* SphericalHarmonic object.
**********************************************************************/
SphericalHarmonic(const std::vector<real>& C,
const std::vector<real>& S,
int N, real a, unsigned norm = FULL)
: _a(a)
, _norm(norm)
{ _c[0] = SphericalEngine::coeff(C, S, N); }
/**
* Constructor with a subset of coefficients specified.
*
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the degree used to determine the layout of \e C and \e S.
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is
* from 0 thru \e nmx.
* @param[in] mmx the maximum order used in the sum. The sum over \e m is
* from 0 thru min(\e n, \e mmx).
* @param[in] a the reference radius appearing in the definition of the
* sum.
* @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic::FULL (the default) or
* SphericalHarmonic::SCHMIDT.
* @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy
* \e N &ge; \e nmx &ge; \e mmx &ge; &minus;1.
* @exception GeographicErr if \e C or \e S is not big enough to hold the
* coefficients.
*
* The class stores <i>pointers</i> to the first elements of \e C and \e S.
* These arrays should not be altered or destroyed during the lifetime of a
* SphericalHarmonic object.
**********************************************************************/
SphericalHarmonic(const std::vector<real>& C,
const std::vector<real>& S,
int N, int nmx, int mmx,
real a, unsigned norm = FULL)
: _a(a)
, _norm(norm)
{ _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx); }
/**
* A default constructor so that the object can be created when the
* constructor for another object is initialized. This default object can
* then be reset with the default copy assignment operator.
**********************************************************************/
SphericalHarmonic() {}
/**
* Compute the spherical harmonic sum.
*
* @param[in] x cartesian coordinate.
* @param[in] y cartesian coordinate.
* @param[in] z cartesian coordinate.
* @return \e V the spherical harmonic sum.
*
* This routine requires constant memory and thus never throws an
* exception.
**********************************************************************/
Math::real operator()(real x, real y, real z) const {
real f[] = {1};
real v = 0;
real dummy;
switch (_norm) {
case FULL:
v = SphericalEngine::Value<false, SphericalEngine::FULL, 1>
(_c, f, x, y, z, _a, dummy, dummy, dummy);
break;
case SCHMIDT:
default: // To avoid compiler warnings
v = SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 1>
(_c, f, x, y, z, _a, dummy, dummy, dummy);
break;
}
return v;
}
/**
* Compute a spherical harmonic sum and its gradient.
*
* @param[in] x cartesian coordinate.
* @param[in] y cartesian coordinate.
* @param[in] z cartesian coordinate.
* @param[out] gradx \e x component of the gradient
* @param[out] grady \e y component of the gradient
* @param[out] gradz \e z component of the gradient
* @return \e V the spherical harmonic sum.
*
* This is the same as the previous function, except that the components of
* the gradients of the sum in the \e x, \e y, and \e z directions are
* computed. This routine requires constant memory and thus never throws
* an exception.
**********************************************************************/
Math::real operator()(real x, real y, real z,
real& gradx, real& grady, real& gradz) const {
real f[] = {1};
real v = 0;
switch (_norm) {
case FULL:
v = SphericalEngine::Value<true, SphericalEngine::FULL, 1>
(_c, f, x, y, z, _a, gradx, grady, gradz);
break;
case SCHMIDT:
default: // To avoid compiler warnings
v = SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 1>
(_c, f, x, y, z, _a, gradx, grady, gradz);
break;
}
return v;
}
/**
* Create a CircularEngine to allow the efficient evaluation of several
* points on a circle of latitude.
*
* @param[in] p the radius of the circle.
* @param[in] z the height of the circle above the equatorial plane.
* @param[in] gradp if true the returned object will be able to compute the
* gradient of the sum.
* @exception std::bad_alloc if the memory for the CircularEngine can't be
* allocated.
* @return the CircularEngine object.
*
* SphericalHarmonic::operator()() exchanges the order of the sums in the
* definition, i.e., &sum;<sub><i>n</i> = 0..<i>N</i></sub>
* &sum;<sub><i>m</i> = 0..<i>n</i></sub> becomes &sum;<sub><i>m</i> =
* 0..<i>N</i></sub> &sum;<sub><i>n</i> = <i>m</i>..<i>N</i></sub>.
* SphericalHarmonic::Circle performs the inner sum over degree \e n (which
* entails about <i>N</i><sup>2</sup> operations). Calling
* CircularEngine::operator()() on the returned object performs the outer
* sum over the order \e m (about \e N operations).
*
* Here's an example of computing the spherical sum at a sequence of
* longitudes without using a CircularEngine object \code
SphericalHarmonic h(...); // Create the SphericalHarmonic object
double r = 2, lat = 33, lon0 = 44, dlon = 0.01;
double
phi = lat * Math::degree<double>(),
z = r * sin(phi), p = r * cos(phi);
for (int i = 0; i <= 100; ++i) {
real
lon = lon0 + i * dlon,
lam = lon * Math::degree<double>();
std::cout << lon << " " << h(p * cos(lam), p * sin(lam), z) << "\n";
}
\endcode
* Here is the same calculation done using a CircularEngine object. This
* will be about <i>N</i>/2 times faster. \code
SphericalHarmonic h(...); // Create the SphericalHarmonic object
double r = 2, lat = 33, lon0 = 44, dlon = 0.01;
double
phi = lat * Math::degree<double>(),
z = r * sin(phi), p = r * cos(phi);
CircularEngine c(h(p, z, false)); // Create the CircularEngine object
for (int i = 0; i <= 100; ++i) {
real
lon = lon0 + i * dlon;
std::cout << lon << " " << c(lon) << "\n";
}
\endcode
**********************************************************************/
CircularEngine Circle(real p, real z, bool gradp) const {
real f[] = {1};
switch (_norm) {
case FULL:
return gradp ?
SphericalEngine::Circle<true, SphericalEngine::FULL, 1>
(_c, f, p, z, _a) :
SphericalEngine::Circle<false, SphericalEngine::FULL, 1>
(_c, f, p, z, _a);
break;
case SCHMIDT:
default: // To avoid compiler warnings
return gradp ?
SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 1>
(_c, f, p, z, _a) :
SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 1>
(_c, f, p, z, _a);
break;
}
}
/**
* @return the zeroth SphericalEngine::coeff object.
**********************************************************************/
const SphericalEngine::coeff& Coefficients() const
{ return _c[0]; }
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_SPHERICALHARMONIC_HPP

283
external/include/GeographicLib/SphericalHarmonic1.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,283 @@
/**
* \file SphericalHarmonic1.hpp
* \brief Header for GeographicLib::SphericalHarmonic1 class
*
* Copyright (c) Charles Karney (2011) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP)
#define GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/SphericalEngine.hpp>
#include <GeographicLib/CircularEngine.hpp>
namespace GeographicLib {
/**
* \brief Spherical harmonic series with a correction to the coefficients
*
* This classes is similar to SphericalHarmonic, except that the coefficients
* <i>C</i><sub><i>nm</i></sub> are replaced by
* <i>C</i><sub><i>nm</i></sub> + \e tau <i>C'</i><sub><i>nm</i></sub> (and
* similarly for <i>S</i><sub><i>nm</i></sub>).
*
* Example of use:
* \include example-SphericalHarmonic1.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT SphericalHarmonic1 {
public:
/**
* Supported normalizations for associate Legendre polynomials.
**********************************************************************/
enum normalization {
/**
* Fully normalized associated Legendre polynomials. See
* SphericalHarmonic::FULL for documentation.
*
* @hideinitializer
**********************************************************************/
FULL = SphericalEngine::FULL,
/**
* Schmidt semi-normalized associated Legendre polynomials. See
* SphericalHarmonic::SCHMIDT for documentation.
*
* @hideinitializer
**********************************************************************/
SCHMIDT = SphericalEngine::SCHMIDT,
};
private:
typedef Math::real real;
SphericalEngine::coeff _c[2];
real _a;
unsigned _norm;
public:
/**
* Constructor with a full set of coefficients specified.
*
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the maximum degree and order of the sum
* @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the maximum degree and order of the correction
* coefficients <i>C'</i><sub><i>nm</i></sub> and
* <i>S'</i><sub><i>nm</i></sub>.
* @param[in] a the reference radius appearing in the definition of the
* sum.
* @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic1::FULL (the default) or
* SphericalHarmonic1::SCHMIDT.
* @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge;
* \e N1 &ge; &minus;1.
* @exception GeographicErr if any of the vectors of coefficients is not
* large enough.
*
* See SphericalHarmonic for the way the coefficients should be stored.
*
* The class stores <i>pointers</i> to the first elements of \e C, \e S, \e
* C', and \e S'. These arrays should not be altered or destroyed during
* the lifetime of a SphericalHarmonic object.
**********************************************************************/
SphericalHarmonic1(const std::vector<real>& C,
const std::vector<real>& S,
int N,
const std::vector<real>& C1,
const std::vector<real>& S1,
int N1,
real a, unsigned norm = FULL)
: _a(a)
, _norm(norm) {
if (!(N1 <= N))
throw GeographicErr("N1 cannot be larger that N");
_c[0] = SphericalEngine::coeff(C, S, N);
_c[1] = SphericalEngine::coeff(C1, S1, N1);
}
/**
* Constructor with a subset of coefficients specified.
*
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the degree used to determine the layout of \e C and \e S.
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is
* from 0 thru \e nmx.
* @param[in] mmx the maximum order used in the sum. The sum over \e m is
* from 0 thru min(\e n, \e mmx).
* @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the degree used to determine the layout of \e C' and \e
* S'.
* @param[in] nmx1 the maximum degree used for \e C' and \e S'.
* @param[in] mmx1 the maximum order used for \e C' and \e S'.
* @param[in] a the reference radius appearing in the definition of the
* sum.
* @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic1::FULL (the default) or
* SphericalHarmonic1::SCHMIDT.
* @exception GeographicErr if the parameters do not satisfy \e N &ge; \e
* nmx &ge; \e mmx &ge; &minus;1; \e N1 &ge; \e nmx1 &ge; \e mmx1 &ge;
* &minus;1; \e N &ge; \e N1; \e nmx &ge; \e nmx1; \e mmx &ge; \e mmx1.
* @exception GeographicErr if any of the vectors of coefficients is not
* large enough.
*
* The class stores <i>pointers</i> to the first elements of \e C, \e S, \e
* C', and \e S'. These arrays should not be altered or destroyed during
* the lifetime of a SphericalHarmonic object.
**********************************************************************/
SphericalHarmonic1(const std::vector<real>& C,
const std::vector<real>& S,
int N, int nmx, int mmx,
const std::vector<real>& C1,
const std::vector<real>& S1,
int N1, int nmx1, int mmx1,
real a, unsigned norm = FULL)
: _a(a)
, _norm(norm) {
if (!(nmx1 <= nmx))
throw GeographicErr("nmx1 cannot be larger that nmx");
if (!(mmx1 <= mmx))
throw GeographicErr("mmx1 cannot be larger that mmx");
_c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx);
_c[1] = SphericalEngine::coeff(C1, S1, N1, nmx1, mmx1);
}
/**
* A default constructor so that the object can be created when the
* constructor for another object is initialized. This default object can
* then be reset with the default copy assignment operator.
**********************************************************************/
SphericalHarmonic1() {}
/**
* Compute a spherical harmonic sum with a correction term.
*
* @param[in] tau multiplier for correction coefficients \e C' and \e S'.
* @param[in] x cartesian coordinate.
* @param[in] y cartesian coordinate.
* @param[in] z cartesian coordinate.
* @return \e V the spherical harmonic sum.
*
* This routine requires constant memory and thus never throws
* an exception.
**********************************************************************/
Math::real operator()(real tau, real x, real y, real z) const {
real f[] = {1, tau};
real v = 0;
real dummy;
switch (_norm) {
case FULL:
v = SphericalEngine::Value<false, SphericalEngine::FULL, 2>
(_c, f, x, y, z, _a, dummy, dummy, dummy);
break;
case SCHMIDT:
default: // To avoid compiler warnings
v = SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 2>
(_c, f, x, y, z, _a, dummy, dummy, dummy);
break;
}
return v;
}
/**
* Compute a spherical harmonic sum with a correction term and its
* gradient.
*
* @param[in] tau multiplier for correction coefficients \e C' and \e S'.
* @param[in] x cartesian coordinate.
* @param[in] y cartesian coordinate.
* @param[in] z cartesian coordinate.
* @param[out] gradx \e x component of the gradient
* @param[out] grady \e y component of the gradient
* @param[out] gradz \e z component of the gradient
* @return \e V the spherical harmonic sum.
*
* This is the same as the previous function, except that the components of
* the gradients of the sum in the \e x, \e y, and \e z directions are
* computed. This routine requires constant memory and thus never throws
* an exception.
**********************************************************************/
Math::real operator()(real tau, real x, real y, real z,
real& gradx, real& grady, real& gradz) const {
real f[] = {1, tau};
real v = 0;
switch (_norm) {
case FULL:
v = SphericalEngine::Value<true, SphericalEngine::FULL, 2>
(_c, f, x, y, z, _a, gradx, grady, gradz);
break;
case SCHMIDT:
default: // To avoid compiler warnings
v = SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 2>
(_c, f, x, y, z, _a, gradx, grady, gradz);
break;
}
return v;
}
/**
* Create a CircularEngine to allow the efficient evaluation of several
* points on a circle of latitude at a fixed value of \e tau.
*
* @param[in] tau the multiplier for the correction coefficients.
* @param[in] p the radius of the circle.
* @param[in] z the height of the circle above the equatorial plane.
* @param[in] gradp if true the returned object will be able to compute the
* gradient of the sum.
* @exception std::bad_alloc if the memory for the CircularEngine can't be
* allocated.
* @return the CircularEngine object.
*
* SphericalHarmonic1::operator()() exchanges the order of the sums in the
* definition, i.e., &sum;<sub><i>n</i> = 0..<i>N</i></sub>
* &sum;<sub><i>m</i> = 0..<i>n</i></sub> becomes &sum;<sub><i>m</i> =
* 0..<i>N</i></sub> &sum;<sub><i>n</i> = <i>m</i>..<i>N</i></sub>.
* SphericalHarmonic1::Circle performs the inner sum over degree \e n
* (which entails about <i>N</i><sup>2</sup> operations). Calling
* CircularEngine::operator()() on the returned object performs the outer
* sum over the order \e m (about \e N operations).
*
* See SphericalHarmonic::Circle for an example of its use.
**********************************************************************/
CircularEngine Circle(real tau, real p, real z, bool gradp) const {
real f[] = {1, tau};
switch (_norm) {
case FULL:
return gradp ?
SphericalEngine::Circle<true, SphericalEngine::FULL, 2>
(_c, f, p, z, _a) :
SphericalEngine::Circle<false, SphericalEngine::FULL, 2>
(_c, f, p, z, _a);
break;
case SCHMIDT:
default: // To avoid compiler warnings
return gradp ?
SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 2>
(_c, f, p, z, _a) :
SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 2>
(_c, f, p, z, _a);
break;
}
}
/**
* @return the zeroth SphericalEngine::coeff object.
**********************************************************************/
const SphericalEngine::coeff& Coefficients() const
{ return _c[0]; }
/**
* @return the first SphericalEngine::coeff object.
**********************************************************************/
const SphericalEngine::coeff& Coefficients1() const
{ return _c[1]; }
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP

320
external/include/GeographicLib/SphericalHarmonic2.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,320 @@
/**
* \file SphericalHarmonic2.hpp
* \brief Header for GeographicLib::SphericalHarmonic2 class
*
* Copyright (c) Charles Karney (2011-2012) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP)
#define GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP 1
#include <vector>
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/SphericalEngine.hpp>
#include <GeographicLib/CircularEngine.hpp>
namespace GeographicLib {
/**
* \brief Spherical harmonic series with two corrections to the coefficients
*
* This classes is similar to SphericalHarmonic, except that the coefficients
* <i>C</i><sub><i>nm</i></sub> are replaced by
* <i>C</i><sub><i>nm</i></sub> + \e tau' <i>C'</i><sub><i>nm</i></sub> + \e
* tau'' <i>C''</i><sub><i>nm</i></sub> (and similarly for
* <i>S</i><sub><i>nm</i></sub>).
*
* Example of use:
* \include example-SphericalHarmonic2.cpp
**********************************************************************/
// Don't include the GEOGRPAHIC_EXPORT because this header-only class isn't
// used by any other classes in the library.
class /*GEOGRAPHICLIB_EXPORT*/ SphericalHarmonic2 {
public:
/**
* Supported normalizations for associate Legendre polynomials.
**********************************************************************/
enum normalization {
/**
* Fully normalized associated Legendre polynomials. See
* SphericalHarmonic::FULL for documentation.
*
* @hideinitializer
**********************************************************************/
FULL = SphericalEngine::FULL,
/**
* Schmidt semi-normalized associated Legendre polynomials. See
* SphericalHarmonic::SCHMIDT for documentation.
*
* @hideinitializer
**********************************************************************/
SCHMIDT = SphericalEngine::SCHMIDT,
};
private:
typedef Math::real real;
SphericalEngine::coeff _c[3];
real _a;
unsigned _norm;
public:
/**
* Constructor with a full set of coefficients specified.
*
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the maximum degree and order of the sum
* @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the maximum degree and order of the first correction
* coefficients <i>C'</i><sub><i>nm</i></sub> and
* <i>S'</i><sub><i>nm</i></sub>.
* @param[in] C2 the coefficients <i>C''</i><sub><i>nm</i></sub>.
* @param[in] S2 the coefficients <i>S''</i><sub><i>nm</i></sub>.
* @param[in] N2 the maximum degree and order of the second correction
* coefficients <i>C'</i><sub><i>nm</i></sub> and
* <i>S'</i><sub><i>nm</i></sub>.
* @param[in] a the reference radius appearing in the definition of the
* sum.
* @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic2::FULL (the default) or
* SphericalHarmonic2::SCHMIDT.
* @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge;
* \e N1 &ge; &minus;1, and similarly for \e N2.
* @exception GeographicErr if any of the vectors of coefficients is not
* large enough.
*
* See SphericalHarmonic for the way the coefficients should be stored. \e
* N1 and \e N2 should satisfy \e N1 &le; \e N and \e N2 &le; \e N.
*
* The class stores <i>pointers</i> to the first elements of \e C, \e S, \e
* C', \e S', \e C'', and \e S''. These arrays should not be altered or
* destroyed during the lifetime of a SphericalHarmonic object.
**********************************************************************/
SphericalHarmonic2(const std::vector<real>& C,
const std::vector<real>& S,
int N,
const std::vector<real>& C1,
const std::vector<real>& S1,
int N1,
const std::vector<real>& C2,
const std::vector<real>& S2,
int N2,
real a, unsigned norm = FULL)
: _a(a)
, _norm(norm) {
if (!(N1 <= N && N2 <= N))
throw GeographicErr("N1 and N2 cannot be larger that N");
_c[0] = SphericalEngine::coeff(C, S, N);
_c[1] = SphericalEngine::coeff(C1, S1, N1);
_c[2] = SphericalEngine::coeff(C2, S2, N2);
}
/**
* Constructor with a subset of coefficients specified.
*
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the degree used to determine the layout of \e C and \e S.
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is
* from 0 thru \e nmx.
* @param[in] mmx the maximum order used in the sum. The sum over \e m is
* from 0 thru min(\e n, \e mmx).
* @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the degree used to determine the layout of \e C' and \e
* S'.
* @param[in] nmx1 the maximum degree used for \e C' and \e S'.
* @param[in] mmx1 the maximum order used for \e C' and \e S'.
* @param[in] C2 the coefficients <i>C''</i><sub><i>nm</i></sub>.
* @param[in] S2 the coefficients <i>S''</i><sub><i>nm</i></sub>.
* @param[in] N2 the degree used to determine the layout of \e C'' and \e
* S''.
* @param[in] nmx2 the maximum degree used for \e C'' and \e S''.
* @param[in] mmx2 the maximum order used for \e C'' and \e S''.
* @param[in] a the reference radius appearing in the definition of the
* sum.
* @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic2::FULL (the default) or
* SphericalHarmonic2::SCHMIDT.
* @exception GeographicErr if the parameters do not satisfy \e N &ge; \e
* nmx &ge; \e mmx &ge; &minus;1; \e N1 &ge; \e nmx1 &ge; \e mmx1 &ge;
* &minus;1; \e N &ge; \e N1; \e nmx &ge; \e nmx1; \e mmx &ge; \e mmx1;
* and similarly for \e N2, \e nmx2, and \e mmx2.
* @exception GeographicErr if any of the vectors of coefficients is not
* large enough.
*
* The class stores <i>pointers</i> to the first elements of \e C, \e S, \e
* C', \e S', \e C'', and \e S''. These arrays should not be altered or
* destroyed during the lifetime of a SphericalHarmonic object.
**********************************************************************/
SphericalHarmonic2(const std::vector<real>& C,
const std::vector<real>& S,
int N, int nmx, int mmx,
const std::vector<real>& C1,
const std::vector<real>& S1,
int N1, int nmx1, int mmx1,
const std::vector<real>& C2,
const std::vector<real>& S2,
int N2, int nmx2, int mmx2,
real a, unsigned norm = FULL)
: _a(a)
, _norm(norm) {
if (!(nmx1 <= nmx && nmx2 <= nmx))
throw GeographicErr("nmx1 and nmx2 cannot be larger that nmx");
if (!(mmx1 <= mmx && mmx2 <= mmx))
throw GeographicErr("mmx1 and mmx2 cannot be larger that mmx");
_c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx);
_c[1] = SphericalEngine::coeff(C1, S1, N1, nmx1, mmx1);
_c[2] = SphericalEngine::coeff(C2, S2, N2, nmx2, mmx2);
}
/**
* A default constructor so that the object can be created when the
* constructor for another object is initialized. This default object can
* then be reset with the default copy assignment operator.
**********************************************************************/
SphericalHarmonic2() {}
/**
* Compute a spherical harmonic sum with two correction terms.
*
* @param[in] tau1 multiplier for correction coefficients \e C' and \e S'.
* @param[in] tau2 multiplier for correction coefficients \e C'' and \e
* S''.
* @param[in] x cartesian coordinate.
* @param[in] y cartesian coordinate.
* @param[in] z cartesian coordinate.
* @return \e V the spherical harmonic sum.
*
* This routine requires constant memory and thus never throws an
* exception.
**********************************************************************/
Math::real operator()(real tau1, real tau2, real x, real y, real z)
const {
real f[] = {1, tau1, tau2};
real v = 0;
real dummy;
switch (_norm) {
case FULL:
v = SphericalEngine::Value<false, SphericalEngine::FULL, 3>
(_c, f, x, y, z, _a, dummy, dummy, dummy);
break;
case SCHMIDT:
default: // To avoid compiler warnings
v = SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 3>
(_c, f, x, y, z, _a, dummy, dummy, dummy);
break;
}
return v;
}
/**
* Compute a spherical harmonic sum with two correction terms and its
* gradient.
*
* @param[in] tau1 multiplier for correction coefficients \e C' and \e S'.
* @param[in] tau2 multiplier for correction coefficients \e C'' and \e
* S''.
* @param[in] x cartesian coordinate.
* @param[in] y cartesian coordinate.
* @param[in] z cartesian coordinate.
* @param[out] gradx \e x component of the gradient
* @param[out] grady \e y component of the gradient
* @param[out] gradz \e z component of the gradient
* @return \e V the spherical harmonic sum.
*
* This is the same as the previous function, except that the components of
* the gradients of the sum in the \e x, \e y, and \e z directions are
* computed. This routine requires constant memory and thus never throws
* an exception.
**********************************************************************/
Math::real operator()(real tau1, real tau2, real x, real y, real z,
real& gradx, real& grady, real& gradz) const {
real f[] = {1, tau1, tau2};
real v = 0;
switch (_norm) {
case FULL:
v = SphericalEngine::Value<true, SphericalEngine::FULL, 3>
(_c, f, x, y, z, _a, gradx, grady, gradz);
break;
case SCHMIDT:
default: // To avoid compiler warnings
v = SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 3>
(_c, f, x, y, z, _a, gradx, grady, gradz);
break;
}
return v;
}
/**
* Create a CircularEngine to allow the efficient evaluation of several
* points on a circle of latitude at fixed values of \e tau1 and \e tau2.
*
* @param[in] tau1 multiplier for correction coefficients \e C' and \e S'.
* @param[in] tau2 multiplier for correction coefficients \e C'' and \e
* S''.
* @param[in] p the radius of the circle.
* @param[in] z the height of the circle above the equatorial plane.
* @param[in] gradp if true the returned object will be able to compute the
* gradient of the sum.
* @exception std::bad_alloc if the memory for the CircularEngine can't be
* allocated.
* @return the CircularEngine object.
*
* SphericalHarmonic2::operator()() exchanges the order of the sums in the
* definition, i.e., &sum;<sub><i>n</i> = 0..<i>N</i></sub>
* &sum;<sub><i>m</i> = 0..<i>n</i></sub> becomes &sum;<sub><i>m</i> =
* 0..<i>N</i></sub> &sum;<sub><i>n</i> = <i>m</i>..<i>N</i></sub>..
* SphericalHarmonic2::Circle performs the inner sum over degree \e n
* (which entails about <i>N</i><sup>2</sup> operations). Calling
* CircularEngine::operator()() on the returned object performs the outer
* sum over the order \e m (about \e N operations).
*
* See SphericalHarmonic::Circle for an example of its use.
**********************************************************************/
CircularEngine Circle(real tau1, real tau2, real p, real z, bool gradp)
const {
real f[] = {1, tau1, tau2};
switch (_norm) {
case FULL:
return gradp ?
SphericalEngine::Circle<true, SphericalEngine::FULL, 3>
(_c, f, p, z, _a) :
SphericalEngine::Circle<false, SphericalEngine::FULL, 3>
(_c, f, p, z, _a);
break;
case SCHMIDT:
default: // To avoid compiler warnings
return gradp ?
SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 3>
(_c, f, p, z, _a) :
SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 3>
(_c, f, p, z, _a);
break;
}
}
/**
* @return the zeroth SphericalEngine::coeff object.
**********************************************************************/
const SphericalEngine::coeff& Coefficients() const
{ return _c[0]; }
/**
* @return the first SphericalEngine::coeff object.
**********************************************************************/
const SphericalEngine::coeff& Coefficients1() const
{ return _c[1]; }
/**
* @return the second SphericalEngine::coeff object.
**********************************************************************/
const SphericalEngine::coeff& Coefficients2() const
{ return _c[2]; }
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP

206
external/include/GeographicLib/TransverseMercator.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,206 @@
/**
* \file TransverseMercator.hpp
* \brief Header for GeographicLib::TransverseMercator class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP)
#define GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP 1
#include <GeographicLib/Constants.hpp>
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER)
/**
* The order of the series approximation used in TransverseMercator.
* GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER can be set to any integer in [4, 8].
**********************************************************************/
# define GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER \
(GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
(GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
#endif
namespace GeographicLib {
/**
* \brief Transverse Mercator projection
*
* This uses Kr&uuml;ger's method which evaluates the projection and its
* inverse in terms of a series. See
* - L. Kr&uuml;ger,
* <a href="https://doi.org/10.2312/GFZ.b103-krueger28"> Konforme
* Abbildung des Erdellipsoids in der Ebene</a> (Conformal mapping of the
* ellipsoidal earth to the plane), Royal Prussian Geodetic Institute, New
* Series 52, 172 pp. (1912).
* - C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-011-0445-3">
* Transverse Mercator with an accuracy of a few nanometers,</a>
* J. Geodesy 85(8), 475--485 (Aug. 2011);
* preprint
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>.
*
* Kr&uuml;ger's method has been extended from 4th to 6th order. The maximum
* error is 5 nm (5 nanometers), ground distance, for all positions within 35
* degrees of the central meridian. The error in the convergence is 2
* &times; 10<sup>&minus;15</sup>&quot; and the relative error in the scale
* is 6 &times; 10<sup>&minus;12</sup>%%. See Sec. 4 of
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for details.
* The speed penalty in going to 6th order is only about 1%.
*
* There's a singularity in the projection at &phi; = 0&deg;, &lambda;
* &minus; &lambda;<sub>0</sub> = &plusmn;(1 &minus; \e e)90&deg; (&asymp;
* &plusmn;82.6&deg; for the WGS84 ellipsoid), where \e e is the
* eccentricity. Beyond this point, the series ceases to converge and the
* results from this method will be garbage. To be on the safe side, don't
* use this method if the angular distance from the central meridian exceeds
* (1 &minus; 2e)90&deg; (&asymp; 75&deg; for the WGS84 ellipsoid)
*
* TransverseMercatorExact is an alternative implementation of the projection
* using exact formulas which yield accurate (to 8 nm) results over the
* entire ellipsoid.
*
* The ellipsoid parameters and the central scale are set in the constructor.
* The central meridian (which is a trivial shift of the longitude) is
* specified as the \e lon0 argument of the TransverseMercator::Forward and
* TransverseMercator::Reverse functions. The latitude of origin is taken to
* be the equator. There is no provision in this class for specifying a
* false easting or false northing or a different latitude of origin.
* However these are can be simply included by the calling function. For
* example, the UTMUPS class applies the false easting and false northing for
* the UTM projections. A more complicated example is the British National
* Grid (<a href="https://www.spatialreference.org/ref/epsg/7405/">
* EPSG:7405</a>) which requires the use of a latitude of origin. This is
* implemented by the GeographicLib::OSGB class.
*
* This class also returns the meridian convergence \e gamma and scale \e k.
* The meridian convergence is the bearing of grid north (the \e y axis)
* measured clockwise from true north.
*
* See TransverseMercator.cpp for more information on the implementation.
*
* See \ref transversemercator for a discussion of this projection.
*
* Example of use:
* \include example-TransverseMercator.cpp
*
* <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
* command-line utility providing access to the functionality of
* TransverseMercator and TransverseMercatorExact.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT TransverseMercator {
private:
typedef Math::real real;
static const int maxpow_ = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER;
static const int numit_ = 5;
real _a, _f, _k0, _e2, _es, _e2m, _c, _n;
// _alp[0] and _bet[0] unused
real _a1, _b1, _alp[maxpow_ + 1], _bet[maxpow_ + 1];
friend class Ellipsoid; // For access to taupf, tauf.
public:
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
* @param[in] k0 central scale factor.
* @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive.
**********************************************************************/
TransverseMercator(real a, real f, real k0);
/**
* Forward projection, from geographic to transverse Mercator.
*
* @param[in] lon0 central meridian of the projection (degrees).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* No false easting or northing is added. \e lat should be in the range
* [&minus;90&deg;, 90&deg;].
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y, real& gamma, real& k) const;
/**
* Reverse projection, from transverse Mercator to geographic.
*
* @param[in] lon0 central meridian of the projection (degrees).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* No false easting or northing is added. The value of \e lon returned is
* in the range [&minus;180&deg;, 180&deg;].
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon, real& gamma, real& k) const;
/**
* TransverseMercator::Forward without returning the convergence and scale.
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y) const {
real gamma, k;
Forward(lon0, lat, lon, x, y, gamma, k);
}
/**
* TransverseMercator::Reverse without returning the convergence and scale.
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon) const {
real gamma, k;
Reverse(lon0, x, y, lat, lon, gamma, k);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the value used in
* the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return \e k0 central scale for the projection. This is the value of \e
* k0 used in the constructor and is the scale on the central meridian.
**********************************************************************/
Math::real CentralScale() const { return _k0; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of TransverseMercator with the WGS84 ellipsoid
* and the UTM scale factor. However, unlike UTM, no false easting or
* northing is added.
**********************************************************************/
static const TransverseMercator& UTM();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP

مشاهده پرونده

@@ -0,0 +1,264 @@
/**
* \file TransverseMercatorExact.hpp
* \brief Header for GeographicLib::TransverseMercatorExact class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP)
#define GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP 1
#include <GeographicLib/Constants.hpp>
#include <GeographicLib/EllipticFunction.hpp>
namespace GeographicLib {
/**
* \brief An exact implementation of the transverse Mercator projection
*
* Implementation of the Transverse Mercator Projection given in
* - L. P. Lee,
* <a href="https://doi.org/10.3138/X687-1574-4325-WM62"> Conformal
* Projections Based On Jacobian Elliptic Functions</a>, Part V of
* Conformal Projections Based on Elliptic Functions,
* (B. V. Gutsell, Toronto, 1976), 128pp.,
* ISBN: 0919870163
* (also appeared as:
* Monograph 16, Suppl. No. 1 to Canadian Cartographer, Vol 13).
* - C. F. F. Karney,
* <a href="https://doi.org/10.1007/s00190-011-0445-3">
* Transverse Mercator with an accuracy of a few nanometers,</a>
* J. Geodesy 85(8), 475--485 (Aug. 2011);
* preprint
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>.
*
* Lee gives the correct results for forward and reverse transformations
* subject to the branch cut rules (see the description of the \e extendp
* argument to the constructor). The maximum error is about 8 nm (8
* nanometers), ground distance, for the forward and reverse transformations.
* The error in the convergence is 2 &times; 10<sup>&minus;15</sup>&quot;,
* the relative error in the scale is 7 &times; 10<sup>&minus;12</sup>%%.
* See Sec. 3 of
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for details.
* The method is "exact" in the sense that the errors are close to the
* round-off limit and that no changes are needed in the algorithms for them
* to be used with reals of a higher precision. Thus the errors using long
* double (with a 64-bit fraction) are about 2000 times smaller than using
* double (with a 53-bit fraction).
*
* This algorithm is about 4.5 times slower than the 6th-order Kr&uuml;ger
* method, TransverseMercator, taking about 11 us for a combined forward and
* reverse projection on a 2.66 GHz Intel machine (g++, version 4.3.0, -O3).
*
* The ellipsoid parameters and the central scale are set in the constructor.
* The central meridian (which is a trivial shift of the longitude) is
* specified as the \e lon0 argument of the TransverseMercatorExact::Forward
* and TransverseMercatorExact::Reverse functions. The latitude of origin is
* taken to be the equator. See the documentation on TransverseMercator for
* how to include a false easting, false northing, or a latitude of origin.
*
* See <a href="https://geographiclib.sourceforge.io/tm-grid.kmz"
* type="application/vnd.google-earth.kmz"> tm-grid.kmz</a>, for an
* illustration of the transverse Mercator grid in Google Earth.
*
* This class also returns the meridian convergence \e gamma and scale \e k.
* The meridian convergence is the bearing of grid north (the \e y axis)
* measured clockwise from true north.
*
* See TransverseMercatorExact.cpp for more information on the
* implementation.
*
* See \ref transversemercator for a discussion of this projection.
*
* Example of use:
* \include example-TransverseMercatorExact.cpp
*
* <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
* command-line utility providing access to the functionality of
* TransverseMercator and TransverseMercatorExact.
**********************************************************************/
class GEOGRAPHICLIB_EXPORT TransverseMercatorExact {
private:
typedef Math::real real;
static const int numit_ = 10;
real tol_, tol2_, taytol_;
real _a, _f, _k0, _mu, _mv, _e;
bool _extendp;
EllipticFunction _Eu, _Ev;
void zeta(real u, real snu, real cnu, real dnu,
real v, real snv, real cnv, real dnv,
real& taup, real& lam) const;
void dwdzeta(real u, real snu, real cnu, real dnu,
real v, real snv, real cnv, real dnv,
real& du, real& dv) const;
bool zetainv0(real psi, real lam, real& u, real& v) const;
void zetainv(real taup, real lam, real& u, real& v) const;
void sigma(real u, real snu, real cnu, real dnu,
real v, real snv, real cnv, real dnv,
real& xi, real& eta) const;
void dwdsigma(real u, real snu, real cnu, real dnu,
real v, real snv, real cnv, real dnv,
real& du, real& dv) const;
bool sigmainv0(real xi, real eta, real& u, real& v) const;
void sigmainv(real xi, real eta, real& u, real& v) const;
void Scale(real tau, real lam,
real snu, real cnu, real dnu,
real snv, real cnv, real dnv,
real& gamma, real& k) const;
public:
/**
* Constructor for a ellipsoid with
*
* @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid.
* @param[in] k0 central scale factor.
* @param[in] extendp use extended domain.
* @exception GeographicErr if \e a, \e f, or \e k0 is not positive.
*
* The transverse Mercator projection has a branch point singularity at \e
* lat = 0 and \e lon &minus; \e lon0 = 90 (1 &minus; \e e) or (for
* TransverseMercatorExact::UTM) x = 18381 km, y = 0m. The \e extendp
* argument governs where the branch cut is placed. With \e extendp =
* false, the "standard" convention is followed, namely the cut is placed
* along \e x > 18381 km, \e y = 0m. Forward can be called with any \e lat
* and \e lon then produces the transformation shown in Lee, Fig 46.
* Reverse analytically continues this in the &plusmn; \e x direction. As
* a consequence, Reverse may map multiple points to the same geographic
* location; for example, for TransverseMercatorExact::UTM, \e x =
* 22051449.037349 m, \e y = &minus;7131237.022729 m and \e x =
* 29735142.378357 m, \e y = 4235043.607933 m both map to \e lat =
* &minus;2&deg;, \e lon = 88&deg;.
*
* With \e extendp = true, the branch cut is moved to the lower left
* quadrant. The various symmetries of the transverse Mercator projection
* can be used to explore the projection on any sheet. In this mode the
* domains of \e lat, \e lon, \e x, and \e y are restricted to
* - the union of
* - \e lat in [0, 90] and \e lon &minus; \e lon0 in [0, 90]
* - \e lat in (-90, 0] and \e lon &minus; \e lon0 in [90 (1 &minus; \e
e), 90]
* - the union of
* - <i>x</i>/(\e k0 \e a) in [0, &infin;) and
* <i>y</i>/(\e k0 \e a) in [0, E(<i>e</i><sup>2</sup>)]
* - <i>x</i>/(\e k0 \e a) in [K(1 &minus; <i>e</i><sup>2</sup>) &minus;
* E(1 &minus; <i>e</i><sup>2</sup>), &infin;) and <i>y</i>/(\e k0 \e
* a) in (&minus;&infin;, 0]
* .
* See Sec. 5 of
* <a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a> for a full
* discussion of the treatment of the branch cut.
*
* The method will work for all ellipsoids used in terrestrial geodesy.
* The method cannot be applied directly to the case of a sphere (\e f = 0)
* because some the constants characterizing this method diverge in that
* limit, and in practice, \e f should be larger than about
* numeric_limits<real>::epsilon(). However, TransverseMercator treats the
* sphere exactly.
**********************************************************************/
TransverseMercatorExact(real a, real f, real k0, bool extendp = false);
/**
* Forward projection, from geographic to transverse Mercator.
*
* @param[in] lon0 central meridian of the projection (degrees).
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* No false easting or northing is added. \e lat should be in the range
* [&minus;90&deg;, 90&deg;].
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y, real& gamma, real& k) const;
/**
* Reverse projection, from transverse Mercator to geographic.
*
* @param[in] lon0 central meridian of the projection (degrees).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
*
* No false easting or northing is added. The value of \e lon returned is
* in the range [&minus;180&deg;, 180&deg;].
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon, real& gamma, real& k) const;
/**
* TransverseMercatorExact::Forward without returning the convergence and
* scale.
**********************************************************************/
void Forward(real lon0, real lat, real lon,
real& x, real& y) const {
real gamma, k;
Forward(lon0, lat, lon, x, y, gamma, k);
}
/**
* TransverseMercatorExact::Reverse without returning the convergence and
* scale.
**********************************************************************/
void Reverse(real lon0, real x, real y,
real& lat, real& lon) const {
real gamma, k;
Reverse(lon0, x, y, lat, lon, gamma, k);
}
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor.
**********************************************************************/
Math::real EquatorialRadius() const { return _a; }
/**
* @return \e f the flattening of the ellipsoid. This is the value used in
* the constructor.
**********************************************************************/
Math::real Flattening() const { return _f; }
/**
* @return \e k0 central scale for the projection. This is the value of \e
* k0 used in the constructor and is the scale on the central meridian.
**********************************************************************/
Math::real CentralScale() const { return _k0; }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
Math::real MajorRadius() const { return EquatorialRadius(); }
///@}
/**
* A global instantiation of TransverseMercatorExact with the WGS84
* ellipsoid and the UTM scale factor. However, unlike UTM, no false
* easting or northing is added.
**********************************************************************/
static const TransverseMercatorExact& UTM();
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP

428
external/include/GeographicLib/UTMUPS.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,428 @@
/**
* \file UTMUPS.hpp
* \brief Header for GeographicLib::UTMUPS class
*
* Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_UTMUPS_HPP)
#define GEOGRAPHICLIB_UTMUPS_HPP 1
#include <GeographicLib/Constants.hpp>
namespace GeographicLib {
/**
* \brief Convert between geographic coordinates and UTM/UPS
*
* UTM and UPS are defined
* - J. W. Hager, J. F. Behensky, and B. W. Drew,
* <a href="https://web.archive.org/web/20161214054445/http://earth-info.nga.mil/GandG/publications/tm8358.2/TM8358_2.pdf">
* The Universal Grids: Universal Transverse Mercator (UTM) and Universal
* Polar Stereographic (UPS)</a>, Defense Mapping Agency, Technical Manual
* TM8358.2 (1989).
* .
* Section 2-3 defines UTM and section 3-2.4 defines UPS. This document also
* includes approximate algorithms for the computation of the underlying
* transverse Mercator and polar stereographic projections. Here we
* substitute much more accurate algorithms given by
* GeographicLib:TransverseMercator and GeographicLib:PolarStereographic.
* These are the algorithms recommended by the NGA document
* - <a href="https://earth-info.nga.mil/php/download.php?file=coord-utmups">
* The Universal Grids and the Transverse Mercator and Polar Stereographic
* Map Projections</a>, NGA.SIG.0012 (2014).
*
* In this implementation, the conversions are closed, i.e., output from
* Forward is legal input for Reverse and vice versa. The error is about 5nm
* in each direction. However, the conversion from legal UTM/UPS coordinates
* to geographic coordinates and back might throw an error if the initial
* point is within 5nm of the edge of the allowed range for the UTM/UPS
* coordinates.
*
* The simplest way to guarantee the closed property is to define allowed
* ranges for the eastings and northings for UTM and UPS coordinates. The
* UTM boundaries are the same for all zones. (The only place the
* exceptional nature of the zone boundaries is evident is when converting to
* UTM/UPS coordinates requesting the standard zone.) The MGRS lettering
* scheme imposes natural limits on UTM/UPS coordinates which may be
* converted into MGRS coordinates. For the conversion to/from geographic
* coordinates these ranges have been extended by 100km in order to provide a
* generous overlap between UTM and UPS and between UTM zones.
*
* The <a href="http://www.nga.mil">NGA</a> software package
* <a href="https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_geotrans">geotrans</a>
* also provides conversions to and from UTM and UPS. Version 2.4.2 (and
* earlier) suffers from some drawbacks:
* - Inconsistent rules are used to determine the whether a particular UTM or
* UPS coordinate is legal. A more systematic approach is taken here.
* - The underlying projections are not very accurately implemented.
*
* The GeographicLib::UTMUPS::EncodeZone encodes the UTM zone and hemisphere
* to allow UTM/UPS coordinated to be displayed as, for example, "38N 444500
* 3688500". According to NGA.SIG.0012_2.0.0_UTMUPS the use of "N" to denote
* "north" in the context is not allowed (since a upper case letter in this
* context denotes the MGRS latitude band). Consequently, as of version
* 1.36, EncodeZone uses the lower case letters "n" and "s" to denote the
* hemisphere. In addition EncodeZone accepts an optional final argument \e
* abbrev, which, if false, results in the hemisphere being spelled out as in
* "38north".
*
* Example of use:
* \include example-UTMUPS.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT UTMUPS {
private:
typedef Math::real real;
static const int falseeasting_[4];
static const int falsenorthing_[4];
static const int mineasting_[4];
static const int maxeasting_[4];
static const int minnorthing_[4];
static const int maxnorthing_[4];
static const int epsg01N = 32601; // EPSG code for UTM 01N
static const int epsg60N = 32660; // EPSG code for UTM 60N
static const int epsgN = 32661; // EPSG code for UPS N
static const int epsg01S = 32701; // EPSG code for UTM 01S
static const int epsg60S = 32760; // EPSG code for UTM 60S
static const int epsgS = 32761; // EPSG code for UPS S
static real CentralMeridian(int zone)
{ return real(6 * zone - 183); }
// Throw an error if easting or northing are outside standard ranges. If
// throwp = false, return bool instead.
static bool CheckCoords(bool utmp, bool northp, real x, real y,
bool msgrlimits = false, bool throwp = true);
UTMUPS(); // Disable constructor
public:
/**
* In this class we bring together the UTM and UPS coordinates systems.
* The UTM divides the earth between latitudes &minus;80&deg; and 84&deg;
* into 60 zones numbered 1 thru 60. Zone assign zone number 0 to the UPS
* regions, covering the two poles. Within UTMUPS, non-negative zone
* numbers refer to one of the "physical" zones, 0 for UPS and [1, 60] for
* UTM. Negative "pseudo-zone" numbers are used to select one of the
* physical zones.
**********************************************************************/
enum zonespec {
/**
* The smallest pseudo-zone number.
**********************************************************************/
MINPSEUDOZONE = -4,
/**
* A marker for an undefined or invalid zone. Equivalent to NaN.
**********************************************************************/
INVALID = -4,
/**
* If a coordinate already include zone information (e.g., it is an MGRS
* coordinate), use that, otherwise apply the UTMUPS::STANDARD rules.
**********************************************************************/
MATCH = -3,
/**
* Apply the standard rules for UTM zone assigment extending the UTM zone
* to each pole to give a zone number in [1, 60]. For example, use UTM
* zone 38 for longitude in [42&deg;, 48&deg;). The rules include the
* Norway and Svalbard exceptions.
**********************************************************************/
UTM = -2,
/**
* Apply the standard rules for zone assignment to give a zone number in
* [0, 60]. If the latitude is not in [&minus;80&deg;, 84&deg;), then
* use UTMUPS::UPS = 0, otherwise apply the rules for UTMUPS::UTM. The
* tests on latitudes and longitudes are all closed on the lower end open
* on the upper. Thus for UTM zone 38, latitude is in [&minus;80&deg;,
* 84&deg;) and longitude is in [42&deg;, 48&deg;).
**********************************************************************/
STANDARD = -1,
/**
* The largest pseudo-zone number.
**********************************************************************/
MAXPSEUDOZONE = -1,
/**
* The smallest physical zone number.
**********************************************************************/
MINZONE = 0,
/**
* The zone number used for UPS
**********************************************************************/
UPS = 0,
/**
* The smallest UTM zone number.
**********************************************************************/
MINUTMZONE = 1,
/**
* The largest UTM zone number.
**********************************************************************/
MAXUTMZONE = 60,
/**
* The largest physical zone number.
**********************************************************************/
MAXZONE = 60,
};
/**
* The standard zone.
*
* @param[in] lat latitude (degrees).
* @param[in] lon longitude (degrees).
* @param[in] setzone zone override (optional). If omitted, use the
* standard rules for picking the zone. If \e setzone is given then use
* that zone if it is non-negative, otherwise apply the rules given in
* UTMUPS::zonespec.
* @exception GeographicErr if \e setzone is outside the range
* [UTMUPS::MINPSEUDOZONE, UTMUPS::MAXZONE] = [&minus;4, 60].
*
* This is exact.
**********************************************************************/
static int StandardZone(real lat, real lon, int setzone = STANDARD);
/**
* Forward projection, from geographic to UTM/UPS.
*
* @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees).
* @param[out] zone the UTM zone (zero means UPS).
* @param[out] northp hemisphere (true means north, false means south).
* @param[out] x easting of point (meters).
* @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
* @param[in] setzone zone override (optional).
* @param[in] mgrslimits if true enforce the stricter MGRS limits on the
* coordinates (default = false).
* @exception GeographicErr if \e lat is not in [&minus;90&deg;,
* 90&deg;].
* @exception GeographicErr if the resulting \e x or \e y is out of allowed
* range (see Reverse); in this case, these arguments are unchanged.
*
* If \e setzone is omitted, use the standard rules for picking the zone.
* If \e setzone is given then use that zone if it is non-negative,
* otherwise apply the rules given in UTMUPS::zonespec. The accuracy of
* the conversion is about 5nm.
*
* The northing \e y jumps by UTMUPS::UTMShift() when crossing the equator
* in the southerly direction. Sometimes it is useful to remove this
* discontinuity in \e y by extending the "northern" hemisphere using
* UTMUPS::Transfer:
* \code
double lat = -1, lon = 123;
int zone;
bool northp;
double x, y, gamma, k;
GeographicLib::UTMUPS::Forward(lat, lon, zone, northp, x, y, gamma, k);
GeographicLib::UTMUPS::Transfer(zone, northp, x, y,
zone, true, x, y, zone);
northp = true;
\endcode
**********************************************************************/
static void Forward(real lat, real lon,
int& zone, bool& northp, real& x, real& y,
real& gamma, real& k,
int setzone = STANDARD, bool mgrslimits = false);
/**
* Reverse projection, from UTM/UPS to geographic.
*
* @param[in] zone the UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @param[in] x easting of point (meters).
* @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees).
* @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point.
* @param[in] mgrslimits if true enforce the stricter MGRS limits on the
* coordinates (default = false).
* @exception GeographicErr if \e zone, \e x, or \e y is out of allowed
* range; this this case the arguments are unchanged.
*
* The accuracy of the conversion is about 5nm.
*
* UTM eastings are allowed to be in the range [0km, 1000km], northings are
* allowed to be in in [0km, 9600km] for the northern hemisphere and in
* [900km, 10000km] for the southern hemisphere. However UTM northings
* can be continued across the equator. So the actual limits on the
* northings are [-9100km, 9600km] for the "northern" hemisphere and
* [900km, 19600km] for the "southern" hemisphere.
*
* UPS eastings and northings are allowed to be in the range [1200km,
* 2800km] in the northern hemisphere and in [700km, 3300km] in the
* southern hemisphere.
*
* These ranges are 100km larger than allowed for the conversions to MGRS.
* (100km is the maximum extra padding consistent with eastings remaining
* non-negative.) This allows generous overlaps between zones and UTM and
* UPS. If \e mgrslimits = true, then all the ranges are shrunk by 100km
* so that they agree with the stricter MGRS ranges. No checks are
* performed besides these (e.g., to limit the distance outside the
* standard zone boundaries).
**********************************************************************/
static void Reverse(int zone, bool northp, real x, real y,
real& lat, real& lon, real& gamma, real& k,
bool mgrslimits = false);
/**
* UTMUPS::Forward without returning convergence and scale.
**********************************************************************/
static void Forward(real lat, real lon,
int& zone, bool& northp, real& x, real& y,
int setzone = STANDARD, bool mgrslimits = false) {
real gamma, k;
Forward(lat, lon, zone, northp, x, y, gamma, k, setzone, mgrslimits);
}
/**
* UTMUPS::Reverse without returning convergence and scale.
**********************************************************************/
static void Reverse(int zone, bool northp, real x, real y,
real& lat, real& lon, bool mgrslimits = false) {
real gamma, k;
Reverse(zone, northp, x, y, lat, lon, gamma, k, mgrslimits);
}
/**
* Transfer UTM/UPS coordinated from one zone to another.
*
* @param[in] zonein the UTM zone for \e xin and \e yin (or zero for UPS).
* @param[in] northpin hemisphere for \e xin and \e yin (true means north,
* false means south).
* @param[in] xin easting of point (meters) in \e zonein.
* @param[in] yin northing of point (meters) in \e zonein.
* @param[in] zoneout the requested UTM zone for \e xout and \e yout (or
* zero for UPS).
* @param[in] northpout hemisphere for \e xout output and \e yout.
* @param[out] xout easting of point (meters) in \e zoneout.
* @param[out] yout northing of point (meters) in \e zoneout.
* @param[out] zone the actual UTM zone for \e xout and \e yout (or zero
* for UPS); this equals \e zoneout if \e zoneout &ge; 0.
* @exception GeographicErr if \e zonein is out of range (see below).
* @exception GeographicErr if \e zoneout is out of range (see below).
* @exception GeographicErr if \e xin or \e yin fall outside their allowed
* ranges (see UTMUPS::Reverse).
* @exception GeographicErr if \e xout or \e yout fall outside their
* allowed ranges (see UTMUPS::Reverse).
*
* \e zonein must be in the range [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0,
* 60] with \e zonein = UTMUPS::UPS, 0, indicating UPS. \e zonein may
* also be UTMUPS::INVALID.
*
* \e zoneout must be in the range [UTMUPS::MINPSEUDOZONE, UTMUPS::MAXZONE]
* = [-4, 60]. If \e zoneout &lt; UTMUPS::MINZONE then the rules give in
* the documentation of UTMUPS::zonespec are applied, and \e zone is set to
* the actual zone used for output.
*
* (\e xout, \e yout) can overlap with (\e xin, \e yin).
**********************************************************************/
static void Transfer(int zonein, bool northpin, real xin, real yin,
int zoneout, bool northpout, real& xout, real& yout,
int& zone);
/**
* Decode a UTM/UPS zone string.
*
* @param[in] zonestr string representation of zone and hemisphere.
* @param[out] zone the UTM zone (zero means UPS).
* @param[out] northp hemisphere (true means north, false means south).
* @exception GeographicErr if \e zonestr is malformed.
*
* For UTM, \e zonestr has the form of a zone number in the range
* [UTMUPS::MINUTMZONE, UTMUPS::MAXUTMZONE] = [1, 60] followed by a
* hemisphere letter, n or s (or "north" or "south" spelled out). For UPS,
* it consists just of the hemisphere letter (or the spelled out
* hemisphere). The returned value of \e zone is UTMUPS::UPS = 0 for UPS.
* Note well that "38s" indicates the southern hemisphere of zone 38 and
* not latitude band S, 32&deg; &le; \e lat &lt; 40&deg;. n, 01s, 2n, 38s,
* south, 3north are legal. 0n, 001s, +3n, 61n, 38P are illegal. INV is a
* special value for which the returned value of \e is UTMUPS::INVALID.
**********************************************************************/
static void DecodeZone(const std::string& zonestr,
int& zone, bool& northp);
/**
* Encode a UTM/UPS zone string.
*
* @param[in] zone the UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @param[in] abbrev if true (the default) use abbreviated (n/s) notation
* for hemisphere; otherwise spell out the hemisphere (north/south)
* @exception GeographicErr if \e zone is out of range (see below).
* @exception std::bad_alloc if memoy for the string can't be allocated.
* @return string representation of zone and hemisphere.
*
* \e zone must be in the range [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0,
* 60] with \e zone = UTMUPS::UPS, 0, indicating UPS (but the resulting
* string does not contain "0"). \e zone may also be UTMUPS::INVALID, in
* which case the returned string is "inv". This reverses
* UTMUPS::DecodeZone.
**********************************************************************/
static std::string EncodeZone(int zone, bool northp, bool abbrev = true);
/**
* Decode EPSG.
*
* @param[in] epsg the EPSG code.
* @param[out] zone the UTM zone (zero means UPS).
* @param[out] northp hemisphere (true means north, false means south).
*
* EPSG (European Petroleum Survery Group) codes are a way to refer to many
* different projections. DecodeEPSG decodes those referring to UTM or UPS
* projections for the WGS84 ellipsoid. If the code does not refer to one
* of these projections, \e zone is set to UTMUPS::INVALID. See
* https://www.spatialreference.org/ref/epsg/
**********************************************************************/
static void DecodeEPSG(int epsg, int& zone, bool& northp);
/**
* Encode zone as EPSG.
*
* @param[in] zone the UTM zone (zero means UPS).
* @param[in] northp hemisphere (true means north, false means south).
* @return EPSG code (or -1 if \e zone is not in the range
* [UTMUPS::MINZONE, UTMUPS::MAXZONE] = [0, 60])
*
* Convert \e zone and \e northp to the corresponding EPSG (European
* Petroleum Survery Group) codes
**********************************************************************/
static int EncodeEPSG(int zone, bool northp);
/**
* @return shift (meters) necessary to align north and south halves of a
* UTM zone (10<sup>7</sup>).
**********************************************************************/
static Math::real UTMShift();
/** \name Inspector functions
**********************************************************************/
///@{
/**
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
*
* (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.)
**********************************************************************/
static Math::real EquatorialRadius()
{ return Constants::WGS84_a(); }
/**
* @return \e f the flattening of the WGS84 ellipsoid.
*
* (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.)
**********************************************************************/
static Math::real Flattening()
{ return Constants::WGS84_f(); }
/**
* \deprecated An old name for EquatorialRadius().
**********************************************************************/
GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
static Math::real MajorRadius() { return EquatorialRadius(); }
///@}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_UTMUPS_HPP

733
external/include/GeographicLib/Utility.hpp فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,733 @@
/**
* \file Utility.hpp
* \brief Header for GeographicLib::Utility class
*
* Copyright (c) Charles Karney (2011-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_UTILITY_HPP)
#define GEOGRAPHICLIB_UTILITY_HPP 1
#include <GeographicLib/Constants.hpp>
#include <iomanip>
#include <vector>
#include <sstream>
#include <cctype>
#include <ctime>
#include <cstring>
#if defined(_MSC_VER)
// Squelch warnings about constant conditional expressions and unsafe gmtime
# pragma warning (push)
# pragma warning (disable: 4127 4996)
#endif
namespace GeographicLib {
/**
* \brief Some utility routines for %GeographicLib
*
* Example of use:
* \include example-Utility.cpp
**********************************************************************/
class GEOGRAPHICLIB_EXPORT Utility {
private:
static bool gregorian(int y, int m, int d) {
// The original cut over to the Gregorian calendar in Pope Gregory XIII's
// time had 1582-10-04 followed by 1582-10-15. Here we implement the
// switch over used by the English-speaking world where 1752-09-02 was
// followed by 1752-09-14. We also assume that the year always begins
// with January 1, whereas in reality it often was reckoned to begin in
// March.
return 100 * (100 * y + m) + d >= 17520914; // or 15821015
}
static bool gregorian(int s) {
return s >= 639799; // 1752-09-14
}
public:
/**
* Convert a date to the day numbering sequentially starting with
* 0001-01-01 as day 1.
*
* @param[in] y the year (must be positive).
* @param[in] m the month, Jan = 1, etc. (must be positive). Default = 1.
* @param[in] d the day of the month (must be positive). Default = 1.
* @return the sequential day number.
**********************************************************************/
static int day(int y, int m = 1, int d = 1) {
// Convert from date to sequential day and vice versa
//
// Here is some code to convert a date to sequential day and vice
// versa. The sequential day is numbered so that January 1, 1 AD is day 1
// (a Saturday). So this is offset from the "Julian" day which starts the
// numbering with 4713 BC.
//
// This is inspired by a talk by John Conway at the John von Neumann
// National Supercomputer Center when he described his Doomsday algorithm
// for figuring the day of the week. The code avoids explicitly doing ifs
// (except for the decision of whether to use the Julian or Gregorian
// calendar). Instead the equivalent result is achieved using integer
// arithmetic. I got this idea from the routine for the day of the week
// in MACLisp (I believe that that routine was written by Guy Steele).
//
// There are three issues to take care of
//
// 1. the rules for leap years,
// 2. the inconvenient placement of leap days at the end of February,
// 3. the irregular pattern of month lengths.
//
// We deal with these as follows:
//
// 1. Leap years are given by simple rules which are straightforward to
// accommodate.
//
// 2. We simplify the calculations by moving January and February to the
// previous year. Here we internally number the months MarchDecember,
// January, February as 09, 10, 11.
//
// 3. The pattern of month lengths from March through January is regular
// with a 5-month period—31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31. The
// 5-month period is 153 days long. Since February is now at the end of
// the year, we don't need to include its length in this part of the
// calculation.
bool greg = gregorian(y, m, d);
y += (m + 9) / 12 - 1; // Move Jan and Feb to previous year,
m = (m + 9) % 12; // making March month 0.
return
(1461 * y) / 4 // Julian years converted to days. Julian year is 365 +
// 1/4 = 1461/4 days.
// Gregorian leap year corrections. The 2 offset with respect to the
// Julian calendar synchronizes the vernal equinox with that at the
// time of the Council of Nicea (325 AD).
+ (greg ? (y / 100) / 4 - (y / 100) + 2 : 0)
+ (153 * m + 2) / 5 // The zero-based start of the m'th month
+ d - 1 // The zero-based day
- 305; // The number of days between March 1 and December 31.
// This makes 0001-01-01 day 1
}
/**
* Convert a date to the day numbering sequentially starting with
* 0001-01-01 as day 1.
*
* @param[in] y the year (must be positive).
* @param[in] m the month, Jan = 1, etc. (must be positive). Default = 1.
* @param[in] d the day of the month (must be positive). Default = 1.
* @param[in] check whether to check the date.
* @exception GeographicErr if the date is invalid and \e check is true.
* @return the sequential day number.
**********************************************************************/
static int day(int y, int m, int d, bool check) {
int s = day(y, m, d);
if (!check)
return s;
int y1, m1, d1;
date(s, y1, m1, d1);
if (!(s > 0 && y == y1 && m == m1 && d == d1))
throw GeographicErr("Invalid date " +
str(y) + "-" + str(m) + "-" + str(d)
+ (s > 0 ? "; use " +
str(y1) + "-" + str(m1) + "-" + str(d1) :
" before 0001-01-01"));
return s;
}
/**
* Given a day (counting from 0001-01-01 as day 1), return the date.
*
* @param[in] s the sequential day number (must be positive)
* @param[out] y the year.
* @param[out] m the month, Jan = 1, etc.
* @param[out] d the day of the month.
**********************************************************************/
static void date(int s, int& y, int& m, int& d) {
int c = 0;
bool greg = gregorian(s);
s += 305; // s = 0 on March 1, 1BC
if (greg) {
s -= 2; // The 2 day Gregorian offset
// Determine century with the Gregorian rules for leap years. The
// Gregorian year is 365 + 1/4 - 1/100 + 1/400 = 146097/400 days.
c = (4 * s + 3) / 146097;
s -= (c * 146097) / 4; // s = 0 at beginning of century
}
y = (4 * s + 3) / 1461; // Determine the year using Julian rules.
s -= (1461 * y) / 4; // s = 0 at start of year, i.e., March 1
y += c * 100; // Assemble full year
m = (5 * s + 2) / 153; // Determine the month
s -= (153 * m + 2) / 5; // s = 0 at beginning of month
d = s + 1; // Determine day of month
y += (m + 2) / 12; // Move Jan and Feb back to original year
m = (m + 2) % 12 + 1; // Renumber the months so January = 1
}
/**
* Given a date as a string in the format yyyy, yyyy-mm, or yyyy-mm-dd,
* return the numeric values for the year, month, and day. No checking is
* done on these values. The string "now" is interpreted as the present
* date (in UTC).
*
* @param[in] s the date in string format.
* @param[out] y the year.
* @param[out] m the month, Jan = 1, etc.
* @param[out] d the day of the month.
* @exception GeographicErr is \e s is malformed.
**********************************************************************/
static void date(const std::string& s, int& y, int& m, int& d) {
if (s == "now") {
std::time_t t = std::time(0);
struct tm* now = gmtime(&t);
y = now->tm_year + 1900;
m = now->tm_mon + 1;
d = now->tm_mday;
return;
}
int y1, m1 = 1, d1 = 1;
const char* digits = "0123456789";
std::string::size_type p1 = s.find_first_not_of(digits);
if (p1 == std::string::npos)
y1 = val<int>(s);
else if (s[p1] != '-')
throw GeographicErr("Delimiter not hyphen in date " + s);
else if (p1 == 0)
throw GeographicErr("Empty year field in date " + s);
else {
y1 = val<int>(s.substr(0, p1));
if (++p1 == s.size())
throw GeographicErr("Empty month field in date " + s);
std::string::size_type p2 = s.find_first_not_of(digits, p1);
if (p2 == std::string::npos)
m1 = val<int>(s.substr(p1));
else if (s[p2] != '-')
throw GeographicErr("Delimiter not hyphen in date " + s);
else if (p2 == p1)
throw GeographicErr("Empty month field in date " + s);
else {
m1 = val<int>(s.substr(p1, p2 - p1));
if (++p2 == s.size())
throw GeographicErr("Empty day field in date " + s);
d1 = val<int>(s.substr(p2));
}
}
y = y1; m = m1; d = d1;
}
/**
* Given the date, return the day of the week.
*
* @param[in] y the year (must be positive).
* @param[in] m the month, Jan = 1, etc. (must be positive).
* @param[in] d the day of the month (must be positive).
* @return the day of the week with Sunday, Monday--Saturday = 0,
* 1--6.
**********************************************************************/
static int dow(int y, int m, int d) { return dow(day(y, m, d)); }
/**
* Given the sequential day, return the day of the week.
*
* @param[in] s the sequential day (must be positive).
* @return the day of the week with Sunday, Monday--Saturday = 0,
* 1--6.
**********************************************************************/
static int dow(int s) {
return (s + 5) % 7; // The 5 offset makes day 1 (0001-01-01) a Saturday.
}
/**
* Convert a string representing a date to a fractional year.
*
* @tparam T the type of the argument.
* @param[in] s the string to be converted.
* @exception GeographicErr if \e s can't be interpreted as a date.
* @return the fractional year.
*
* The string is first read as an ordinary number (e.g., 2010 or 2012.5);
* if this is successful, the value is returned. Otherwise the string
* should be of the form yyyy-mm or yyyy-mm-dd and this is converted to a
* number with 2010-01-01 giving 2010.0 and 2012-07-03 giving 2012.5.
**********************************************************************/
template<typename T> static T fractionalyear(const std::string& s) {
try {
return val<T>(s);
}
catch (const std::exception&) {}
int y, m, d;
date(s, y, m, d);
int t = day(y, m, d, true);
return T(y) + T(t - day(y)) / T(day(y + 1) - day(y));
}
/**
* Convert a object of type T to a string.
*
* @tparam T the type of the argument.
* @param[in] x the value to be converted.
* @param[in] p the precision used (default &minus;1).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return the string representation.
*
* If \e p &ge; 0, then the number fixed format is used with p bits of
* precision. With p < 0, there is no manipulation of the format.
**********************************************************************/
template<typename T> static std::string str(T x, int p = -1) {
std::ostringstream s;
if (p >= 0) s << std::fixed << std::setprecision(p);
s << x; return s.str();
}
/**
* Convert a Math::real object to a string.
*
* @param[in] x the value to be converted.
* @param[in] p the precision used (default &minus;1).
* @exception std::bad_alloc if memory for the string can't be allocated.
* @return the string representation.
*
* If \e p &ge; 0, then the number fixed format is used with p bits of
* precision. With p < 0, there is no manipulation of the format. This is
* an overload of str<T> which deals with inf and nan.
**********************************************************************/
static std::string str(Math::real x, int p = -1) {
using std::isfinite;
if (!isfinite(x))
return x < 0 ? std::string("-inf") :
(x > 0 ? std::string("inf") : std::string("nan"));
std::ostringstream s;
#if GEOGRAPHICLIB_PRECISION == 4
// boost-quadmath treats precision == 0 as "use as many digits as
// necessary" (see https://svn.boost.org/trac/boost/ticket/10103), so...
using std::floor; using std::fmod;
if (p == 0) {
x += Math::real(0.5);
Math::real ix = floor(x);
// Implement the "round ties to even" rule
x = (ix == x && fmod(ix, Math::real(2)) == 1) ? ix - 1 : ix;
s << std::fixed << std::setprecision(1) << x;
std::string r(s.str());
// strip off trailing ".0"
return r.substr(0, (std::max)(int(r.size()) - 2, 0));
}
#endif
if (p >= 0) s << std::fixed << std::setprecision(p);
s << x; return s.str();
}
/**
* Trim the white space from the beginning and end of a string.
*
* @param[in] s the string to be trimmed
* @return the trimmed string
**********************************************************************/
static std::string trim(const std::string& s) {
unsigned
beg = 0,
end = unsigned(s.size());
while (beg < end && isspace(s[beg]))
++beg;
while (beg < end && isspace(s[end - 1]))
--end;
return std::string(s, beg, end-beg);
}
/**
* Convert a string to type T.
*
* @tparam T the type of the return value.
* @param[in] s the string to be converted.
* @exception GeographicErr is \e s is not readable as a T.
* @return object of type T.
*
* White space at the beginning and end of \e s is ignored.
*
* Special handling is provided for some types.
*
* If T is a floating point type, then inf and nan are recognized.
*
* If T is bool, then \e s should either be string a representing 0 (false)
* or 1 (true) or one of the strings
* - "false", "f", "nil", "no", "n", "off", or "" meaning false,
* - "true", "t", "yes", "y", or "on" meaning true;
* .
* case is ignored.
*
* If T is std::string, then \e s is returned (with the white space at the
* beginning and end removed).
**********************************************************************/
template<typename T> static T val(const std::string& s) {
// If T is bool, then the specialization val<bool>() defined below is
// used.
T x;
std::string errmsg, t(trim(s));
do { // Executed once (provides the ability to break)
std::istringstream is(t);
if (!(is >> x)) {
errmsg = "Cannot decode " + t;
break;
}
int pos = int(is.tellg()); // Returns -1 at end of string?
if (!(pos < 0 || pos == int(t.size()))) {
errmsg = "Extra text " + t.substr(pos) + " at end of " + t;
break;
}
return x;
} while (false);
x = std::numeric_limits<T>::is_integer ? 0 : nummatch<T>(t);
if (x == 0)
throw GeographicErr(errmsg);
return x;
}
/**
* \deprecated An old name for val<T>(s).
**********************************************************************/
template<typename T>
GEOGRAPHICLIB_DEPRECATED("Use Utility::val<T>(s)")
static T num(const std::string& s) {
return val<T>(s);
}
/**
* Match "nan" and "inf" (and variants thereof) in a string.
*
* @tparam T the type of the return value (this should be a floating point
* type).
* @param[in] s the string to be matched.
* @return appropriate special value (&plusmn;&infin;, nan) or 0 if none is
* found.
*
* White space is not allowed at the beginning or end of \e s.
**********************************************************************/
template<typename T> static T nummatch(const std::string& s) {
if (s.length() < 3)
return 0;
std::string t(s);
for (std::string::iterator p = t.begin(); p != t.end(); ++p)
*p = char(std::toupper(*p));
for (size_t i = s.length(); i--;)
t[i] = char(std::toupper(s[i]));
int sign = t[0] == '-' ? -1 : 1;
std::string::size_type p0 = t[0] == '-' || t[0] == '+' ? 1 : 0;
std::string::size_type p1 = t.find_last_not_of('0');
if (p1 == std::string::npos || p1 + 1 < p0 + 3)
return 0;
// Strip off sign and trailing 0s
t = t.substr(p0, p1 + 1 - p0); // Length at least 3
if (t == "NAN" || t == "1.#QNAN" || t == "1.#SNAN" || t == "1.#IND" ||
t == "1.#R")
return Math::NaN<T>();
else if (t == "INF" || t == "1.#INF")
return sign * Math::infinity<T>();
return 0;
}
/**
* Read a simple fraction, e.g., 3/4, from a string to an object of type T.
*
* @tparam T the type of the return value.
* @param[in] s the string to be converted.
* @exception GeographicErr is \e s is not readable as a fraction of type
* T.
* @return object of type T
*
* \note The msys shell under Windows converts arguments which look like
* pathnames into their Windows equivalents. As a result the argument
* "-1/300" gets mangled into something unrecognizable. A workaround is to
* use a floating point number in the numerator, i.e., "-1.0/300". (Recent
* versions of the msys shell appear \e not to have this problem.)
**********************************************************************/
template<typename T> static T fract(const std::string& s) {
std::string::size_type delim = s.find('/');
return
!(delim != std::string::npos && delim >= 1 && delim + 2 <= s.size()) ?
val<T>(s) :
// delim in [1, size() - 2]
val<T>(s.substr(0, delim)) / val<T>(s.substr(delim + 1));
}
/**
* Lookup up a character in a string.
*
* @param[in] s the string to be searched.
* @param[in] c the character to look for.
* @return the index of the first occurrence character in the string or
* &minus;1 is the character is not present.
*
* \e c is converted to upper case before search \e s. Therefore, it is
* intended that \e s should not contain any lower case letters.
**********************************************************************/
static int lookup(const std::string& s, char c) {
std::string::size_type r = s.find(char(std::toupper(c)));
return r == std::string::npos ? -1 : int(r);
}
/**
* Lookup up a character in a char*.
*
* @param[in] s the char* string to be searched.
* @param[in] c the character to look for.
* @return the index of the first occurrence character in the string or
* &minus;1 is the character is not present.
*
* \e c is converted to upper case before search \e s. Therefore, it is
* intended that \e s should not contain any lower case letters.
**********************************************************************/
static int lookup(const char* s, char c) {
const char* p = std::strchr(s, std::toupper(c));
return p != NULL ? int(p - s) : -1;
}
/**
* Read data of type ExtT from a binary stream to an array of type IntT.
* The data in the file is in (bigendp ? big : little)-endian format.
*
* @tparam ExtT the type of the objects in the binary stream (external).
* @tparam IntT the type of the objects in the array (internal).
* @tparam bigendp true if the external storage format is big-endian.
* @param[in] str the input stream containing the data of type ExtT
* (external).
* @param[out] array the output array of type IntT (internal).
* @param[in] num the size of the array.
* @exception GeographicErr if the data cannot be read.
**********************************************************************/
template<typename ExtT, typename IntT, bool bigendp>
static void readarray(std::istream& str, IntT array[], size_t num) {
#if GEOGRAPHICLIB_PRECISION < 4
if (sizeof(IntT) == sizeof(ExtT) &&
std::numeric_limits<IntT>::is_integer ==
std::numeric_limits<ExtT>::is_integer)
{
// Data is compatible (aside from the issue of endian-ness).
str.read(reinterpret_cast<char*>(array), num * sizeof(ExtT));
if (!str.good())
throw GeographicErr("Failure reading data");
if (bigendp != Math::bigendian) { // endian mismatch -> swap bytes
for (size_t i = num; i--;)
array[i] = Math::swab<IntT>(array[i]);
}
}
else
#endif
{
const int bufsize = 1024; // read this many values at a time
ExtT buffer[bufsize]; // temporary buffer
int k = int(num); // data values left to read
int i = 0; // index into output array
while (k) {
int n = (std::min)(k, bufsize);
str.read(reinterpret_cast<char*>(buffer), n * sizeof(ExtT));
if (!str.good())
throw GeographicErr("Failure reading data");
for (int j = 0; j < n; ++j)
// fix endian-ness and cast to IntT
array[i++] = IntT(bigendp == Math::bigendian ? buffer[j] :
Math::swab<ExtT>(buffer[j]));
k -= n;
}
}
return;
}
/**
* Read data of type ExtT from a binary stream to a vector array of type
* IntT. The data in the file is in (bigendp ? big : little)-endian
* format.
*
* @tparam ExtT the type of the objects in the binary stream (external).
* @tparam IntT the type of the objects in the array (internal).
* @tparam bigendp true if the external storage format is big-endian.
* @param[in] str the input stream containing the data of type ExtT
* (external).
* @param[out] array the output vector of type IntT (internal).
* @exception GeographicErr if the data cannot be read.
**********************************************************************/
template<typename ExtT, typename IntT, bool bigendp>
static void readarray(std::istream& str, std::vector<IntT>& array) {
if (array.size() > 0)
readarray<ExtT, IntT, bigendp>(str, &array[0], array.size());
}
/**
* Write data in an array of type IntT as type ExtT to a binary stream.
* The data in the file is in (bigendp ? big : little)-endian format.
*
* @tparam ExtT the type of the objects in the binary stream (external).
* @tparam IntT the type of the objects in the array (internal).
* @tparam bigendp true if the external storage format is big-endian.
* @param[out] str the output stream for the data of type ExtT (external).
* @param[in] array the input array of type IntT (internal).
* @param[in] num the size of the array.
* @exception GeographicErr if the data cannot be written.
**********************************************************************/
template<typename ExtT, typename IntT, bool bigendp>
static void writearray(std::ostream& str, const IntT array[], size_t num)
{
#if GEOGRAPHICLIB_PRECISION < 4
if (sizeof(IntT) == sizeof(ExtT) &&
std::numeric_limits<IntT>::is_integer ==
std::numeric_limits<ExtT>::is_integer &&
bigendp == Math::bigendian)
{
// Data is compatible (including endian-ness).
str.write(reinterpret_cast<const char*>(array), num * sizeof(ExtT));
if (!str.good())
throw GeographicErr("Failure writing data");
}
else
#endif
{
const int bufsize = 1024; // write this many values at a time
ExtT buffer[bufsize]; // temporary buffer
int k = int(num); // data values left to write
int i = 0; // index into output array
while (k) {
int n = (std::min)(k, bufsize);
for (int j = 0; j < n; ++j)
// cast to ExtT and fix endian-ness
buffer[j] = bigendp == Math::bigendian ? ExtT(array[i++]) :
Math::swab<ExtT>(ExtT(array[i++]));
str.write(reinterpret_cast<const char*>(buffer), n * sizeof(ExtT));
if (!str.good())
throw GeographicErr("Failure writing data");
k -= n;
}
}
return;
}
/**
* Write data in an array of type IntT as type ExtT to a binary stream.
* The data in the file is in (bigendp ? big : little)-endian format.
*
* @tparam ExtT the type of the objects in the binary stream (external).
* @tparam IntT the type of the objects in the array (internal).
* @tparam bigendp true if the external storage format is big-endian.
* @param[out] str the output stream for the data of type ExtT (external).
* @param[in] array the input vector of type IntT (internal).
* @exception GeographicErr if the data cannot be written.
**********************************************************************/
template<typename ExtT, typename IntT, bool bigendp>
static void writearray(std::ostream& str, std::vector<IntT>& array) {
if (array.size() > 0)
writearray<ExtT, IntT, bigendp>(str, &array[0], array.size());
}
/**
* Parse a KEY [=] VALUE line.
*
* @param[in] line the input line.
* @param[out] key the KEY.
* @param[out] value the VALUE.
* @param[in] delim delimiter to separate KEY and VALUE, if NULL use first
* space character.
* @exception std::bad_alloc if memory for the internal strings can't be
* allocated.
* @return whether a key was found.
*
* A "#" character and everything after it are discarded and the result
* trimmed of leading and trailing white space. Use the delimiter
* character (or, if it is NULL, the first white space) to separate \e key
* and \e value. \e key and \e value are trimmed of leading and trailing
* white space. If \e key is empty, then \e value is set to "" and false
* is returned.
**********************************************************************/
static bool ParseLine(const std::string& line,
std::string& key, std::string& value,
char delim);
/**
* Parse a KEY VALUE line.
*
* @param[in] line the input line.
* @param[out] key the KEY.
* @param[out] value the VALUE.
* @exception std::bad_alloc if memory for the internal strings can't be
* allocated.
* @return whether a key was found.
*
* \note This is a transition routine. At some point \e delim will be made
* an optional argument in the previous version of ParseLine and this
* version will be removed.
**********************************************************************/
static bool ParseLine(const std::string& line,
std::string& key, std::string& value);
/**
* Set the binary precision of a real number.
*
* @param[in] ndigits the number of bits of precision. If ndigits is 0
* (the default), then determine the precision from the environment
* variable GEOGRAPHICLIB_DIGITS. If this is undefined, use ndigits =
* 256 (i.e., about 77 decimal digits).
* @return the resulting number of bits of precision.
*
* This only has an effect when GEOGRAPHICLIB_PRECISION = 5. The
* precision should only be set once and before calls to any other
* GeographicLib functions. (Several functions, for example Math::pi(),
* cache the return value in a static local variable. The precision needs
* to be set before a call to any such functions.) In multi-threaded
* applications, it is necessary also to set the precision in each thread
* (see the example GeoidToGTX.cpp).
**********************************************************************/
static int set_digits(int ndigits = 0);
};
/**
* The specialization of Utility::val<T>() for strings.
**********************************************************************/
template<> inline std::string Utility::val<std::string>(const std::string& s)
{ return trim(s); }
/**
* The specialization of Utility::val<T>() for bools.
**********************************************************************/
template<> inline bool Utility::val<bool>(const std::string& s) {
std::string t(trim(s));
if (t.empty()) return false;
bool x;
{
std::istringstream is(t);
if (is >> x) {
int pos = int(is.tellg()); // Returns -1 at end of string?
if (!(pos < 0 || pos == int(t.size())))
throw GeographicErr("Extra text " + t.substr(pos) +
" at end of " + t);
return x;
}
}
for (std::string::iterator p = t.begin(); p != t.end(); ++p)
*p = char(std::tolower(*p));
switch (t[0]) { // already checked that t isn't empty
case 'f':
if (t == "f" || t == "false") return false;
break;
case 'n':
if (t == "n" || t == "nil" || t == "no") return false;
break;
case 'o':
if (t == "off") return false;
else if (t == "on") return true;
break;
case 't':
if (t == "t" || t == "true") return true;
break;
case 'y':
if (t == "y" || t == "yes") return true;
break;
default:
break;
}
throw GeographicErr("Cannot decode " + t + " as a bool");
}
} // namespace GeographicLib
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
#endif // GEOGRAPHICLIB_UTILITY_HPP

2919
external/include/curl/curl.h فروخته شده Normal file

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است Diff را بارگزاری کن

77
external/include/curl/curlver.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,77 @@
#ifndef CURLINC_CURLVER_H
#define CURLINC_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.71.1-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 71
#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal (using 8 bits each). All three numbers are always represented
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
appears as "0x090b07".
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
Note: This define is the full hex number and _does not_ use the
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x074701
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in git, as the timestamp is properly set in the
* tarballs by the maketgz script.
*
* The format of the date follows this template:
*
* "2007-11-23"
*/
#define LIBCURL_TIMESTAMP "[unreleased]"
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
#endif /* CURLINC_CURLVER_H */

123
external/include/curl/easy.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,123 @@
#ifndef CURLINC_EASY_H
#define CURLINC_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/* Flag bits in the curl_blob struct: */
#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */
#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
struct curl_blob {
void *data;
size_t len;
unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
left zeroes */
};
CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
/*
* NAME curl_easy_getinfo()
*
* DESCRIPTION
*
* Request internal information from the curl session with this function. The
* third argument MUST be a pointer to a long, a pointer to a char * or a
* pointer to a double (as the documentation describes elsewhere). The data
* pointed to will be filled in accordingly and can be relied upon only if the
* function returns CURLE_OK. This function is intended to get used *AFTER* a
* performed transfer, all results from this function are undefined until the
* transfer is completed.
*/
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
/*
* NAME curl_easy_duphandle()
*
* DESCRIPTION
*
* Creates a new curl session handle with the same options set for the handle
* passed in. Duplicating a handle could only be a matter of cloning data and
* options, internal state info and things like persistent connections cannot
* be transferred. It is useful in multithreaded applications when you can run
* curl_easy_duphandle() for each new thread to avoid a series of identical
* curl_easy_setopt() invokes in every thread.
*/
CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
*
* DESCRIPTION
*
* Re-initializes a CURL handle to the default values. This puts back the
* handle to the same state as it was in when it was just created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
*/
CURL_EXTERN void curl_easy_reset(CURL *curl);
/*
* NAME curl_easy_recv()
*
* DESCRIPTION
*
* Receives data from the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
size_t *n);
/*
* NAME curl_easy_send()
*
* DESCRIPTION
*
* Sends data over the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
size_t buflen, size_t *n);
/*
* NAME curl_easy_upkeep()
*
* DESCRIPTION
*
* Performs connection upkeep for the given session handle.
*/
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus
}
#endif
#endif

50
external/include/curl/mprintf.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,50 @@
#ifndef CURLINC_MPRINTF_H
#define CURLINC_MPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <stdarg.h>
#include <stdio.h> /* needed for FILE */
#include "curl.h" /* for CURL_EXTERN */
#ifdef __cplusplus
extern "C" {
#endif
CURL_EXTERN int curl_mprintf(const char *format, ...);
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
const char *format, ...);
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
const char *format, va_list args);
CURL_EXTERN char *curl_maprintf(const char *format, ...);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef __cplusplus
}
#endif
#endif /* CURLINC_MPRINTF_H */

454
external/include/curl/multi.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,454 @@
#ifndef CURLINC_MULTI_H
#define CURLINC_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/*
This is an "external" header file. Don't give away any internals here!
GOALS
o Enable a "pull" interface. The application that uses libcurl decides where
and when to ask libcurl to get/send data.
o Enable multiple simultaneous transfers in the same thread without making it
complicated for the application.
o Enable the application to select() on its own file descriptors and curl's
file descriptors simultaneous easily.
*/
/*
* This header file should not really need to include "curl.h" since curl.h
* itself includes this file and we expect user applications to do #include
* <curl/curl.h> without the need for especially including multi.h.
*
* For some reason we added this include here at one point, and rather than to
* break existing (wrongly written) libcurl applications, we leave it as-is
* but with this warning attached.
*/
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
typedef struct Curl_multi CURLM;
#else
typedef void CURLM;
#endif
typedef enum {
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
curl_multi_socket*() soon */
CURLM_OK,
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
callback */
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
CURLM_LAST
} CURLMcode;
/* just to make code nicer when using curl_multi_socket() you can now check
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
/* bitmask bits for CURLMOPT_PIPELINING */
#define CURLPIPE_NOTHING 0L
#define CURLPIPE_HTTP1 1L
#define CURLPIPE_MULTIPLEX 2L
typedef enum {
CURLMSG_NONE, /* first, not used */
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
the CURLcode of the transfer */
CURLMSG_LAST /* last, not used */
} CURLMSG;
struct CURLMsg {
CURLMSG msg; /* what this message means */
CURL *easy_handle; /* the handle it concerns */
union {
void *whatever; /* message-specific data */
CURLcode result; /* return code for transfer */
} data;
};
typedef struct CURLMsg CURLMsg;
/* Based on poll(2) structure and values.
* We don't use pollfd and POLL* constants explicitly
* to cover platforms without poll(). */
#define CURL_WAIT_POLLIN 0x0001
#define CURL_WAIT_POLLPRI 0x0002
#define CURL_WAIT_POLLOUT 0x0004
struct curl_waitfd {
curl_socket_t fd;
short events;
short revents; /* not supported yet */
};
/*
* Name: curl_multi_init()
*
* Desc: inititalize multi-style curl usage
*
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
CURL_EXTERN CURLM *curl_multi_init(void);
/*
* Name: curl_multi_add_handle()
*
* Desc: add a standard curl handle to the multi stack
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_remove_handle()
*
* Desc: removes a curl handle from the multi stack again
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_fdset()
*
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
* poll() on. We want curl_multi_perform() called as soon as one of
* them are ready.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
/*
* Name: curl_multi_wait()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_poll()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_wakeup()
*
* Desc: wakes up a sleeping curl_multi_poll call.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);
/*
* Name: curl_multi_perform()
*
* Desc: When the app thinks there's data available for curl it calls this
* function to read/write whatever there is right now. This returns
* as soon as the reads and writes are done. This function does not
* require that there actually is data available for reading or that
* data can be written, it can be called just in case. It returns
* the number of handles that still transfer data in the second
* argument's integer-pointer.
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
* still have occurred problems on individual transfers even when
* this returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
/*
* Name: curl_multi_cleanup()
*
* Desc: Cleans up and removes a whole multi stack. It does not free or
* touch any individual easy handles in any way. We need to define
* in what state those handles will be if this function is called
* in the middle of a transfer.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
/*
* Name: curl_multi_info_read()
*
* Desc: Ask the multi handle if there's any messages/informationals from
* the individual transfers. Messages include informationals such as
* error code from the transfer or just the fact that a transfer is
* completed. More details on these should be written down as well.
*
* Repeated calls to this function will return a new struct each
* time, until a special "end of msgs" struct is returned as a signal
* that there is no more to get at this point.
*
* The data the returned pointer points to will not survive calling
* curl_multi_cleanup().
*
* The 'CURLMsg' struct is meant to be very simple and only contain
* very basic information. If more involved information is wanted,
* we will provide the particular "transfer handle" in that struct
* and that should/could/would be used in subsequent
* curl_easy_getinfo() calls (or similar). The point being that we
* must never expose complex structs to applications, as then we'll
* undoubtably get backwards compatibility problems in the future.
*
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
* of structs. It also writes the number of messages left in the
* queue (after this read) in the integer the second argument points
* to.
*/
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
/*
* Name: curl_multi_strerror()
*
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
* value into the equivalent human readable error string. This is
* useful for printing meaningful error messages.
*
* Returns: A pointer to a null-terminated error message.
*/
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
/*
* Name: curl_multi_socket() and
* curl_multi_socket_all()
*
* Desc: An alternative version of curl_multi_perform() that allows the
* application to pass in one of the file descriptors that have been
* detected to have "action" on them and let libcurl perform.
* See man page for details.
*/
#define CURL_POLL_NONE 0
#define CURL_POLL_IN 1
#define CURL_POLL_OUT 2
#define CURL_POLL_INOUT 3
#define CURL_POLL_REMOVE 4
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
#define CURL_CSELECT_IN 0x01
#define CURL_CSELECT_OUT 0x02
#define CURL_CSELECT_ERR 0x04
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
void *userp, /* private callback
pointer */
void *socketp); /* private socket
pointer */
/*
* Name: curl_multi_timer_callback
*
* Desc: Called by libcurl whenever the library detects a change in the
* maximum number of milliseconds the app is allowed to wait before
* curl_multi_socket() or curl_multi_perform() must be called
* (to allow libcurl's timed events to take place).
*
* Returns: The callback should return zero.
*/
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
long timeout_ms, /* see above */
void *userp); /* private callback
pointer */
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s,
int ev_bitmask,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
int *running_handles);
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
/* This macro below was added in 7.16.3 to push users who recompile to use
the new curl_multi_socket_action() instead of the old curl_multi_socket()
*/
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
#endif
/*
* Name: curl_multi_timeout()
*
* Desc: Returns the maximum number of milliseconds the app is allowed to
* wait before curl_multi_socket() or curl_multi_perform() must be
* called (to allow libcurl's timed events to take place).
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
long *milliseconds);
typedef enum {
/* This is the socket callback function pointer */
CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
/* This is the argument passed to the socket callback */
CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
/* set to 1 to enable pipelining for this multi handle */
CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
/* This is the timer callback function pointer */
CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
/* This is the argument passed to the timer callback */
CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
/* maximum number of entries in the connection cache */
CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
/* maximum number of (pipelining) connections to one host */
CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
/* maximum number of requests in a pipeline */
CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
/* a connection with a content-length longer than this
will not be considered for pipelining */
CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
/* a connection with a chunk length longer than this
will not be considered for pipelining */
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
/* a list of site names(+port) that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
/* a list of server types that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
/* maximum number of open connections in total */
CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
/* This is the server push callback function pointer */
CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
/* This is the argument passed to the server push callback */
CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
/* maximum number of concurrent streams to support on a connection */
CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
CURLMOPT_LASTENTRY /* the last unused */
} CURLMoption;
/*
* Name: curl_multi_setopt()
*
* Desc: Sets options for the multi handle.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURLMoption option, ...);
/*
* Name: curl_multi_assign()
*
* Desc: This function sets an association in the multi handle between the
* given socket and a private pointer of the application. This is
* (only) useful for curl_multi_socket uses.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t sockfd, void *sockp);
/*
* Name: curl_push_callback
*
* Desc: This callback gets called when a new stream is being pushed by the
* server. It approves or denies the new stream.
*
* Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
*/
#define CURL_PUSH_OK 0
#define CURL_PUSH_DENY 1
struct curl_pushheaders; /* forward declaration only */
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
size_t num);
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
const char *name);
typedef int (*curl_push_callback)(CURL *parent,
CURL *easy,
size_t num_headers,
struct curl_pushheaders *headers,
void *userp);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

33
external/include/curl/stdcheaders.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,33 @@
#ifndef CURLINC_STDCHEADERS_H
#define CURLINC_STDCHEADERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <sys/types.h>
size_t fread(void *, size_t, size_t, FILE *);
size_t fwrite(const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
#endif /* CURLINC_STDCHEADERS_H */

504
external/include/curl/system.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,504 @@
#ifndef CURLINC_SYSTEM_H
#define CURLINC_SYSTEM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/*
* Try to keep one section per platform, compiler and architecture, otherwise,
* if an existing section is reused for a different one and later on the
* original is adjusted, probably the piggybacking one can be adversely
* changed.
*
* In order to differentiate between platforms/compilers/architectures use
* only compiler built in predefined preprocessor symbols.
*
* curl_off_t
* ----------
*
* For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
* wide signed integral data type. The width of this data type must remain
* constant and independent of any possible large file support settings.
*
* As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
* wide signed integral data type if there is no 64-bit type.
*
* As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
* only be violated if off_t is the only 64-bit data type available and the
* size of off_t is independent of large file support settings. Keep your
* build on the safe side avoiding an off_t gating. If you have a 64-bit
* off_t then take for sure that another 64-bit data type exists, dig deeper
* and you will find it.
*
*/
#if defined(__DJGPP__) || defined(__GO32__)
# if defined(__DJGPP__) && (__DJGPP__ > 1)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__SALFORDC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__BORLANDC__)
# if (__BORLANDC__ < 0x520)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TURBOC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__WATCOMC__)
# if defined(__386__)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__POCC__)
# if (__POCC__ < 280)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# elif defined(_MSC_VER)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__LCC__)
# if defined(__e2k__) /* MCST eLbrus C Compiler */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# else /* Local (or Little) C Compiler */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(__SYMBIAN32__)
# if defined(__EABI__) /* Treat all ARM compilers equally */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__CW32__)
# pragma longlong on
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__VC32__)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__MWERKS__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__MINGW32__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_WS2TCPIP_H 1
#elif defined(__VMS)
# if defined(__VAX)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__OS400__)
# if defined(__ILEC400__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(__MVS__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
# elif defined(_LP64)
# endif
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(__370__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
# elif defined(_LP64)
# endif
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(TPF)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TINYC__) /* also known as tcc */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || \
defined(__sparcv8) || \
defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64) || \
defined(__amd64) || defined(__sparcv9)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__xlc__) /* IBM xlc compiler */
# if !defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
/* ===================================== */
/* KEEP MSVC THE PENULTIMATE ENTRY */
/* ===================================== */
#elif defined(_MSC_VER)
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
/* ===================================== */
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
#elif defined(__GNUC__) && !defined(_SCO_DS)
# if !defined(__LP64__) && \
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
defined(__XTENSA__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64__) || \
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
defined(__e2k__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#else
/* generic "safe guess" on old 32 bit style */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#endif
#ifdef _AIX
/* AIX needs <sys/poll.h> */
#define CURL_PULL_SYS_POLL_H
#endif
/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
/* ws2tcpip.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_WS2TCPIP_H
# include <winsock2.h>
# include <windows.h>
# include <ws2tcpip.h>
#endif
/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
/* sys/types.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_TYPES_H
# include <sys/types.h>
#endif
/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
/* sys/socket.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
/* sys/poll.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_POLL_H
# include <sys/poll.h>
#endif
/* Data type definition of curl_socklen_t. */
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
#endif
/* Data type definition of curl_off_t. */
#ifdef CURL_TYPEOF_CURL_OFF_T
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
#endif
/*
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
* these to be visible and exported by the external libcurl interface API,
* while also making them visible to the library internals, simply including
* curl_setup.h, without actually needing to include curl.h internally.
* If some day this section would grow big enough, all this should be moved
* to its own header file.
*/
/*
* Figure out if we can use the ## preprocessor operator, which is supported
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
* or __cplusplus so we need to carefully check for them too.
*/
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
defined(__ILEC400__)
/* This compiler is believed to have an ISO compatible preprocessor */
#define CURL_ISOCPP
#else
/* This compiler is believed NOT to have an ISO compatible preprocessor */
#undef CURL_ISOCPP
#endif
/*
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
*/
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
# define CURLINC_OFF_T_C_HLPR2(x) x
# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
#else
# ifdef CURL_ISOCPP
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# else
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# endif
# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
#endif
#endif /* CURLINC_SYSTEM_H */

700
external/include/curl/typecheck-gcc.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,700 @@
#ifndef CURLINC_TYPECHECK_GCC_H
#define CURLINC_TYPECHECK_GCC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/* wraps curl_easy_setopt() with typechecking */
/* To add a new kind of warning, add an
* if(curlcheck_sometype_option(_curl_opt))
* if(!curlcheck_sometype(value))
* _curl_easy_setopt_err_sometype();
* block and define curlcheck_sometype_option, curlcheck_sometype and
* _curl_easy_setopt_err_sometype below
*
* NOTE: We use two nested 'if' statements here instead of the && operator, in
* order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
* when compiling with -Wlogical-op.
*
* To add an option that uses the same type as an existing option, you'll just
* need to extend the appropriate _curl_*_option macro
*/
#define curl_easy_setopt(handle, option, value) \
__extension__({ \
__typeof__(option) _curl_opt = option; \
if(__builtin_constant_p(_curl_opt)) { \
if(curlcheck_long_option(_curl_opt)) \
if(!curlcheck_long(value)) \
_curl_easy_setopt_err_long(); \
if(curlcheck_off_t_option(_curl_opt)) \
if(!curlcheck_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(curlcheck_string_option(_curl_opt)) \
if(!curlcheck_string(value)) \
_curl_easy_setopt_err_string(); \
if(curlcheck_write_cb_option(_curl_opt)) \
if(!curlcheck_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
if(!curlcheck_resolver_start_callback(value)) \
_curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!curlcheck_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!curlcheck_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!curlcheck_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!curlcheck_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!curlcheck_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!curlcheck_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!curlcheck_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(curlcheck_conv_cb_option(_curl_opt)) \
if(!curlcheck_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!curlcheck_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(curlcheck_cb_data_option(_curl_opt)) \
if(!curlcheck_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!curlcheck_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!curlcheck_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(curlcheck_postfields_option(_curl_opt)) \
if(!curlcheck_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!curlcheck_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!curlcheck_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(curlcheck_slist_option(_curl_opt)) \
if(!curlcheck_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!curlcheck_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
#define curl_easy_getinfo(handle, info, arg) \
__extension__({ \
__typeof__(info) _curl_info = info; \
if(__builtin_constant_p(_curl_info)) { \
if(curlcheck_string_info(_curl_info)) \
if(!curlcheck_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(curlcheck_long_info(_curl_info)) \
if(!curlcheck_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(curlcheck_double_info(_curl_info)) \
if(!curlcheck_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(curlcheck_slist_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(curlcheck_tlssessioninfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(curlcheck_certinfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(curlcheck_socket_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(curlcheck_off_t_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/*
* For now, just make sure that the functions are called with three arguments
*/
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
* functions */
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
#define CURLWARNING(id, message) \
static void __attribute__((__warning__(message))) \
__attribute__((__unused__)) __attribute__((__noinline__)) \
id(void) { __asm__(""); }
CURLWARNING(_curl_easy_setopt_err_long,
"curl_easy_setopt expects a long argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
CURLWARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a "
"string ('char *' or char[]) argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_resolver_start_callback,
"curl_easy_setopt expects a "
"curl_resolver_start_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_ioctl_cb,
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_sockopt_cb,
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_opensocket_cb,
"curl_easy_setopt expects a "
"curl_opensocket_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_progress_cb,
"curl_easy_setopt expects a curl_progress_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_debug_cb,
"curl_easy_setopt expects a curl_debug_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb,
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_conv_cb,
"curl_easy_setopt expects a curl_conv_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_seek_cb,
"curl_easy_setopt expects a curl_seek_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_cb_data,
"curl_easy_setopt expects a "
"private data pointer as argument for this option")
CURLWARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option")
CURLWARNING(_curl_easy_setopt_err_FILE,
"curl_easy_setopt expects a 'FILE *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_postfields,
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_httpost,
"curl_easy_setopt expects a 'struct curl_httppost *' "
"argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_mimepost,
"curl_easy_setopt expects a 'curl_mime *' "
"argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_slist,
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
CURLWARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to 'char *' for this info")
CURLWARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
CURLWARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_tlssessioninfo *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_certinfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_certinfo *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_socket,
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
"curl_easy_getinfo expects a pointer to curl_off_t for this info")
/* groups of curl_easy_setops options that take the same type of argument */
/* To add a new option to one of the groups, just add
* (option) == CURLOPT_SOMETHING
* to the or-expression. If the option takes a long or curl_off_t, you don't
* have to do anything
*/
/* evaluates to true if option takes a long argument */
#define curlcheck_long_option(option) \
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define curlcheck_off_t_option(option) \
(((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
/* evaluates to true if option takes a char* argument */
#define curlcheck_string_option(option) \
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
(option) == CURLOPT_ACCEPT_ENCODING || \
(option) == CURLOPT_ALTSVC || \
(option) == CURLOPT_CAINFO || \
(option) == CURLOPT_CAPATH || \
(option) == CURLOPT_COOKIE || \
(option) == CURLOPT_COOKIEFILE || \
(option) == CURLOPT_COOKIEJAR || \
(option) == CURLOPT_COOKIELIST || \
(option) == CURLOPT_CRLFILE || \
(option) == CURLOPT_CUSTOMREQUEST || \
(option) == CURLOPT_DEFAULT_PROTOCOL || \
(option) == CURLOPT_DNS_INTERFACE || \
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
(option) == CURLOPT_KRBLEVEL || \
(option) == CURLOPT_LOGIN_OPTIONS || \
(option) == CURLOPT_MAIL_AUTH || \
(option) == CURLOPT_MAIL_FROM || \
(option) == CURLOPT_NETRC_FILE || \
(option) == CURLOPT_NOPROXY || \
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \
(option) == CURLOPT_PRE_PROXY || \
(option) == CURLOPT_PROXY || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
(option) == CURLOPT_PROXY_SSLCERT || \
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
(option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_SASL_AUTHZID || \
(option) == CURLOPT_SERVICE_NAME || \
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
(option) == CURLOPT_SSH_KNOWNHOSTS || \
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
(option) == CURLOPT_SSLCERT || \
(option) == CURLOPT_SSLCERTTYPE || \
(option) == CURLOPT_SSLENGINE || \
(option) == CURLOPT_SSLKEY || \
(option) == CURLOPT_SSLKEYTYPE || \
(option) == CURLOPT_SSL_CIPHER_LIST || \
(option) == CURLOPT_TLS13_CIPHERS || \
(option) == CURLOPT_TLSAUTH_PASSWORD || \
(option) == CURLOPT_TLSAUTH_TYPE || \
(option) == CURLOPT_TLSAUTH_USERNAME || \
(option) == CURLOPT_UNIX_SOCKET_PATH || \
(option) == CURLOPT_URL || \
(option) == CURLOPT_USERAGENT || \
(option) == CURLOPT_USERNAME || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
#define curlcheck_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \
(option) == CURLOPT_WRITEFUNCTION)
/* evaluates to true if option takes a curl_conv_callback argument */
#define curlcheck_conv_cb_option(option) \
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
/* evaluates to true if option takes a data argument to pass to a callback */
#define curlcheck_cb_data_option(option) \
((option) == CURLOPT_CHUNK_DATA || \
(option) == CURLOPT_CLOSESOCKETDATA || \
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
(option) == CURLOPT_PRIVATE || \
(option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_READDATA || \
(option) == CURLOPT_SEEKDATA || \
(option) == CURLOPT_SOCKOPTDATA || \
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_RESOLVER_START_DATA || \
(option) == CURLOPT_TRAILERDATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
#define curlcheck_postfields_option(option) \
((option) == CURLOPT_POSTFIELDS || \
(option) == CURLOPT_COPYPOSTFIELDS || \
0)
/* evaluates to true if option takes a struct curl_slist * argument */
#define curlcheck_slist_option(option) \
((option) == CURLOPT_HTTP200ALIASES || \
(option) == CURLOPT_HTTPHEADER || \
(option) == CURLOPT_MAIL_RCPT || \
(option) == CURLOPT_POSTQUOTE || \
(option) == CURLOPT_PREQUOTE || \
(option) == CURLOPT_PROXYHEADER || \
(option) == CURLOPT_QUOTE || \
(option) == CURLOPT_RESOLVE || \
(option) == CURLOPT_TELNETOPTIONS || \
(option) == CURLOPT_CONNECT_TO || \
0)
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
#define curlcheck_string_info(info) \
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
(info) != CURLINFO_PRIVATE)
/* evaluates to true if info expects a pointer to long argument */
#define curlcheck_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
#define curlcheck_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
#define curlcheck_slist_info(info) \
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
#define curlcheck_tlssessioninfo_info(info) \
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
/* true if info expects a pointer to struct curl_certinfo * argument */
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
/* true if info expects a pointer to struct curl_socket_t argument */
#define curlcheck_socket_info(info) \
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
/* true if info expects a pointer to curl_off_t argument */
#define curlcheck_off_t_info(info) \
(CURLINFO_OFF_T < (info))
/* typecheck helpers -- check whether given expression has requested type*/
/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
* otherwise define a new macro. Search for __builtin_types_compatible_p
* in the GCC manual.
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
* the actual expression passed to the curl_easy_setopt macro. This
* means that you can only apply the sizeof and __typeof__ operators, no
* == or whatsoever.
*/
/* XXX: should evaluate to true if expr is a pointer */
#define curlcheck_any_ptr(expr) \
(sizeof(expr) == sizeof(void *))
/* evaluates to true if expr is NULL */
/* XXX: must not evaluate expr, so this check is not accurate */
#define curlcheck_NULL(expr) \
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
/* evaluates to true if expr is type*, const type* or NULL */
#define curlcheck_ptr(expr, type) \
(curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), type *) || \
__builtin_types_compatible_p(__typeof__(expr), const type *))
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
#define curlcheck_arr(expr, type) \
(curlcheck_ptr((expr), type) || \
__builtin_types_compatible_p(__typeof__(expr), type []))
/* evaluates to true if expr is a string */
#define curlcheck_string(expr) \
(curlcheck_arr((expr), char) || \
curlcheck_arr((expr), signed char) || \
curlcheck_arr((expr), unsigned char))
/* evaluates to true if expr is a long (no matter the signedness)
* XXX: for now, int is also accepted (and therefore short and char, which
* are promoted to int when passed to a variadic function) */
#define curlcheck_long(expr) \
(__builtin_types_compatible_p(__typeof__(expr), long) || \
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
__builtin_types_compatible_p(__typeof__(expr), int) || \
__builtin_types_compatible_p(__typeof__(expr), signed int) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
__builtin_types_compatible_p(__typeof__(expr), short) || \
__builtin_types_compatible_p(__typeof__(expr), signed short) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
__builtin_types_compatible_p(__typeof__(expr), char) || \
__builtin_types_compatible_p(__typeof__(expr), signed char) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
/* evaluates to true if expr is of type curl_off_t */
#define curlcheck_off_t(expr) \
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
/* XXX: also check size of an char[] array? */
#define curlcheck_error_buffer(expr) \
(curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), char *) || \
__builtin_types_compatible_p(__typeof__(expr), char[]))
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
#if 0
#define curlcheck_cb_data(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_ptr((expr), FILE))
#else /* be less strict */
#define curlcheck_cb_data(expr) \
curlcheck_any_ptr(expr)
#endif
/* evaluates to true if expr is of type FILE* */
#define curlcheck_FILE(expr) \
(curlcheck_NULL(expr) || \
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define curlcheck_postfields(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_arr((expr), char) || \
curlcheck_arr((expr), unsigned char))
/* helper: __builtin_types_compatible_p distinguishes between functions and
* function pointers, hide it */
#define curlcheck_cb_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func) *, type))
/* evaluates to true if expr is of type curl_resolver_start_callback */
#define curlcheck_resolver_start_callback(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define curlcheck_read_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
curlcheck_cb_compatible((expr), curl_read_callback) || \
curlcheck_cb_compatible((expr), _curl_read_callback1) || \
curlcheck_cb_compatible((expr), _curl_read_callback2) || \
curlcheck_cb_compatible((expr), _curl_read_callback3) || \
curlcheck_cb_compatible((expr), _curl_read_callback4) || \
curlcheck_cb_compatible((expr), _curl_read_callback5) || \
curlcheck_cb_compatible((expr), _curl_read_callback6))
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_write_callback or "similar" */
#define curlcheck_write_cb(expr) \
(curlcheck_read_cb(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
curlcheck_cb_compatible((expr), curl_write_callback) || \
curlcheck_cb_compatible((expr), _curl_write_callback1) || \
curlcheck_cb_compatible((expr), _curl_write_callback2) || \
curlcheck_cb_compatible((expr), _curl_write_callback3) || \
curlcheck_cb_compatible((expr), _curl_write_callback4) || \
curlcheck_cb_compatible((expr), _curl_write_callback5) || \
curlcheck_cb_compatible((expr), _curl_write_callback6))
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
const void *);
typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
const void *);
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define curlcheck_ioctl_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback4))
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define curlcheck_sockopt_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback2))
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or
"similar" */
#define curlcheck_opensocket_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback4))
typedef curl_socket_t (*_curl_opensocket_callback1)
(void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback2)
(void *, curlsocktype, const struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback3)
(const void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback4)
(const void *, curlsocktype, const struct curl_sockaddr *);
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
#define curlcheck_progress_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_progress_callback) || \
curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
curlcheck_cb_compatible((expr), _curl_progress_callback2))
typedef int (*_curl_progress_callback1)(void *,
double, double, double, double);
typedef int (*_curl_progress_callback2)(const void *,
double, double, double, double);
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
#define curlcheck_debug_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_debug_callback) || \
curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
curlcheck_cb_compatible((expr), _curl_debug_callback8))
typedef int (*_curl_debug_callback1) (CURL *,
curl_infotype, char *, size_t, void *);
typedef int (*_curl_debug_callback2) (CURL *,
curl_infotype, char *, size_t, const void *);
typedef int (*_curl_debug_callback3) (CURL *,
curl_infotype, const char *, size_t, void *);
typedef int (*_curl_debug_callback4) (CURL *,
curl_infotype, const char *, size_t, const void *);
typedef int (*_curl_debug_callback5) (CURL *,
curl_infotype, unsigned char *, size_t, void *);
typedef int (*_curl_debug_callback6) (CURL *,
curl_infotype, unsigned char *, size_t, const void *);
typedef int (*_curl_debug_callback7) (CURL *,
curl_infotype, const unsigned char *, size_t, void *);
typedef int (*_curl_debug_callback8) (CURL *,
curl_infotype, const unsigned char *, size_t, const void *);
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
/* this is getting even messier... */
#define curlcheck_ssl_ctx_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8))
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
const void *);
#ifdef HEADER_SSL_H
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
* this will of course break if we're included before OpenSSL headers...
*/
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
const void *);
#else
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
#endif
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
#define curlcheck_conv_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_conv_callback) || \
curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
curlcheck_cb_compatible((expr), _curl_conv_callback4))
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
#define curlcheck_seek_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_seek_callback) || \
curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
curlcheck_cb_compatible((expr), _curl_seek_callback2))
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
#endif /* CURLINC_TYPECHECK_GCC_H */

125
external/include/curl/urlapi.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,125 @@
#ifndef CURLINC_URLAPI_H
#define CURLINC_URLAPI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
/* the error codes for the URL API */
typedef enum {
CURLUE_OK,
CURLUE_BAD_HANDLE, /* 1 */
CURLUE_BAD_PARTPOINTER, /* 2 */
CURLUE_MALFORMED_INPUT, /* 3 */
CURLUE_BAD_PORT_NUMBER, /* 4 */
CURLUE_UNSUPPORTED_SCHEME, /* 5 */
CURLUE_URLDECODE, /* 6 */
CURLUE_OUT_OF_MEMORY, /* 7 */
CURLUE_USER_NOT_ALLOWED, /* 8 */
CURLUE_UNKNOWN_PART, /* 9 */
CURLUE_NO_SCHEME, /* 10 */
CURLUE_NO_USER, /* 11 */
CURLUE_NO_PASSWORD, /* 12 */
CURLUE_NO_OPTIONS, /* 13 */
CURLUE_NO_HOST, /* 14 */
CURLUE_NO_PORT, /* 15 */
CURLUE_NO_QUERY, /* 16 */
CURLUE_NO_FRAGMENT /* 17 */
} CURLUcode;
typedef enum {
CURLUPART_URL,
CURLUPART_SCHEME,
CURLUPART_USER,
CURLUPART_PASSWORD,
CURLUPART_OPTIONS,
CURLUPART_HOST,
CURLUPART_PORT,
CURLUPART_PATH,
CURLUPART_QUERY,
CURLUPART_FRAGMENT,
CURLUPART_ZONEID /* added in 7.65.0 */
} CURLUPart;
#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
if the port number matches the
default for the scheme */
#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
missing */
#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
#define CURLU_URLDECODE (1<<6) /* URL decode on get */
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
typedef struct Curl_URL CURLU;
/*
* curl_url() creates a new CURLU handle and returns a pointer to it.
* Must be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url(void);
/*
* curl_url_cleanup() frees the CURLU handle and related resources used for
* the URL parsing. It will not free strings previously returned with the URL
* API.
*/
CURL_EXTERN void curl_url_cleanup(CURLU *handle);
/*
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
* handle must also be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
/*
* curl_url_get() extracts a specific part of the URL from a CURLU
* handle. Returns error code. The returned pointer MUST be freed with
* curl_free() afterwards.
*/
CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
char **part, unsigned int flags);
/*
* curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
* error code. The passed in string will be copied. Passing a NULL instead of
* a part string, clears that part.
*/
CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
const char *part, unsigned int flags);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_URLAPI_H */

46
external/include/eigen3/Eigen/Cholesky فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,46 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_CHOLESKY_MODULE_H
#define EIGEN_CHOLESKY_MODULE_H
#include "Core"
#include "Jacobi"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup Cholesky_Module Cholesky module
*
*
*
* This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices.
* Those decompositions are also accessible via the following methods:
* - MatrixBase::llt()
* - MatrixBase::ldlt()
* - SelfAdjointView::llt()
* - SelfAdjointView::ldlt()
*
* \code
* #include <Eigen/Cholesky>
* \endcode
*/
#include "src/Cholesky/LLT.h"
#include "src/Cholesky/LDLT.h"
#ifdef EIGEN_USE_LAPACKE
#ifdef EIGEN_USE_MKL
#include "mkl_lapacke.h"
#else
#include "src/misc/lapacke.h"
#endif
#include "src/Cholesky/LLT_LAPACKE.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_CHOLESKY_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

48
external/include/eigen3/Eigen/CholmodSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,48 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_CHOLMODSUPPORT_MODULE_H
#define EIGEN_CHOLMODSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
extern "C" {
#include <cholmod.h>
}
/** \ingroup Support_modules
* \defgroup CholmodSupport_Module CholmodSupport module
*
* This module provides an interface to the Cholmod library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
* It provides the two following main factorization classes:
* - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization.
* - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial).
*
* For the sake of completeness, this module also propose the two following classes:
* - class CholmodSimplicialLLT
* - class CholmodSimplicialLDLT
* Note that these classes does not bring any particular advantage compared to the built-in
* SimplicialLLT and SimplicialLDLT factorization classes.
*
* \code
* #include <Eigen/CholmodSupport>
* \endcode
*
* In order to use this module, the cholmod headers must be accessible from the include paths, and your binary must be linked to the cholmod library and its dependencies.
* The dependencies depend on how cholmod has been compiled.
* For a cmake based project, you can use our FindCholmod.cmake module to help you in this task.
*
*/
#include "src/CholmodSupport/CholmodSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_CHOLMODSUPPORT_MODULE_H

537
external/include/eigen3/Eigen/Core فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,537 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2007-2011 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_CORE_H
#define EIGEN_CORE_H
// first thing Eigen does: stop the compiler from committing suicide
#include "src/Core/util/DisableStupidWarnings.h"
#if defined(__CUDACC__) && !defined(EIGEN_NO_CUDA)
#define EIGEN_CUDACC __CUDACC__
#endif
#if defined(__CUDA_ARCH__) && !defined(EIGEN_NO_CUDA)
#define EIGEN_CUDA_ARCH __CUDA_ARCH__
#endif
#if defined(__CUDACC_VER_MAJOR__) && (__CUDACC_VER_MAJOR__ >= 9)
#define EIGEN_CUDACC_VER ((__CUDACC_VER_MAJOR__ * 10000) + (__CUDACC_VER_MINOR__ * 100))
#elif defined(__CUDACC_VER__)
#define EIGEN_CUDACC_VER __CUDACC_VER__
#else
#define EIGEN_CUDACC_VER 0
#endif
// Handle NVCC/CUDA/SYCL
#if defined(__CUDACC__) || defined(__SYCL_DEVICE_ONLY__)
// Do not try asserts on CUDA and SYCL!
#ifndef EIGEN_NO_DEBUG
#define EIGEN_NO_DEBUG
#endif
#ifdef EIGEN_INTERNAL_DEBUGGING
#undef EIGEN_INTERNAL_DEBUGGING
#endif
#ifdef EIGEN_EXCEPTIONS
#undef EIGEN_EXCEPTIONS
#endif
// All functions callable from CUDA code must be qualified with __device__
#ifdef __CUDACC__
// Do not try to vectorize on CUDA and SYCL!
#ifndef EIGEN_DONT_VECTORIZE
#define EIGEN_DONT_VECTORIZE
#endif
#define EIGEN_DEVICE_FUNC __host__ __device__
// We need cuda_runtime.h to ensure that that EIGEN_USING_STD_MATH macro
// works properly on the device side
#include <cuda_runtime.h>
#else
#define EIGEN_DEVICE_FUNC
#endif
#else
#define EIGEN_DEVICE_FUNC
#endif
// When compiling CUDA device code with NVCC, pull in math functions from the
// global namespace. In host mode, and when device doee with clang, use the
// std versions.
#if defined(__CUDA_ARCH__) && defined(__NVCC__)
#define EIGEN_USING_STD_MATH(FUNC) using ::FUNC;
#else
#define EIGEN_USING_STD_MATH(FUNC) using std::FUNC;
#endif
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) && !defined(EIGEN_EXCEPTIONS) && !defined(EIGEN_USE_SYCL)
#define EIGEN_EXCEPTIONS
#endif
#ifdef EIGEN_EXCEPTIONS
#include <new>
#endif
// then include this file where all our macros are defined. It's really important to do it first because
// it's where we do all the alignment settings (platform detection and honoring the user's will if he
// defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization.
#include "src/Core/util/Macros.h"
// Disable the ipa-cp-clone optimization flag with MinGW 6.x or newer (enabled by default with -O3)
// See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556 for details.
#if EIGEN_COMP_MINGW && EIGEN_GNUC_AT_LEAST(4,6)
#pragma GCC optimize ("-fno-ipa-cp-clone")
#endif
#include <complex>
// this include file manages BLAS and MKL related macros
// and inclusion of their respective header files
#include "src/Core/util/MKL_support.h"
// if alignment is disabled, then disable vectorization. Note: EIGEN_MAX_ALIGN_BYTES is the proper check, it takes into
// account both the user's will (EIGEN_MAX_ALIGN_BYTES,EIGEN_DONT_ALIGN) and our own platform checks
#if EIGEN_MAX_ALIGN_BYTES==0
#ifndef EIGEN_DONT_VECTORIZE
#define EIGEN_DONT_VECTORIZE
#endif
#endif
#if EIGEN_COMP_MSVC
#include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
#if (EIGEN_COMP_MSVC >= 1500) // 2008 or later
// Remember that usage of defined() in a #define is undefined by the standard.
// a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP.
#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || EIGEN_ARCH_x86_64
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
#endif
#endif
#else
// Remember that usage of defined() in a #define is undefined by the standard
#if (defined __SSE2__) && ( (!EIGEN_COMP_GNUC) || EIGEN_COMP_ICC || EIGEN_GNUC_AT_LEAST(4,2) )
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
#endif
#endif
#ifndef EIGEN_DONT_VECTORIZE
#if defined (EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
// Defines symbols for compile-time detection of which instructions are
// used.
// EIGEN_VECTORIZE_YY is defined if and only if the instruction set YY is used
#define EIGEN_VECTORIZE
#define EIGEN_VECTORIZE_SSE
#define EIGEN_VECTORIZE_SSE2
// Detect sse3/ssse3/sse4:
// gcc and icc defines __SSE3__, ...
// there is no way to know about this on msvc. You can define EIGEN_VECTORIZE_SSE* if you
// want to force the use of those instructions with msvc.
#ifdef __SSE3__
#define EIGEN_VECTORIZE_SSE3
#endif
#ifdef __SSSE3__
#define EIGEN_VECTORIZE_SSSE3
#endif
#ifdef __SSE4_1__
#define EIGEN_VECTORIZE_SSE4_1
#endif
#ifdef __SSE4_2__
#define EIGEN_VECTORIZE_SSE4_2
#endif
#ifdef __AVX__
#define EIGEN_VECTORIZE_AVX
#define EIGEN_VECTORIZE_SSE3
#define EIGEN_VECTORIZE_SSSE3
#define EIGEN_VECTORIZE_SSE4_1
#define EIGEN_VECTORIZE_SSE4_2
#endif
#ifdef __AVX2__
#define EIGEN_VECTORIZE_AVX2
#endif
#ifdef __FMA__
#define EIGEN_VECTORIZE_FMA
#endif
#if defined(__AVX512F__) && defined(EIGEN_ENABLE_AVX512)
#define EIGEN_VECTORIZE_AVX512
#define EIGEN_VECTORIZE_AVX2
#define EIGEN_VECTORIZE_AVX
#define EIGEN_VECTORIZE_FMA
#ifdef __AVX512DQ__
#define EIGEN_VECTORIZE_AVX512DQ
#endif
#ifdef __AVX512ER__
#define EIGEN_VECTORIZE_AVX512ER
#endif
#endif
// include files
// This extern "C" works around a MINGW-w64 compilation issue
// https://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354
// In essence, intrin.h is included by windows.h and also declares intrinsics (just as emmintrin.h etc. below do).
// However, intrin.h uses an extern "C" declaration, and g++ thus complains of duplicate declarations
// with conflicting linkage. The linkage for intrinsics doesn't matter, but at that stage the compiler doesn't know;
// so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too.
// notice that since these are C headers, the extern "C" is theoretically needed anyways.
extern "C" {
// In theory we should only include immintrin.h and not the other *mmintrin.h header files directly.
// Doing so triggers some issues with ICC. However old gcc versions seems to not have this file, thus:
#if EIGEN_COMP_ICC >= 1110
#include <immintrin.h>
#else
#include <mmintrin.h>
#include <emmintrin.h>
#include <xmmintrin.h>
#ifdef EIGEN_VECTORIZE_SSE3
#include <pmmintrin.h>
#endif
#ifdef EIGEN_VECTORIZE_SSSE3
#include <tmmintrin.h>
#endif
#ifdef EIGEN_VECTORIZE_SSE4_1
#include <smmintrin.h>
#endif
#ifdef EIGEN_VECTORIZE_SSE4_2
#include <nmmintrin.h>
#endif
#if defined(EIGEN_VECTORIZE_AVX) || defined(EIGEN_VECTORIZE_AVX512)
#include <immintrin.h>
#endif
#endif
} // end extern "C"
#elif defined __VSX__
#define EIGEN_VECTORIZE
#define EIGEN_VECTORIZE_VSX
#include <altivec.h>
// We need to #undef all these ugly tokens defined in <altivec.h>
// => use __vector instead of vector
#undef bool
#undef vector
#undef pixel
#elif defined __ALTIVEC__
#define EIGEN_VECTORIZE
#define EIGEN_VECTORIZE_ALTIVEC
#include <altivec.h>
// We need to #undef all these ugly tokens defined in <altivec.h>
// => use __vector instead of vector
#undef bool
#undef vector
#undef pixel
#elif (defined __ARM_NEON) || (defined __ARM_NEON__)
#define EIGEN_VECTORIZE
#define EIGEN_VECTORIZE_NEON
#include <arm_neon.h>
#elif (defined __s390x__ && defined __VEC__)
#define EIGEN_VECTORIZE
#define EIGEN_VECTORIZE_ZVECTOR
#include <vecintrin.h>
#endif
#endif
#if defined(__F16C__) && !defined(EIGEN_COMP_CLANG)
// We can use the optimized fp16 to float and float to fp16 conversion routines
#define EIGEN_HAS_FP16_C
#endif
#if defined __CUDACC__
#define EIGEN_VECTORIZE_CUDA
#include <vector_types.h>
#if EIGEN_CUDACC_VER >= 70500
#define EIGEN_HAS_CUDA_FP16
#endif
#endif
#if defined EIGEN_HAS_CUDA_FP16
#include <host_defines.h>
#include <cuda_fp16.h>
#endif
#if (defined _OPENMP) && (!defined EIGEN_DONT_PARALLELIZE)
#define EIGEN_HAS_OPENMP
#endif
#ifdef EIGEN_HAS_OPENMP
#include <omp.h>
#endif
// MSVC for windows mobile does not have the errno.h file
#if !(EIGEN_COMP_MSVC && EIGEN_OS_WINCE) && !EIGEN_COMP_ARM
#define EIGEN_HAS_ERRNO
#endif
#ifdef EIGEN_HAS_ERRNO
#include <cerrno>
#endif
#include <cstddef>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <functional>
#include <iosfwd>
#include <cstring>
#include <string>
#include <limits>
#include <climits> // for CHAR_BIT
// for min/max:
#include <algorithm>
// for std::is_nothrow_move_assignable
#ifdef EIGEN_INCLUDE_TYPE_TRAITS
#include <type_traits>
#endif
// for outputting debug info
#ifdef EIGEN_DEBUG_ASSIGN
#include <iostream>
#endif
// required for __cpuid, needs to be included after cmath
#if EIGEN_COMP_MSVC && EIGEN_ARCH_i386_OR_x86_64 && !EIGEN_OS_WINCE
#include <intrin.h>
#endif
/** \brief Namespace containing all symbols from the %Eigen library. */
namespace Eigen {
inline static const char *SimdInstructionSetsInUse(void) {
#if defined(EIGEN_VECTORIZE_AVX512)
return "AVX512, FMA, AVX2, AVX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
#elif defined(EIGEN_VECTORIZE_AVX)
return "AVX SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
#elif defined(EIGEN_VECTORIZE_SSE4_2)
return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
#elif defined(EIGEN_VECTORIZE_SSE4_1)
return "SSE, SSE2, SSE3, SSSE3, SSE4.1";
#elif defined(EIGEN_VECTORIZE_SSSE3)
return "SSE, SSE2, SSE3, SSSE3";
#elif defined(EIGEN_VECTORIZE_SSE3)
return "SSE, SSE2, SSE3";
#elif defined(EIGEN_VECTORIZE_SSE2)
return "SSE, SSE2";
#elif defined(EIGEN_VECTORIZE_ALTIVEC)
return "AltiVec";
#elif defined(EIGEN_VECTORIZE_VSX)
return "VSX";
#elif defined(EIGEN_VECTORIZE_NEON)
return "ARM NEON";
#elif defined(EIGEN_VECTORIZE_ZVECTOR)
return "S390X ZVECTOR";
#else
return "None";
#endif
}
} // end namespace Eigen
#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS || defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API || defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS || defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API || defined EIGEN2_SUPPORT
// This will generate an error message:
#error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information
#endif
namespace Eigen {
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
// ensure QNX/QCC support
using std::size_t;
// gcc 4.6.0 wants std:: for ptrdiff_t
using std::ptrdiff_t;
}
/** \defgroup Core_Module Core module
* This is the main module of Eigen providing dense matrix and vector support
* (both fixed and dynamic size) with all the features corresponding to a BLAS library
* and much more...
*
* \code
* #include <Eigen/Core>
* \endcode
*/
#include "src/Core/util/Constants.h"
#include "src/Core/util/Meta.h"
#include "src/Core/util/ForwardDeclarations.h"
#include "src/Core/util/StaticAssert.h"
#include "src/Core/util/XprHelper.h"
#include "src/Core/util/Memory.h"
#include "src/Core/NumTraits.h"
#include "src/Core/MathFunctions.h"
#include "src/Core/GenericPacketMath.h"
#include "src/Core/MathFunctionsImpl.h"
#include "src/Core/arch/Default/ConjHelper.h"
#if defined EIGEN_VECTORIZE_AVX512
#include "src/Core/arch/SSE/PacketMath.h"
#include "src/Core/arch/AVX/PacketMath.h"
#include "src/Core/arch/AVX512/PacketMath.h"
#include "src/Core/arch/AVX512/MathFunctions.h"
#elif defined EIGEN_VECTORIZE_AVX
// Use AVX for floats and doubles, SSE for integers
#include "src/Core/arch/SSE/PacketMath.h"
#include "src/Core/arch/SSE/Complex.h"
#include "src/Core/arch/SSE/MathFunctions.h"
#include "src/Core/arch/AVX/PacketMath.h"
#include "src/Core/arch/AVX/MathFunctions.h"
#include "src/Core/arch/AVX/Complex.h"
#include "src/Core/arch/AVX/TypeCasting.h"
#include "src/Core/arch/SSE/TypeCasting.h"
#elif defined EIGEN_VECTORIZE_SSE
#include "src/Core/arch/SSE/PacketMath.h"
#include "src/Core/arch/SSE/MathFunctions.h"
#include "src/Core/arch/SSE/Complex.h"
#include "src/Core/arch/SSE/TypeCasting.h"
#elif defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX)
#include "src/Core/arch/AltiVec/PacketMath.h"
#include "src/Core/arch/AltiVec/MathFunctions.h"
#include "src/Core/arch/AltiVec/Complex.h"
#elif defined EIGEN_VECTORIZE_NEON
#include "src/Core/arch/NEON/PacketMath.h"
#include "src/Core/arch/NEON/MathFunctions.h"
#include "src/Core/arch/NEON/Complex.h"
#elif defined EIGEN_VECTORIZE_ZVECTOR
#include "src/Core/arch/ZVector/PacketMath.h"
#include "src/Core/arch/ZVector/MathFunctions.h"
#include "src/Core/arch/ZVector/Complex.h"
#endif
// Half float support
#include "src/Core/arch/CUDA/Half.h"
#include "src/Core/arch/CUDA/PacketMathHalf.h"
#include "src/Core/arch/CUDA/TypeCasting.h"
#if defined EIGEN_VECTORIZE_CUDA
#include "src/Core/arch/CUDA/PacketMath.h"
#include "src/Core/arch/CUDA/MathFunctions.h"
#endif
#include "src/Core/arch/Default/Settings.h"
#include "src/Core/functors/TernaryFunctors.h"
#include "src/Core/functors/BinaryFunctors.h"
#include "src/Core/functors/UnaryFunctors.h"
#include "src/Core/functors/NullaryFunctors.h"
#include "src/Core/functors/StlFunctors.h"
#include "src/Core/functors/AssignmentFunctors.h"
// Specialized functors to enable the processing of complex numbers
// on CUDA devices
#include "src/Core/arch/CUDA/Complex.h"
#include "src/Core/IO.h"
#include "src/Core/DenseCoeffsBase.h"
#include "src/Core/DenseBase.h"
#include "src/Core/MatrixBase.h"
#include "src/Core/EigenBase.h"
#include "src/Core/Product.h"
#include "src/Core/CoreEvaluators.h"
#include "src/Core/AssignEvaluator.h"
#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874
// at least confirmed with Doxygen 1.5.5 and 1.5.6
#include "src/Core/Assign.h"
#endif
#include "src/Core/ArrayBase.h"
#include "src/Core/util/BlasUtil.h"
#include "src/Core/DenseStorage.h"
#include "src/Core/NestByValue.h"
// #include "src/Core/ForceAlignedAccess.h"
#include "src/Core/ReturnByValue.h"
#include "src/Core/NoAlias.h"
#include "src/Core/PlainObjectBase.h"
#include "src/Core/Matrix.h"
#include "src/Core/Array.h"
#include "src/Core/CwiseTernaryOp.h"
#include "src/Core/CwiseBinaryOp.h"
#include "src/Core/CwiseUnaryOp.h"
#include "src/Core/CwiseNullaryOp.h"
#include "src/Core/CwiseUnaryView.h"
#include "src/Core/SelfCwiseBinaryOp.h"
#include "src/Core/Dot.h"
#include "src/Core/StableNorm.h"
#include "src/Core/Stride.h"
#include "src/Core/MapBase.h"
#include "src/Core/Map.h"
#include "src/Core/Ref.h"
#include "src/Core/Block.h"
#include "src/Core/VectorBlock.h"
#include "src/Core/Transpose.h"
#include "src/Core/DiagonalMatrix.h"
#include "src/Core/Diagonal.h"
#include "src/Core/DiagonalProduct.h"
#include "src/Core/Redux.h"
#include "src/Core/Visitor.h"
#include "src/Core/Fuzzy.h"
#include "src/Core/Swap.h"
#include "src/Core/CommaInitializer.h"
#include "src/Core/GeneralProduct.h"
#include "src/Core/Solve.h"
#include "src/Core/Inverse.h"
#include "src/Core/SolverBase.h"
#include "src/Core/PermutationMatrix.h"
#include "src/Core/Transpositions.h"
#include "src/Core/TriangularMatrix.h"
#include "src/Core/SelfAdjointView.h"
#include "src/Core/products/GeneralBlockPanelKernel.h"
#include "src/Core/products/Parallelizer.h"
#include "src/Core/ProductEvaluators.h"
#include "src/Core/products/GeneralMatrixVector.h"
#include "src/Core/products/GeneralMatrixMatrix.h"
#include "src/Core/SolveTriangular.h"
#include "src/Core/products/GeneralMatrixMatrixTriangular.h"
#include "src/Core/products/SelfadjointMatrixVector.h"
#include "src/Core/products/SelfadjointMatrixMatrix.h"
#include "src/Core/products/SelfadjointProduct.h"
#include "src/Core/products/SelfadjointRank2Update.h"
#include "src/Core/products/TriangularMatrixVector.h"
#include "src/Core/products/TriangularMatrixMatrix.h"
#include "src/Core/products/TriangularSolverMatrix.h"
#include "src/Core/products/TriangularSolverVector.h"
#include "src/Core/BandMatrix.h"
#include "src/Core/CoreIterators.h"
#include "src/Core/ConditionEstimator.h"
#include "src/Core/BooleanRedux.h"
#include "src/Core/Select.h"
#include "src/Core/VectorwiseOp.h"
#include "src/Core/Random.h"
#include "src/Core/Replicate.h"
#include "src/Core/Reverse.h"
#include "src/Core/ArrayWrapper.h"
#ifdef EIGEN_USE_BLAS
#include "src/Core/products/GeneralMatrixMatrix_BLAS.h"
#include "src/Core/products/GeneralMatrixVector_BLAS.h"
#include "src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h"
#include "src/Core/products/SelfadjointMatrixMatrix_BLAS.h"
#include "src/Core/products/SelfadjointMatrixVector_BLAS.h"
#include "src/Core/products/TriangularMatrixMatrix_BLAS.h"
#include "src/Core/products/TriangularMatrixVector_BLAS.h"
#include "src/Core/products/TriangularSolverMatrix_BLAS.h"
#endif // EIGEN_USE_BLAS
#ifdef EIGEN_USE_MKL_VML
#include "src/Core/Assign_MKL.h"
#endif
#include "src/Core/GlobalFunctions.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_CORE_H

7
external/include/eigen3/Eigen/Dense فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,7 @@
#include "Core"
#include "LU"
#include "Cholesky"
#include "QR"
#include "SVD"
#include "Geometry"
#include "Eigenvalues"

2
external/include/eigen3/Eigen/Eigen فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,2 @@
#include "Dense"
#include "Sparse"

61
external/include/eigen3/Eigen/Eigenvalues فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,61 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_EIGENVALUES_MODULE_H
#define EIGEN_EIGENVALUES_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
#include "Cholesky"
#include "Jacobi"
#include "Householder"
#include "LU"
#include "Geometry"
/** \defgroup Eigenvalues_Module Eigenvalues module
*
*
*
* This module mainly provides various eigenvalue solvers.
* This module also provides some MatrixBase methods, including:
* - MatrixBase::eigenvalues(),
* - MatrixBase::operatorNorm()
*
* \code
* #include <Eigen/Eigenvalues>
* \endcode
*/
#include "src/misc/RealSvd2x2.h"
#include "src/Eigenvalues/Tridiagonalization.h"
#include "src/Eigenvalues/RealSchur.h"
#include "src/Eigenvalues/EigenSolver.h"
#include "src/Eigenvalues/SelfAdjointEigenSolver.h"
#include "src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h"
#include "src/Eigenvalues/HessenbergDecomposition.h"
#include "src/Eigenvalues/ComplexSchur.h"
#include "src/Eigenvalues/ComplexEigenSolver.h"
#include "src/Eigenvalues/RealQZ.h"
#include "src/Eigenvalues/GeneralizedEigenSolver.h"
#include "src/Eigenvalues/MatrixBaseEigenvalues.h"
#ifdef EIGEN_USE_LAPACKE
#ifdef EIGEN_USE_MKL
#include "mkl_lapacke.h"
#else
#include "src/misc/lapacke.h"
#endif
#include "src/Eigenvalues/RealSchur_LAPACKE.h"
#include "src/Eigenvalues/ComplexSchur_LAPACKE.h"
#include "src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_EIGENVALUES_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

62
external/include/eigen3/Eigen/Geometry فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,62 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_GEOMETRY_MODULE_H
#define EIGEN_GEOMETRY_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
#include "SVD"
#include "LU"
#include <limits>
/** \defgroup Geometry_Module Geometry module
*
* This module provides support for:
* - fixed-size homogeneous transformations
* - translation, scaling, 2D and 3D rotations
* - \link Quaternion quaternions \endlink
* - cross products (\ref MatrixBase::cross, \ref MatrixBase::cross3)
* - orthognal vector generation (\ref MatrixBase::unitOrthogonal)
* - some linear components: \link ParametrizedLine parametrized-lines \endlink and \link Hyperplane hyperplanes \endlink
* - \link AlignedBox axis aligned bounding boxes \endlink
* - \link umeyama least-square transformation fitting \endlink
*
* \code
* #include <Eigen/Geometry>
* \endcode
*/
#include "src/Geometry/OrthoMethods.h"
#include "src/Geometry/EulerAngles.h"
#include "src/Geometry/Homogeneous.h"
#include "src/Geometry/RotationBase.h"
#include "src/Geometry/Rotation2D.h"
#include "src/Geometry/Quaternion.h"
#include "src/Geometry/AngleAxis.h"
#include "src/Geometry/Transform.h"
#include "src/Geometry/Translation.h"
#include "src/Geometry/Scaling.h"
#include "src/Geometry/Hyperplane.h"
#include "src/Geometry/ParametrizedLine.h"
#include "src/Geometry/AlignedBox.h"
#include "src/Geometry/Umeyama.h"
// Use the SSE optimized version whenever possible. At the moment the
// SSE version doesn't compile when AVX is enabled
#if defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX
#include "src/Geometry/arch/Geometry_SSE.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_GEOMETRY_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

30
external/include/eigen3/Eigen/Householder فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,30 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_HOUSEHOLDER_MODULE_H
#define EIGEN_HOUSEHOLDER_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup Householder_Module Householder module
* This module provides Householder transformations.
*
* \code
* #include <Eigen/Householder>
* \endcode
*/
#include "src/Householder/Householder.h"
#include "src/Householder/HouseholderSequence.h"
#include "src/Householder/BlockHouseholder.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_HOUSEHOLDER_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

48
external/include/eigen3/Eigen/IterativeLinearSolvers فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,48 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ITERATIVELINEARSOLVERS_MODULE_H
#define EIGEN_ITERATIVELINEARSOLVERS_MODULE_H
#include "SparseCore"
#include "OrderingMethods"
#include "src/Core/util/DisableStupidWarnings.h"
/**
* \defgroup IterativeLinearSolvers_Module IterativeLinearSolvers module
*
* This module currently provides iterative methods to solve problems of the form \c A \c x = \c b, where \c A is a squared matrix, usually very large and sparse.
* Those solvers are accessible via the following classes:
* - ConjugateGradient for selfadjoint (hermitian) matrices,
* - LeastSquaresConjugateGradient for rectangular least-square problems,
* - BiCGSTAB for general square matrices.
*
* These iterative solvers are associated with some preconditioners:
* - IdentityPreconditioner - not really useful
* - DiagonalPreconditioner - also called Jacobi preconditioner, work very well on diagonal dominant matrices.
* - IncompleteLUT - incomplete LU factorization with dual thresholding
*
* Such problems can also be solved using the direct sparse decomposition modules: SparseCholesky, CholmodSupport, UmfPackSupport, SuperLUSupport.
*
\code
#include <Eigen/IterativeLinearSolvers>
\endcode
*/
#include "src/IterativeLinearSolvers/SolveWithGuess.h"
#include "src/IterativeLinearSolvers/IterativeSolverBase.h"
#include "src/IterativeLinearSolvers/BasicPreconditioners.h"
#include "src/IterativeLinearSolvers/ConjugateGradient.h"
#include "src/IterativeLinearSolvers/LeastSquareConjugateGradient.h"
#include "src/IterativeLinearSolvers/BiCGSTAB.h"
#include "src/IterativeLinearSolvers/IncompleteLUT.h"
#include "src/IterativeLinearSolvers/IncompleteCholesky.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_ITERATIVELINEARSOLVERS_MODULE_H

33
external/include/eigen3/Eigen/Jacobi فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,33 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_JACOBI_MODULE_H
#define EIGEN_JACOBI_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup Jacobi_Module Jacobi module
* This module provides Jacobi and Givens rotations.
*
* \code
* #include <Eigen/Jacobi>
* \endcode
*
* In addition to listed classes, it defines the two following MatrixBase methods to apply a Jacobi or Givens rotation:
* - MatrixBase::applyOnTheLeft()
* - MatrixBase::applyOnTheRight().
*/
#include "src/Jacobi/Jacobi.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_JACOBI_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

50
external/include/eigen3/Eigen/LU فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,50 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_LU_MODULE_H
#define EIGEN_LU_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup LU_Module LU module
* This module includes %LU decomposition and related notions such as matrix inversion and determinant.
* This module defines the following MatrixBase methods:
* - MatrixBase::inverse()
* - MatrixBase::determinant()
*
* \code
* #include <Eigen/LU>
* \endcode
*/
#include "src/misc/Kernel.h"
#include "src/misc/Image.h"
#include "src/LU/FullPivLU.h"
#include "src/LU/PartialPivLU.h"
#ifdef EIGEN_USE_LAPACKE
#ifdef EIGEN_USE_MKL
#include "mkl_lapacke.h"
#else
#include "src/misc/lapacke.h"
#endif
#include "src/LU/PartialPivLU_LAPACKE.h"
#endif
#include "src/LU/Determinant.h"
#include "src/LU/InverseImpl.h"
// Use the SSE optimized version whenever possible. At the moment the
// SSE version doesn't compile when AVX is enabled
#if defined EIGEN_VECTORIZE_SSE && !defined EIGEN_VECTORIZE_AVX
#include "src/LU/arch/Inverse_SSE.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_LU_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

35
external/include/eigen3/Eigen/MetisSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,35 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_METISSUPPORT_MODULE_H
#define EIGEN_METISSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
extern "C" {
#include <metis.h>
}
/** \ingroup Support_modules
* \defgroup MetisSupport_Module MetisSupport module
*
* \code
* #include <Eigen/MetisSupport>
* \endcode
* This module defines an interface to the METIS reordering package (http://glaros.dtc.umn.edu/gkhome/views/metis).
* It can be used just as any other built-in method as explained in \link OrderingMethods_Module here. \endlink
*/
#include "src/MetisSupport/MetisSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_METISSUPPORT_MODULE_H

73
external/include/eigen3/Eigen/OrderingMethods فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,73 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ORDERINGMETHODS_MODULE_H
#define EIGEN_ORDERINGMETHODS_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
/**
* \defgroup OrderingMethods_Module OrderingMethods module
*
* This module is currently for internal use only
*
* It defines various built-in and external ordering methods for sparse matrices.
* They are typically used to reduce the number of elements during
* the sparse matrix decomposition (LLT, LU, QR).
* Precisely, in a preprocessing step, a permutation matrix P is computed using
* those ordering methods and applied to the columns of the matrix.
* Using for instance the sparse Cholesky decomposition, it is expected that
* the nonzeros elements in LLT(A*P) will be much smaller than that in LLT(A).
*
*
* Usage :
* \code
* #include <Eigen/OrderingMethods>
* \endcode
*
* A simple usage is as a template parameter in the sparse decomposition classes :
*
* \code
* SparseLU<MatrixType, COLAMDOrdering<int> > solver;
* \endcode
*
* \code
* SparseQR<MatrixType, COLAMDOrdering<int> > solver;
* \endcode
*
* It is possible as well to call directly a particular ordering method for your own purpose,
* \code
* AMDOrdering<int> ordering;
* PermutationMatrix<Dynamic, Dynamic, int> perm;
* SparseMatrix<double> A;
* //Fill the matrix ...
*
* ordering(A, perm); // Call AMD
* \endcode
*
* \note Some of these methods (like AMD or METIS), need the sparsity pattern
* of the input matrix to be symmetric. When the matrix is structurally unsymmetric,
* Eigen computes internally the pattern of \f$A^T*A\f$ before calling the method.
* If your matrix is already symmetric (at leat in structure), you can avoid that
* by calling the method with a SelfAdjointView type.
*
* \code
* // Call the ordering on the pattern of the lower triangular matrix A
* ordering(A.selfadjointView<Lower>(), perm);
* \endcode
*/
#ifndef EIGEN_MPL2_ONLY
#include "src/OrderingMethods/Amd.h"
#endif
#include "src/OrderingMethods/Ordering.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_ORDERINGMETHODS_MODULE_H

48
external/include/eigen3/Eigen/PaStiXSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,48 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_PASTIXSUPPORT_MODULE_H
#define EIGEN_PASTIXSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
extern "C" {
#include <pastix_nompi.h>
#include <pastix.h>
}
#ifdef complex
#undef complex
#endif
/** \ingroup Support_modules
* \defgroup PaStiXSupport_Module PaStiXSupport module
*
* This module provides an interface to the <a href="http://pastix.gforge.inria.fr/">PaSTiX</a> library.
* PaSTiX is a general \b supernodal, \b parallel and \b opensource sparse solver.
* It provides the two following main factorization classes:
* - class PastixLLT : a supernodal, parallel LLt Cholesky factorization.
* - class PastixLDLT: a supernodal, parallel LDLt Cholesky factorization.
* - class PastixLU : a supernodal, parallel LU factorization (optimized for a symmetric pattern).
*
* \code
* #include <Eigen/PaStiXSupport>
* \endcode
*
* In order to use this module, the PaSTiX headers must be accessible from the include paths, and your binary must be linked to the PaSTiX library and its dependencies.
* The dependencies depend on how PaSTiX has been compiled.
* For a cmake based project, you can use our FindPaSTiX.cmake module to help you in this task.
*
*/
#include "src/PaStiXSupport/PaStiXSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_PASTIXSUPPORT_MODULE_H

35
external/include/eigen3/Eigen/PardisoSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,35 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_PARDISOSUPPORT_MODULE_H
#define EIGEN_PARDISOSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
#include <mkl_pardiso.h>
/** \ingroup Support_modules
* \defgroup PardisoSupport_Module PardisoSupport module
*
* This module brings support for the Intel(R) MKL PARDISO direct sparse solvers.
*
* \code
* #include <Eigen/PardisoSupport>
* \endcode
*
* In order to use this module, the MKL headers must be accessible from the include paths, and your binary must be linked to the MKL library and its dependencies.
* See this \ref TopicUsingIntelMKL "page" for more information on MKL-Eigen integration.
*
*/
#include "src/PardisoSupport/PardisoSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_PARDISOSUPPORT_MODULE_H

51
external/include/eigen3/Eigen/QR فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,51 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_QR_MODULE_H
#define EIGEN_QR_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
#include "Cholesky"
#include "Jacobi"
#include "Householder"
/** \defgroup QR_Module QR module
*
*
*
* This module provides various QR decompositions
* This module also provides some MatrixBase methods, including:
* - MatrixBase::householderQr()
* - MatrixBase::colPivHouseholderQr()
* - MatrixBase::fullPivHouseholderQr()
*
* \code
* #include <Eigen/QR>
* \endcode
*/
#include "src/QR/HouseholderQR.h"
#include "src/QR/FullPivHouseholderQR.h"
#include "src/QR/ColPivHouseholderQR.h"
#include "src/QR/CompleteOrthogonalDecomposition.h"
#ifdef EIGEN_USE_LAPACKE
#ifdef EIGEN_USE_MKL
#include "mkl_lapacke.h"
#else
#include "src/misc/lapacke.h"
#endif
#include "src/QR/HouseholderQR_LAPACKE.h"
#include "src/QR/ColPivHouseholderQR_LAPACKE.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_QR_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

40
external/include/eigen3/Eigen/QtAlignedMalloc فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,40 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_QTMALLOC_MODULE_H
#define EIGEN_QTMALLOC_MODULE_H
#include "Core"
#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
#include "src/Core/util/DisableStupidWarnings.h"
void *qMalloc(std::size_t size)
{
return Eigen::internal::aligned_malloc(size);
}
void qFree(void *ptr)
{
Eigen::internal::aligned_free(ptr);
}
void *qRealloc(void *ptr, std::size_t size)
{
void* newPtr = Eigen::internal::aligned_malloc(size);
std::memcpy(newPtr, ptr, size);
Eigen::internal::aligned_free(ptr);
return newPtr;
}
#include "src/Core/util/ReenableStupidWarnings.h"
#endif
#endif // EIGEN_QTMALLOC_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

34
external/include/eigen3/Eigen/SPQRSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,34 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPQRSUPPORT_MODULE_H
#define EIGEN_SPQRSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
#include "SuiteSparseQR.hpp"
/** \ingroup Support_modules
* \defgroup SPQRSupport_Module SuiteSparseQR module
*
* This module provides an interface to the SPQR library, which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
*
* \code
* #include <Eigen/SPQRSupport>
* \endcode
*
* In order to use this module, the SPQR headers must be accessible from the include paths, and your binary must be linked to the SPQR library and its dependencies (Cholmod, AMD, COLAMD,...).
* For a cmake based project, you can use our FindSPQR.cmake and FindCholmod.Cmake modules
*
*/
#include "src/CholmodSupport/CholmodSupport.h"
#include "src/SPQRSupport/SuiteSparseQRSupport.h"
#endif

51
external/include/eigen3/Eigen/SVD فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,51 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SVD_MODULE_H
#define EIGEN_SVD_MODULE_H
#include "QR"
#include "Householder"
#include "Jacobi"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup SVD_Module SVD module
*
*
*
* This module provides SVD decomposition for matrices (both real and complex).
* Two decomposition algorithms are provided:
* - JacobiSVD implementing two-sided Jacobi iterations is numerically very accurate, fast for small matrices, but very slow for larger ones.
* - BDCSVD implementing a recursive divide & conquer strategy on top of an upper-bidiagonalization which remains fast for large problems.
* These decompositions are accessible via the respective classes and following MatrixBase methods:
* - MatrixBase::jacobiSvd()
* - MatrixBase::bdcSvd()
*
* \code
* #include <Eigen/SVD>
* \endcode
*/
#include "src/misc/RealSvd2x2.h"
#include "src/SVD/UpperBidiagonalization.h"
#include "src/SVD/SVDBase.h"
#include "src/SVD/JacobiSVD.h"
#include "src/SVD/BDCSVD.h"
#if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT)
#ifdef EIGEN_USE_MKL
#include "mkl_lapacke.h"
#else
#include "src/misc/lapacke.h"
#endif
#include "src/SVD/JacobiSVD_LAPACKE.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SVD_MODULE_H
/* vim: set filetype=cpp et sw=2 ts=2 ai: */

36
external/include/eigen3/Eigen/Sparse فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,36 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPARSE_MODULE_H
#define EIGEN_SPARSE_MODULE_H
/** \defgroup Sparse_Module Sparse meta-module
*
* Meta-module including all related modules:
* - \ref SparseCore_Module
* - \ref OrderingMethods_Module
* - \ref SparseCholesky_Module
* - \ref SparseLU_Module
* - \ref SparseQR_Module
* - \ref IterativeLinearSolvers_Module
*
\code
#include <Eigen/Sparse>
\endcode
*/
#include "SparseCore"
#include "OrderingMethods"
#ifndef EIGEN_MPL2_ONLY
#include "SparseCholesky"
#endif
#include "SparseLU"
#include "SparseQR"
#include "IterativeLinearSolvers"
#endif // EIGEN_SPARSE_MODULE_H

45
external/include/eigen3/Eigen/SparseCholesky فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,45 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2013 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPARSECHOLESKY_MODULE_H
#define EIGEN_SPARSECHOLESKY_MODULE_H
#include "SparseCore"
#include "OrderingMethods"
#include "src/Core/util/DisableStupidWarnings.h"
/**
* \defgroup SparseCholesky_Module SparseCholesky module
*
* This module currently provides two variants of the direct sparse Cholesky decomposition for selfadjoint (hermitian) matrices.
* Those decompositions are accessible via the following classes:
* - SimplicialLLt,
* - SimplicialLDLt
*
* Such problems can also be solved using the ConjugateGradient solver from the IterativeLinearSolvers module.
*
* \code
* #include <Eigen/SparseCholesky>
* \endcode
*/
#ifdef EIGEN_MPL2_ONLY
#error The SparseCholesky module has nothing to offer in MPL2 only mode
#endif
#include "src/SparseCholesky/SimplicialCholesky.h"
#ifndef EIGEN_MPL2_ONLY
#include "src/SparseCholesky/SimplicialCholesky_impl.h"
#endif
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SPARSECHOLESKY_MODULE_H

69
external/include/eigen3/Eigen/SparseCore فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,69 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPARSECORE_MODULE_H
#define EIGEN_SPARSECORE_MODULE_H
#include "Core"
#include "src/Core/util/DisableStupidWarnings.h"
#include <vector>
#include <map>
#include <cstdlib>
#include <cstring>
#include <algorithm>
/**
* \defgroup SparseCore_Module SparseCore module
*
* This module provides a sparse matrix representation, and basic associated matrix manipulations
* and operations.
*
* See the \ref TutorialSparse "Sparse tutorial"
*
* \code
* #include <Eigen/SparseCore>
* \endcode
*
* This module depends on: Core.
*/
#include "src/SparseCore/SparseUtil.h"
#include "src/SparseCore/SparseMatrixBase.h"
#include "src/SparseCore/SparseAssign.h"
#include "src/SparseCore/CompressedStorage.h"
#include "src/SparseCore/AmbiVector.h"
#include "src/SparseCore/SparseCompressedBase.h"
#include "src/SparseCore/SparseMatrix.h"
#include "src/SparseCore/SparseMap.h"
#include "src/SparseCore/MappedSparseMatrix.h"
#include "src/SparseCore/SparseVector.h"
#include "src/SparseCore/SparseRef.h"
#include "src/SparseCore/SparseCwiseUnaryOp.h"
#include "src/SparseCore/SparseCwiseBinaryOp.h"
#include "src/SparseCore/SparseTranspose.h"
#include "src/SparseCore/SparseBlock.h"
#include "src/SparseCore/SparseDot.h"
#include "src/SparseCore/SparseRedux.h"
#include "src/SparseCore/SparseView.h"
#include "src/SparseCore/SparseDiagonalProduct.h"
#include "src/SparseCore/ConservativeSparseSparseProduct.h"
#include "src/SparseCore/SparseSparseProductWithPruning.h"
#include "src/SparseCore/SparseProduct.h"
#include "src/SparseCore/SparseDenseProduct.h"
#include "src/SparseCore/SparseSelfAdjointView.h"
#include "src/SparseCore/SparseTriangularView.h"
#include "src/SparseCore/TriangularSolver.h"
#include "src/SparseCore/SparsePermutation.h"
#include "src/SparseCore/SparseFuzzy.h"
#include "src/SparseCore/SparseSolverBase.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SPARSECORE_MODULE_H

46
external/include/eigen3/Eigen/SparseLU فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,46 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPARSELU_MODULE_H
#define EIGEN_SPARSELU_MODULE_H
#include "SparseCore"
/**
* \defgroup SparseLU_Module SparseLU module
* This module defines a supernodal factorization of general sparse matrices.
* The code is fully optimized for supernode-panel updates with specialized kernels.
* Please, see the documentation of the SparseLU class for more details.
*/
// Ordering interface
#include "OrderingMethods"
#include "src/SparseLU/SparseLU_gemm_kernel.h"
#include "src/SparseLU/SparseLU_Structs.h"
#include "src/SparseLU/SparseLU_SupernodalMatrix.h"
#include "src/SparseLU/SparseLUImpl.h"
#include "src/SparseCore/SparseColEtree.h"
#include "src/SparseLU/SparseLU_Memory.h"
#include "src/SparseLU/SparseLU_heap_relax_snode.h"
#include "src/SparseLU/SparseLU_relax_snode.h"
#include "src/SparseLU/SparseLU_pivotL.h"
#include "src/SparseLU/SparseLU_panel_dfs.h"
#include "src/SparseLU/SparseLU_kernel_bmod.h"
#include "src/SparseLU/SparseLU_panel_bmod.h"
#include "src/SparseLU/SparseLU_column_dfs.h"
#include "src/SparseLU/SparseLU_column_bmod.h"
#include "src/SparseLU/SparseLU_copy_to_ucol.h"
#include "src/SparseLU/SparseLU_pruneL.h"
#include "src/SparseLU/SparseLU_Utils.h"
#include "src/SparseLU/SparseLU.h"
#endif // EIGEN_SPARSELU_MODULE_H

37
external/include/eigen3/Eigen/SparseQR فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,37 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SPARSEQR_MODULE_H
#define EIGEN_SPARSEQR_MODULE_H
#include "SparseCore"
#include "OrderingMethods"
#include "src/Core/util/DisableStupidWarnings.h"
/** \defgroup SparseQR_Module SparseQR module
* \brief Provides QR decomposition for sparse matrices
*
* This module provides a simplicial version of the left-looking Sparse QR decomposition.
* The columns of the input matrix should be reordered to limit the fill-in during the
* decomposition. Built-in methods (COLAMD, AMD) or external methods (METIS) can be used to this end.
* See the \link OrderingMethods_Module OrderingMethods\endlink module for the list
* of built-in and external ordering methods.
*
* \code
* #include <Eigen/SparseQR>
* \endcode
*
*
*/
#include "OrderingMethods"
#include "src/SparseCore/SparseColEtree.h"
#include "src/SparseQR/SparseQR.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif

27
external/include/eigen3/Eigen/StdDeque فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,27 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_STDDEQUE_MODULE_H
#define EIGEN_STDDEQUE_MODULE_H
#include "Core"
#include <deque>
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */
#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...)
#else
#include "src/StlSupport/StdDeque.h"
#endif
#endif // EIGEN_STDDEQUE_MODULE_H

26
external/include/eigen3/Eigen/StdList فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,26 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_STDLIST_MODULE_H
#define EIGEN_STDLIST_MODULE_H
#include "Core"
#include <list>
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */
#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...)
#else
#include "src/StlSupport/StdList.h"
#endif
#endif // EIGEN_STDLIST_MODULE_H

27
external/include/eigen3/Eigen/StdVector فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,27 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_STDVECTOR_MODULE_H
#define EIGEN_STDVECTOR_MODULE_H
#include "Core"
#include <vector>
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */
#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...)
#else
#include "src/StlSupport/StdVector.h"
#endif
#endif // EIGEN_STDVECTOR_MODULE_H

64
external/include/eigen3/Eigen/SuperLUSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,64 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_SUPERLUSUPPORT_MODULE_H
#define EIGEN_SUPERLUSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
#ifdef EMPTY
#define EIGEN_EMPTY_WAS_ALREADY_DEFINED
#endif
typedef int int_t;
#include <slu_Cnames.h>
#include <supermatrix.h>
#include <slu_util.h>
// slu_util.h defines a preprocessor token named EMPTY which is really polluting,
// so we remove it in favor of a SUPERLU_EMPTY token.
// If EMPTY was already defined then we don't undef it.
#if defined(EIGEN_EMPTY_WAS_ALREADY_DEFINED)
# undef EIGEN_EMPTY_WAS_ALREADY_DEFINED
#elif defined(EMPTY)
# undef EMPTY
#endif
#define SUPERLU_EMPTY (-1)
namespace Eigen { struct SluMatrix; }
/** \ingroup Support_modules
* \defgroup SuperLUSupport_Module SuperLUSupport module
*
* This module provides an interface to the <a href="http://crd-legacy.lbl.gov/~xiaoye/SuperLU/">SuperLU</a> library.
* It provides the following factorization class:
* - class SuperLU: a supernodal sequential LU factorization.
* - class SuperILU: a supernodal sequential incomplete LU factorization (to be used as a preconditioner for iterative methods).
*
* \warning This wrapper requires at least versions 4.0 of SuperLU. The 3.x versions are not supported.
*
* \warning When including this module, you have to use SUPERLU_EMPTY instead of EMPTY which is no longer defined because it is too polluting.
*
* \code
* #include <Eigen/SuperLUSupport>
* \endcode
*
* In order to use this module, the superlu headers must be accessible from the include paths, and your binary must be linked to the superlu library and its dependencies.
* The dependencies depend on how superlu has been compiled.
* For a cmake based project, you can use our FindSuperLU.cmake module to help you in this task.
*
*/
#include "src/SuperLUSupport/SuperLUSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_SUPERLUSUPPORT_MODULE_H

40
external/include/eigen3/Eigen/UmfPackSupport فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,40 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_UMFPACKSUPPORT_MODULE_H
#define EIGEN_UMFPACKSUPPORT_MODULE_H
#include "SparseCore"
#include "src/Core/util/DisableStupidWarnings.h"
extern "C" {
#include <umfpack.h>
}
/** \ingroup Support_modules
* \defgroup UmfPackSupport_Module UmfPackSupport module
*
* This module provides an interface to the UmfPack library which is part of the <a href="http://www.suitesparse.com">suitesparse</a> package.
* It provides the following factorization class:
* - class UmfPackLU: a multifrontal sequential LU factorization.
*
* \code
* #include <Eigen/UmfPackSupport>
* \endcode
*
* In order to use this module, the umfpack headers must be accessible from the include paths, and your binary must be linked to the umfpack library and its dependencies.
* The dependencies depend on how umfpack has been compiled.
* For a cmake based project, you can use our FindUmfPack.cmake module to help you in this task.
*
*/
#include "src/UmfPackSupport/UmfPackSupport.h"
#include "src/Core/util/ReenableStupidWarnings.h"
#endif // EIGEN_UMFPACKSUPPORT_MODULE_H

673
external/include/eigen3/Eigen/src/Cholesky/LDLT.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,673 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2009 Keir Mierle <mierle@gmail.com>
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2011 Timothy E. Holy <tim.holy@gmail.com >
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_LDLT_H
#define EIGEN_LDLT_H
namespace Eigen {
namespace internal {
template<typename MatrixType, int UpLo> struct LDLT_Traits;
// PositiveSemiDef means positive semi-definite and non-zero; same for NegativeSemiDef
enum SignMatrix { PositiveSemiDef, NegativeSemiDef, ZeroSign, Indefinite };
}
/** \ingroup Cholesky_Module
*
* \class LDLT
*
* \brief Robust Cholesky decomposition of a matrix with pivoting
*
* \tparam _MatrixType the type of the matrix of which to compute the LDL^T Cholesky decomposition
* \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper.
* The other triangular part won't be read.
*
* Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite
* matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L
* is lower triangular with a unit diagonal and D is a diagonal matrix.
*
* The decomposition uses pivoting to ensure stability, so that L will have
* zeros in the bottom right rank(A) - n submatrix. Avoiding the square root
* on D also stabilizes the computation.
*
* Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky
* decomposition to determine whether a system of equations has a solution.
*
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
*
* \sa MatrixBase::ldlt(), SelfAdjointView::ldlt(), class LLT
*/
template<typename _MatrixType, int _UpLo> class LDLT
{
public:
typedef _MatrixType MatrixType;
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
UpLo = _UpLo
};
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
typedef typename MatrixType::StorageIndex StorageIndex;
typedef Matrix<Scalar, RowsAtCompileTime, 1, 0, MaxRowsAtCompileTime, 1> TmpMatrixType;
typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType;
typedef internal::LDLT_Traits<MatrixType,UpLo> Traits;
/** \brief Default Constructor.
*
* The default constructor is useful in cases in which the user intends to
* perform decompositions via LDLT::compute(const MatrixType&).
*/
LDLT()
: m_matrix(),
m_transpositions(),
m_sign(internal::ZeroSign),
m_isInitialized(false)
{}
/** \brief Default Constructor with memory preallocation
*
* Like the default constructor but with preallocation of the internal data
* according to the specified problem \a size.
* \sa LDLT()
*/
explicit LDLT(Index size)
: m_matrix(size, size),
m_transpositions(size),
m_temporary(size),
m_sign(internal::ZeroSign),
m_isInitialized(false)
{}
/** \brief Constructor with decomposition
*
* This calculates the decomposition for the input \a matrix.
*
* \sa LDLT(Index size)
*/
template<typename InputType>
explicit LDLT(const EigenBase<InputType>& matrix)
: m_matrix(matrix.rows(), matrix.cols()),
m_transpositions(matrix.rows()),
m_temporary(matrix.rows()),
m_sign(internal::ZeroSign),
m_isInitialized(false)
{
compute(matrix.derived());
}
/** \brief Constructs a LDLT factorization from a given matrix
*
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when \c MatrixType is a Eigen::Ref.
*
* \sa LDLT(const EigenBase&)
*/
template<typename InputType>
explicit LDLT(EigenBase<InputType>& matrix)
: m_matrix(matrix.derived()),
m_transpositions(matrix.rows()),
m_temporary(matrix.rows()),
m_sign(internal::ZeroSign),
m_isInitialized(false)
{
compute(matrix.derived());
}
/** Clear any existing decomposition
* \sa rankUpdate(w,sigma)
*/
void setZero()
{
m_isInitialized = false;
}
/** \returns a view of the upper triangular matrix U */
inline typename Traits::MatrixU matrixU() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return Traits::getU(m_matrix);
}
/** \returns a view of the lower triangular matrix L */
inline typename Traits::MatrixL matrixL() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return Traits::getL(m_matrix);
}
/** \returns the permutation matrix P as a transposition sequence.
*/
inline const TranspositionType& transpositionsP() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return m_transpositions;
}
/** \returns the coefficients of the diagonal matrix D */
inline Diagonal<const MatrixType> vectorD() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return m_matrix.diagonal();
}
/** \returns true if the matrix is positive (semidefinite) */
inline bool isPositive() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return m_sign == internal::PositiveSemiDef || m_sign == internal::ZeroSign;
}
/** \returns true if the matrix is negative (semidefinite) */
inline bool isNegative(void) const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return m_sign == internal::NegativeSemiDef || m_sign == internal::ZeroSign;
}
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
*
* This function also supports in-place solves using the syntax <tt>x = decompositionObject.solve(x)</tt> .
*
* \note_about_checking_solutions
*
* More precisely, this method solves \f$ A x = b \f$ using the decomposition \f$ A = P^T L D L^* P \f$
* by solving the systems \f$ P^T y_1 = b \f$, \f$ L y_2 = y_1 \f$, \f$ D y_3 = y_2 \f$,
* \f$ L^* y_4 = y_3 \f$ and \f$ P x = y_4 \f$ in succession. If the matrix \f$ A \f$ is singular, then
* \f$ D \f$ will also be singular (all the other matrices are invertible). In that case, the
* least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function
* computes the least-square solution of \f$ A x = b \f$ is \f$ A \f$ is singular.
*
* \sa MatrixBase::ldlt(), SelfAdjointView::ldlt()
*/
template<typename Rhs>
inline const Solve<LDLT, Rhs>
solve(const MatrixBase<Rhs>& b) const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
eigen_assert(m_matrix.rows()==b.rows()
&& "LDLT::solve(): invalid number of rows of the right hand side matrix b");
return Solve<LDLT, Rhs>(*this, b.derived());
}
template<typename Derived>
bool solveInPlace(MatrixBase<Derived> &bAndX) const;
template<typename InputType>
LDLT& compute(const EigenBase<InputType>& matrix);
/** \returns an estimate of the reciprocal condition number of the matrix of
* which \c *this is the LDLT decomposition.
*/
RealScalar rcond() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return internal::rcond_estimate_helper(m_l1_norm, *this);
}
template <typename Derived>
LDLT& rankUpdate(const MatrixBase<Derived>& w, const RealScalar& alpha=1);
/** \returns the internal LDLT decomposition matrix
*
* TODO: document the storage layout
*/
inline const MatrixType& matrixLDLT() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return m_matrix;
}
MatrixType reconstructedMatrix() const;
/** \returns the adjoint of \c *this, that is, a const reference to the decomposition itself as the underlying matrix is self-adjoint.
*
* This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as:
* \code x = decomposition.adjoint().solve(b) \endcode
*/
const LDLT& adjoint() const { return *this; };
inline Index rows() const { return m_matrix.rows(); }
inline Index cols() const { return m_matrix.cols(); }
/** \brief Reports whether previous computation was successful.
*
* \returns \c Success if computation was succesful,
* \c NumericalIssue if the factorization failed because of a zero pivot.
*/
ComputationInfo info() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
return m_info;
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename RhsType, typename DstType>
EIGEN_DEVICE_FUNC
void _solve_impl(const RhsType &rhs, DstType &dst) const;
#endif
protected:
static void check_template_parameters()
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
}
/** \internal
* Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
* The strict upper part is used during the decomposition, the strict lower
* part correspond to the coefficients of L (its diagonal is equal to 1 and
* is not stored), and the diagonal entries correspond to D.
*/
MatrixType m_matrix;
RealScalar m_l1_norm;
TranspositionType m_transpositions;
TmpMatrixType m_temporary;
internal::SignMatrix m_sign;
bool m_isInitialized;
ComputationInfo m_info;
};
namespace internal {
template<int UpLo> struct ldlt_inplace;
template<> struct ldlt_inplace<Lower>
{
template<typename MatrixType, typename TranspositionType, typename Workspace>
static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
{
using std::abs;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef typename TranspositionType::StorageIndex IndexType;
eigen_assert(mat.rows()==mat.cols());
const Index size = mat.rows();
bool found_zero_pivot = false;
bool ret = true;
if (size <= 1)
{
transpositions.setIdentity();
if(size==0) sign = ZeroSign;
else if (numext::real(mat.coeff(0,0)) > static_cast<RealScalar>(0) ) sign = PositiveSemiDef;
else if (numext::real(mat.coeff(0,0)) < static_cast<RealScalar>(0)) sign = NegativeSemiDef;
else sign = ZeroSign;
return true;
}
for (Index k = 0; k < size; ++k)
{
// Find largest diagonal element
Index index_of_biggest_in_corner;
mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner);
index_of_biggest_in_corner += k;
transpositions.coeffRef(k) = IndexType(index_of_biggest_in_corner);
if(k != index_of_biggest_in_corner)
{
// apply the transposition while taking care to consider only
// the lower triangular part
Index s = size-index_of_biggest_in_corner-1; // trailing size after the biggest element
mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner));
for(Index i=k+1;i<index_of_biggest_in_corner;++i)
{
Scalar tmp = mat.coeffRef(i,k);
mat.coeffRef(i,k) = numext::conj(mat.coeffRef(index_of_biggest_in_corner,i));
mat.coeffRef(index_of_biggest_in_corner,i) = numext::conj(tmp);
}
if(NumTraits<Scalar>::IsComplex)
mat.coeffRef(index_of_biggest_in_corner,k) = numext::conj(mat.coeff(index_of_biggest_in_corner,k));
}
// partition the matrix:
// A00 | - | -
// lu = A10 | A11 | -
// A20 | A21 | A22
Index rs = size - k - 1;
Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
if(k>0)
{
temp.head(k) = mat.diagonal().real().head(k).asDiagonal() * A10.adjoint();
mat.coeffRef(k,k) -= (A10 * temp.head(k)).value();
if(rs>0)
A21.noalias() -= A20 * temp.head(k);
}
// In some previous versions of Eigen (e.g., 3.2.1), the scaling was omitted if the pivot
// was smaller than the cutoff value. However, since LDLT is not rank-revealing
// we should only make sure that we do not introduce INF or NaN values.
// Remark that LAPACK also uses 0 as the cutoff value.
RealScalar realAkk = numext::real(mat.coeffRef(k,k));
bool pivot_is_valid = (abs(realAkk) > RealScalar(0));
if(k==0 && !pivot_is_valid)
{
// The entire diagonal is zero, there is nothing more to do
// except filling the transpositions, and checking whether the matrix is zero.
sign = ZeroSign;
for(Index j = 0; j<size; ++j)
{
transpositions.coeffRef(j) = IndexType(j);
ret = ret && (mat.col(j).tail(size-j-1).array()==Scalar(0)).all();
}
return ret;
}
if((rs>0) && pivot_is_valid)
A21 /= realAkk;
else if(rs>0)
ret = ret && (A21.array()==Scalar(0)).all();
if(found_zero_pivot && pivot_is_valid) ret = false; // factorization failed
else if(!pivot_is_valid) found_zero_pivot = true;
if (sign == PositiveSemiDef) {
if (realAkk < static_cast<RealScalar>(0)) sign = Indefinite;
} else if (sign == NegativeSemiDef) {
if (realAkk > static_cast<RealScalar>(0)) sign = Indefinite;
} else if (sign == ZeroSign) {
if (realAkk > static_cast<RealScalar>(0)) sign = PositiveSemiDef;
else if (realAkk < static_cast<RealScalar>(0)) sign = NegativeSemiDef;
}
}
return ret;
}
// Reference for the algorithm: Davis and Hager, "Multiple Rank
// Modifications of a Sparse Cholesky Factorization" (Algorithm 1)
// Trivial rearrangements of their computations (Timothy E. Holy)
// allow their algorithm to work for rank-1 updates even if the
// original matrix is not of full rank.
// Here only rank-1 updates are implemented, to reduce the
// requirement for intermediate storage and improve accuracy
template<typename MatrixType, typename WDerived>
static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, const typename MatrixType::RealScalar& sigma=1)
{
using numext::isfinite;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
const Index size = mat.rows();
eigen_assert(mat.cols() == size && w.size()==size);
RealScalar alpha = 1;
// Apply the update
for (Index j = 0; j < size; j++)
{
// Check for termination due to an original decomposition of low-rank
if (!(isfinite)(alpha))
break;
// Update the diagonal terms
RealScalar dj = numext::real(mat.coeff(j,j));
Scalar wj = w.coeff(j);
RealScalar swj2 = sigma*numext::abs2(wj);
RealScalar gamma = dj*alpha + swj2;
mat.coeffRef(j,j) += swj2/alpha;
alpha += swj2/dj;
// Update the terms of L
Index rs = size-j-1;
w.tail(rs) -= wj * mat.col(j).tail(rs);
if(gamma != 0)
mat.col(j).tail(rs) += (sigma*numext::conj(wj)/gamma)*w.tail(rs);
}
return true;
}
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, const typename MatrixType::RealScalar& sigma=1)
{
// Apply the permutation to the input w
tmp = transpositions * w;
return ldlt_inplace<Lower>::updateInPlace(mat,tmp,sigma);
}
};
template<> struct ldlt_inplace<Upper>
{
template<typename MatrixType, typename TranspositionType, typename Workspace>
static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, SignMatrix& sign)
{
Transpose<MatrixType> matt(mat);
return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
}
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType>
static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, const typename MatrixType::RealScalar& sigma=1)
{
Transpose<MatrixType> matt(mat);
return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma);
}
};
template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower>
{
typedef const TriangularView<const MatrixType, UnitLower> MatrixL;
typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); }
static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); }
};
template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
{
typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
typedef const TriangularView<const MatrixType, UnitUpper> MatrixU;
static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); }
static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); }
};
} // end namespace internal
/** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix
*/
template<typename MatrixType, int _UpLo>
template<typename InputType>
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>& a)
{
check_template_parameters();
eigen_assert(a.rows()==a.cols());
const Index size = a.rows();
m_matrix = a.derived();
// Compute matrix L1 norm = max abs column sum.
m_l1_norm = RealScalar(0);
// TODO move this code to SelfAdjointView
for (Index col = 0; col < size; ++col) {
RealScalar abs_col_sum;
if (_UpLo == Lower)
abs_col_sum = m_matrix.col(col).tail(size - col).template lpNorm<1>() + m_matrix.row(col).head(col).template lpNorm<1>();
else
abs_col_sum = m_matrix.col(col).head(col).template lpNorm<1>() + m_matrix.row(col).tail(size - col).template lpNorm<1>();
if (abs_col_sum > m_l1_norm)
m_l1_norm = abs_col_sum;
}
m_transpositions.resize(size);
m_isInitialized = false;
m_temporary.resize(size);
m_sign = internal::ZeroSign;
m_info = internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, m_sign) ? Success : NumericalIssue;
m_isInitialized = true;
return *this;
}
/** Update the LDLT decomposition: given A = L D L^T, efficiently compute the decomposition of A + sigma w w^T.
* \param w a vector to be incorporated into the decomposition.
* \param sigma a scalar, +1 for updates and -1 for "downdates," which correspond to removing previously-added column vectors. Optional; default value is +1.
* \sa setZero()
*/
template<typename MatrixType, int _UpLo>
template<typename Derived>
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w, const typename LDLT<MatrixType,_UpLo>::RealScalar& sigma)
{
typedef typename TranspositionType::StorageIndex IndexType;
const Index size = w.rows();
if (m_isInitialized)
{
eigen_assert(m_matrix.rows()==size);
}
else
{
m_matrix.resize(size,size);
m_matrix.setZero();
m_transpositions.resize(size);
for (Index i = 0; i < size; i++)
m_transpositions.coeffRef(i) = IndexType(i);
m_temporary.resize(size);
m_sign = sigma>=0 ? internal::PositiveSemiDef : internal::NegativeSemiDef;
m_isInitialized = true;
}
internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma);
return *this;
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename _MatrixType, int _UpLo>
template<typename RhsType, typename DstType>
void LDLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const
{
eigen_assert(rhs.rows() == rows());
// dst = P b
dst = m_transpositions * rhs;
// dst = L^-1 (P b)
matrixL().solveInPlace(dst);
// dst = D^-1 (L^-1 P b)
// more precisely, use pseudo-inverse of D (see bug 241)
using std::abs;
const typename Diagonal<const MatrixType>::RealReturnType vecD(vectorD());
// In some previous versions, tolerance was set to the max of 1/highest (or rather numeric_limits::min())
// and the maximal diagonal entry * epsilon as motivated by LAPACK's xGELSS:
// RealScalar tolerance = numext::maxi(vecD.array().abs().maxCoeff() * NumTraits<RealScalar>::epsilon(),RealScalar(1) / NumTraits<RealScalar>::highest());
// However, LDLT is not rank revealing, and so adjusting the tolerance wrt to the highest
// diagonal element is not well justified and leads to numerical issues in some cases.
// Moreover, Lapack's xSYTRS routines use 0 for the tolerance.
// Using numeric_limits::min() gives us more robustness to denormals.
RealScalar tolerance = (std::numeric_limits<RealScalar>::min)();
for (Index i = 0; i < vecD.size(); ++i)
{
if(abs(vecD(i)) > tolerance)
dst.row(i) /= vecD(i);
else
dst.row(i).setZero();
}
// dst = L^-T (D^-1 L^-1 P b)
matrixU().solveInPlace(dst);
// dst = P^-1 (L^-T D^-1 L^-1 P b) = A^-1 b
dst = m_transpositions.transpose() * dst;
}
#endif
/** \internal use x = ldlt_object.solve(x);
*
* This is the \em in-place version of solve().
*
* \param bAndX represents both the right-hand side matrix b and result x.
*
* \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
*
* This version avoids a copy when the right hand side matrix b is not
* needed anymore.
*
* \sa LDLT::solve(), MatrixBase::ldlt()
*/
template<typename MatrixType,int _UpLo>
template<typename Derived>
bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
eigen_assert(m_matrix.rows() == bAndX.rows());
bAndX = this->solve(bAndX);
return true;
}
/** \returns the matrix represented by the decomposition,
* i.e., it returns the product: P^T L D L^* P.
* This function is provided for debug purpose. */
template<typename MatrixType, int _UpLo>
MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
{
eigen_assert(m_isInitialized && "LDLT is not initialized.");
const Index size = m_matrix.rows();
MatrixType res(size,size);
// P
res.setIdentity();
res = transpositionsP() * res;
// L^* P
res = matrixU() * res;
// D(L^*P)
res = vectorD().real().asDiagonal() * res;
// L(DL^*P)
res = matrixL() * res;
// P^T (LDL^*P)
res = transpositionsP().transpose() * res;
return res;
}
/** \cholesky_module
* \returns the Cholesky decomposition with full pivoting without square root of \c *this
* \sa MatrixBase::ldlt()
*/
template<typename MatrixType, unsigned int UpLo>
inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
SelfAdjointView<MatrixType, UpLo>::ldlt() const
{
return LDLT<PlainObject,UpLo>(m_matrix);
}
/** \cholesky_module
* \returns the Cholesky decomposition with full pivoting without square root of \c *this
* \sa SelfAdjointView::ldlt()
*/
template<typename Derived>
inline const LDLT<typename MatrixBase<Derived>::PlainObject>
MatrixBase<Derived>::ldlt() const
{
return LDLT<PlainObject>(derived());
}
} // end namespace Eigen
#endif // EIGEN_LDLT_H

542
external/include/eigen3/Eigen/src/Cholesky/LLT.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,542 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_LLT_H
#define EIGEN_LLT_H
namespace Eigen {
namespace internal{
template<typename MatrixType, int UpLo> struct LLT_Traits;
}
/** \ingroup Cholesky_Module
*
* \class LLT
*
* \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features
*
* \tparam _MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition
* \tparam _UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper.
* The other triangular part won't be read.
*
* This class performs a LL^T Cholesky decomposition of a symmetric, positive definite
* matrix A such that A = LL^* = U^*U, where L is lower triangular.
*
* While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b,
* for that purpose, we recommend the Cholesky decomposition without square root which is more stable
* and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other
* situations like generalised eigen problems with hermitian matrices.
*
* Remember that Cholesky decompositions are not rank-revealing. This LLT decomposition is only stable on positive definite matrices,
* use LDLT instead for the semidefinite case. Also, do not use a Cholesky decomposition to determine whether a system of equations
* has a solution.
*
* Example: \include LLT_example.cpp
* Output: \verbinclude LLT_example.out
*
* \b Performance: for best performance, it is recommended to use a column-major storage format
* with the Lower triangular part (the default), or, equivalently, a row-major storage format
* with the Upper triangular part. Otherwise, you might get a 20% slowdown for the full factorization
* step, and rank-updates can be up to 3 times slower.
*
* This class supports the \link InplaceDecomposition inplace decomposition \endlink mechanism.
*
* Note that during the decomposition, only the lower (or upper, as defined by _UpLo) triangular part of A is considered.
* Therefore, the strict lower part does not have to store correct values.
*
* \sa MatrixBase::llt(), SelfAdjointView::llt(), class LDLT
*/
template<typename _MatrixType, int _UpLo> class LLT
{
public:
typedef _MatrixType MatrixType;
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
typedef typename MatrixType::Scalar Scalar;
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
typedef typename MatrixType::StorageIndex StorageIndex;
enum {
PacketSize = internal::packet_traits<Scalar>::size,
AlignmentMask = int(PacketSize)-1,
UpLo = _UpLo
};
typedef internal::LLT_Traits<MatrixType,UpLo> Traits;
/**
* \brief Default Constructor.
*
* The default constructor is useful in cases in which the user intends to
* perform decompositions via LLT::compute(const MatrixType&).
*/
LLT() : m_matrix(), m_isInitialized(false) {}
/** \brief Default Constructor with memory preallocation
*
* Like the default constructor but with preallocation of the internal data
* according to the specified problem \a size.
* \sa LLT()
*/
explicit LLT(Index size) : m_matrix(size, size),
m_isInitialized(false) {}
template<typename InputType>
explicit LLT(const EigenBase<InputType>& matrix)
: m_matrix(matrix.rows(), matrix.cols()),
m_isInitialized(false)
{
compute(matrix.derived());
}
/** \brief Constructs a LDLT factorization from a given matrix
*
* This overloaded constructor is provided for \link InplaceDecomposition inplace decomposition \endlink when
* \c MatrixType is a Eigen::Ref.
*
* \sa LLT(const EigenBase&)
*/
template<typename InputType>
explicit LLT(EigenBase<InputType>& matrix)
: m_matrix(matrix.derived()),
m_isInitialized(false)
{
compute(matrix.derived());
}
/** \returns a view of the upper triangular matrix U */
inline typename Traits::MatrixU matrixU() const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
return Traits::getU(m_matrix);
}
/** \returns a view of the lower triangular matrix L */
inline typename Traits::MatrixL matrixL() const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
return Traits::getL(m_matrix);
}
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
*
* Since this LLT class assumes anyway that the matrix A is invertible, the solution
* theoretically exists and is unique regardless of b.
*
* Example: \include LLT_solve.cpp
* Output: \verbinclude LLT_solve.out
*
* \sa solveInPlace(), MatrixBase::llt(), SelfAdjointView::llt()
*/
template<typename Rhs>
inline const Solve<LLT, Rhs>
solve(const MatrixBase<Rhs>& b) const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
eigen_assert(m_matrix.rows()==b.rows()
&& "LLT::solve(): invalid number of rows of the right hand side matrix b");
return Solve<LLT, Rhs>(*this, b.derived());
}
template<typename Derived>
void solveInPlace(const MatrixBase<Derived> &bAndX) const;
template<typename InputType>
LLT& compute(const EigenBase<InputType>& matrix);
/** \returns an estimate of the reciprocal condition number of the matrix of
* which \c *this is the Cholesky decomposition.
*/
RealScalar rcond() const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
eigen_assert(m_info == Success && "LLT failed because matrix appears to be negative");
return internal::rcond_estimate_helper(m_l1_norm, *this);
}
/** \returns the LLT decomposition matrix
*
* TODO: document the storage layout
*/
inline const MatrixType& matrixLLT() const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
return m_matrix;
}
MatrixType reconstructedMatrix() const;
/** \brief Reports whether previous computation was successful.
*
* \returns \c Success if computation was succesful,
* \c NumericalIssue if the matrix.appears not to be positive definite.
*/
ComputationInfo info() const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
return m_info;
}
/** \returns the adjoint of \c *this, that is, a const reference to the decomposition itself as the underlying matrix is self-adjoint.
*
* This method is provided for compatibility with other matrix decompositions, thus enabling generic code such as:
* \code x = decomposition.adjoint().solve(b) \endcode
*/
const LLT& adjoint() const { return *this; };
inline Index rows() const { return m_matrix.rows(); }
inline Index cols() const { return m_matrix.cols(); }
template<typename VectorType>
LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1);
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename RhsType, typename DstType>
EIGEN_DEVICE_FUNC
void _solve_impl(const RhsType &rhs, DstType &dst) const;
#endif
protected:
static void check_template_parameters()
{
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar);
}
/** \internal
* Used to compute and store L
* The strict upper part is not used and even not initialized.
*/
MatrixType m_matrix;
RealScalar m_l1_norm;
bool m_isInitialized;
ComputationInfo m_info;
};
namespace internal {
template<typename Scalar, int UpLo> struct llt_inplace;
template<typename MatrixType, typename VectorType>
static Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma)
{
using std::sqrt;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef typename MatrixType::ColXpr ColXpr;
typedef typename internal::remove_all<ColXpr>::type ColXprCleaned;
typedef typename ColXprCleaned::SegmentReturnType ColXprSegment;
typedef Matrix<Scalar,Dynamic,1> TempVectorType;
typedef typename TempVectorType::SegmentReturnType TempVecSegment;
Index n = mat.cols();
eigen_assert(mat.rows()==n && vec.size()==n);
TempVectorType temp;
if(sigma>0)
{
// This version is based on Givens rotations.
// It is faster than the other one below, but only works for updates,
// i.e., for sigma > 0
temp = sqrt(sigma) * vec;
for(Index i=0; i<n; ++i)
{
JacobiRotation<Scalar> g;
g.makeGivens(mat(i,i), -temp(i), &mat(i,i));
Index rs = n-i-1;
if(rs>0)
{
ColXprSegment x(mat.col(i).tail(rs));
TempVecSegment y(temp.tail(rs));
apply_rotation_in_the_plane(x, y, g);
}
}
}
else
{
temp = vec;
RealScalar beta = 1;
for(Index j=0; j<n; ++j)
{
RealScalar Ljj = numext::real(mat.coeff(j,j));
RealScalar dj = numext::abs2(Ljj);
Scalar wj = temp.coeff(j);
RealScalar swj2 = sigma*numext::abs2(wj);
RealScalar gamma = dj*beta + swj2;
RealScalar x = dj + swj2/beta;
if (x<=RealScalar(0))
return j;
RealScalar nLjj = sqrt(x);
mat.coeffRef(j,j) = nLjj;
beta += swj2/dj;
// Update the terms of L
Index rs = n-j-1;
if(rs)
{
temp.tail(rs) -= (wj/Ljj) * mat.col(j).tail(rs);
if(gamma != 0)
mat.col(j).tail(rs) = (nLjj/Ljj) * mat.col(j).tail(rs) + (nLjj * sigma*numext::conj(wj)/gamma)*temp.tail(rs);
}
}
}
return -1;
}
template<typename Scalar> struct llt_inplace<Scalar, Lower>
{
typedef typename NumTraits<Scalar>::Real RealScalar;
template<typename MatrixType>
static Index unblocked(MatrixType& mat)
{
using std::sqrt;
eigen_assert(mat.rows()==mat.cols());
const Index size = mat.rows();
for(Index k = 0; k < size; ++k)
{
Index rs = size-k-1; // remaining size
Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
RealScalar x = numext::real(mat.coeff(k,k));
if (k>0) x -= A10.squaredNorm();
if (x<=RealScalar(0))
return k;
mat.coeffRef(k,k) = x = sqrt(x);
if (k>0 && rs>0) A21.noalias() -= A20 * A10.adjoint();
if (rs>0) A21 /= x;
}
return -1;
}
template<typename MatrixType>
static Index blocked(MatrixType& m)
{
eigen_assert(m.rows()==m.cols());
Index size = m.rows();
if(size<32)
return unblocked(m);
Index blockSize = size/8;
blockSize = (blockSize/16)*16;
blockSize = (std::min)((std::max)(blockSize,Index(8)), Index(128));
for (Index k=0; k<size; k+=blockSize)
{
// partition the matrix:
// A00 | - | -
// lu = A10 | A11 | -
// A20 | A21 | A22
Index bs = (std::min)(blockSize, size-k);
Index rs = size - k - bs;
Block<MatrixType,Dynamic,Dynamic> A11(m,k, k, bs,bs);
Block<MatrixType,Dynamic,Dynamic> A21(m,k+bs,k, rs,bs);
Block<MatrixType,Dynamic,Dynamic> A22(m,k+bs,k+bs,rs,rs);
Index ret;
if((ret=unblocked(A11))>=0) return k+ret;
if(rs>0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21);
if(rs>0) A22.template selfadjointView<Lower>().rankUpdate(A21,typename NumTraits<RealScalar>::Literal(-1)); // bottleneck
}
return -1;
}
template<typename MatrixType, typename VectorType>
static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma)
{
return Eigen::internal::llt_rank_update_lower(mat, vec, sigma);
}
};
template<typename Scalar> struct llt_inplace<Scalar, Upper>
{
typedef typename NumTraits<Scalar>::Real RealScalar;
template<typename MatrixType>
static EIGEN_STRONG_INLINE Index unblocked(MatrixType& mat)
{
Transpose<MatrixType> matt(mat);
return llt_inplace<Scalar, Lower>::unblocked(matt);
}
template<typename MatrixType>
static EIGEN_STRONG_INLINE Index blocked(MatrixType& mat)
{
Transpose<MatrixType> matt(mat);
return llt_inplace<Scalar, Lower>::blocked(matt);
}
template<typename MatrixType, typename VectorType>
static Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma)
{
Transpose<MatrixType> matt(mat);
return llt_inplace<Scalar, Lower>::rankUpdate(matt, vec.conjugate(), sigma);
}
};
template<typename MatrixType> struct LLT_Traits<MatrixType,Lower>
{
typedef const TriangularView<const MatrixType, Lower> MatrixL;
typedef const TriangularView<const typename MatrixType::AdjointReturnType, Upper> MatrixU;
static inline MatrixL getL(const MatrixType& m) { return MatrixL(m); }
static inline MatrixU getU(const MatrixType& m) { return MatrixU(m.adjoint()); }
static bool inplace_decomposition(MatrixType& m)
{ return llt_inplace<typename MatrixType::Scalar, Lower>::blocked(m)==-1; }
};
template<typename MatrixType> struct LLT_Traits<MatrixType,Upper>
{
typedef const TriangularView<const typename MatrixType::AdjointReturnType, Lower> MatrixL;
typedef const TriangularView<const MatrixType, Upper> MatrixU;
static inline MatrixL getL(const MatrixType& m) { return MatrixL(m.adjoint()); }
static inline MatrixU getU(const MatrixType& m) { return MatrixU(m); }
static bool inplace_decomposition(MatrixType& m)
{ return llt_inplace<typename MatrixType::Scalar, Upper>::blocked(m)==-1; }
};
} // end namespace internal
/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
*
* \returns a reference to *this
*
* Example: \include TutorialLinAlgComputeTwice.cpp
* Output: \verbinclude TutorialLinAlgComputeTwice.out
*/
template<typename MatrixType, int _UpLo>
template<typename InputType>
LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const EigenBase<InputType>& a)
{
check_template_parameters();
eigen_assert(a.rows()==a.cols());
const Index size = a.rows();
m_matrix.resize(size, size);
if (!internal::is_same_dense(m_matrix, a.derived()))
m_matrix = a.derived();
// Compute matrix L1 norm = max abs column sum.
m_l1_norm = RealScalar(0);
// TODO move this code to SelfAdjointView
for (Index col = 0; col < size; ++col) {
RealScalar abs_col_sum;
if (_UpLo == Lower)
abs_col_sum = m_matrix.col(col).tail(size - col).template lpNorm<1>() + m_matrix.row(col).head(col).template lpNorm<1>();
else
abs_col_sum = m_matrix.col(col).head(col).template lpNorm<1>() + m_matrix.row(col).tail(size - col).template lpNorm<1>();
if (abs_col_sum > m_l1_norm)
m_l1_norm = abs_col_sum;
}
m_isInitialized = true;
bool ok = Traits::inplace_decomposition(m_matrix);
m_info = ok ? Success : NumericalIssue;
return *this;
}
/** Performs a rank one update (or dowdate) of the current decomposition.
* If A = LL^* before the rank one update,
* then after it we have LL^* = A + sigma * v v^* where \a v must be a vector
* of same dimension.
*/
template<typename _MatrixType, int _UpLo>
template<typename VectorType>
LLT<_MatrixType,_UpLo> LLT<_MatrixType,_UpLo>::rankUpdate(const VectorType& v, const RealScalar& sigma)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType);
eigen_assert(v.size()==m_matrix.cols());
eigen_assert(m_isInitialized);
if(internal::llt_inplace<typename MatrixType::Scalar, UpLo>::rankUpdate(m_matrix,v,sigma)>=0)
m_info = NumericalIssue;
else
m_info = Success;
return *this;
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename _MatrixType,int _UpLo>
template<typename RhsType, typename DstType>
void LLT<_MatrixType,_UpLo>::_solve_impl(const RhsType &rhs, DstType &dst) const
{
dst = rhs;
solveInPlace(dst);
}
#endif
/** \internal use x = llt_object.solve(x);
*
* This is the \em in-place version of solve().
*
* \param bAndX represents both the right-hand side matrix b and result x.
*
* This version avoids a copy when the right hand side matrix b is not needed anymore.
*
* \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here.
* This function will const_cast it, so constness isn't honored here.
*
* \sa LLT::solve(), MatrixBase::llt()
*/
template<typename MatrixType, int _UpLo>
template<typename Derived>
void LLT<MatrixType,_UpLo>::solveInPlace(const MatrixBase<Derived> &bAndX) const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
eigen_assert(m_matrix.rows()==bAndX.rows());
matrixL().solveInPlace(bAndX);
matrixU().solveInPlace(bAndX);
}
/** \returns the matrix represented by the decomposition,
* i.e., it returns the product: L L^*.
* This function is provided for debug purpose. */
template<typename MatrixType, int _UpLo>
MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const
{
eigen_assert(m_isInitialized && "LLT is not initialized.");
return matrixL() * matrixL().adjoint().toDenseMatrix();
}
/** \cholesky_module
* \returns the LLT decomposition of \c *this
* \sa SelfAdjointView::llt()
*/
template<typename Derived>
inline const LLT<typename MatrixBase<Derived>::PlainObject>
MatrixBase<Derived>::llt() const
{
return LLT<PlainObject>(derived());
}
/** \cholesky_module
* \returns the LLT decomposition of \c *this
* \sa SelfAdjointView::llt()
*/
template<typename MatrixType, unsigned int UpLo>
inline const LLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
SelfAdjointView<MatrixType, UpLo>::llt() const
{
return LLT<PlainObject,UpLo>(m_matrix);
}
} // end namespace Eigen
#endif // EIGEN_LLT_H

مشاهده پرونده

@@ -0,0 +1,99 @@
/*
Copyright (c) 2011, Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************
* Content : Eigen bindings to LAPACKe
* LLt decomposition based on LAPACKE_?potrf function.
********************************************************************************
*/
#ifndef EIGEN_LLT_LAPACKE_H
#define EIGEN_LLT_LAPACKE_H
namespace Eigen {
namespace internal {
template<typename Scalar> struct lapacke_llt;
#define EIGEN_LAPACKE_LLT(EIGTYPE, BLASTYPE, LAPACKE_PREFIX) \
template<> struct lapacke_llt<EIGTYPE> \
{ \
template<typename MatrixType> \
static inline Index potrf(MatrixType& m, char uplo) \
{ \
lapack_int matrix_order; \
lapack_int size, lda, info, StorageOrder; \
EIGTYPE* a; \
eigen_assert(m.rows()==m.cols()); \
/* Set up parameters for ?potrf */ \
size = convert_index<lapack_int>(m.rows()); \
StorageOrder = MatrixType::Flags&RowMajorBit?RowMajor:ColMajor; \
matrix_order = StorageOrder==RowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \
a = &(m.coeffRef(0,0)); \
lda = convert_index<lapack_int>(m.outerStride()); \
\
info = LAPACKE_##LAPACKE_PREFIX##potrf( matrix_order, uplo, size, (BLASTYPE*)a, lda ); \
info = (info==0) ? -1 : info>0 ? info-1 : size; \
return info; \
} \
}; \
template<> struct llt_inplace<EIGTYPE, Lower> \
{ \
template<typename MatrixType> \
static Index blocked(MatrixType& m) \
{ \
return lapacke_llt<EIGTYPE>::potrf(m, 'L'); \
} \
template<typename MatrixType, typename VectorType> \
static Index rankUpdate(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) \
{ return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); } \
}; \
template<> struct llt_inplace<EIGTYPE, Upper> \
{ \
template<typename MatrixType> \
static Index blocked(MatrixType& m) \
{ \
return lapacke_llt<EIGTYPE>::potrf(m, 'U'); \
} \
template<typename MatrixType, typename VectorType> \
static Index rankUpdate(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) \
{ \
Transpose<MatrixType> matt(mat); \
return llt_inplace<EIGTYPE, Lower>::rankUpdate(matt, vec.conjugate(), sigma); \
} \
};
EIGEN_LAPACKE_LLT(double, double, d)
EIGEN_LAPACKE_LLT(float, float, s)
EIGEN_LAPACKE_LLT(dcomplex, lapack_complex_double, z)
EIGEN_LAPACKE_LLT(scomplex, lapack_complex_float, c)
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_LLT_LAPACKE_H

مشاهده پرونده

@@ -0,0 +1,639 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_CHOLMODSUPPORT_H
#define EIGEN_CHOLMODSUPPORT_H
namespace Eigen {
namespace internal {
template<typename Scalar> struct cholmod_configure_matrix;
template<> struct cholmod_configure_matrix<double> {
template<typename CholmodType>
static void run(CholmodType& mat) {
mat.xtype = CHOLMOD_REAL;
mat.dtype = CHOLMOD_DOUBLE;
}
};
template<> struct cholmod_configure_matrix<std::complex<double> > {
template<typename CholmodType>
static void run(CholmodType& mat) {
mat.xtype = CHOLMOD_COMPLEX;
mat.dtype = CHOLMOD_DOUBLE;
}
};
// Other scalar types are not yet suppotred by Cholmod
// template<> struct cholmod_configure_matrix<float> {
// template<typename CholmodType>
// static void run(CholmodType& mat) {
// mat.xtype = CHOLMOD_REAL;
// mat.dtype = CHOLMOD_SINGLE;
// }
// };
//
// template<> struct cholmod_configure_matrix<std::complex<float> > {
// template<typename CholmodType>
// static void run(CholmodType& mat) {
// mat.xtype = CHOLMOD_COMPLEX;
// mat.dtype = CHOLMOD_SINGLE;
// }
// };
} // namespace internal
/** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object.
* Note that the data are shared.
*/
template<typename _Scalar, int _Options, typename _StorageIndex>
cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> > mat)
{
cholmod_sparse res;
res.nzmax = mat.nonZeros();
res.nrow = mat.rows();
res.ncol = mat.cols();
res.p = mat.outerIndexPtr();
res.i = mat.innerIndexPtr();
res.x = mat.valuePtr();
res.z = 0;
res.sorted = 1;
if(mat.isCompressed())
{
res.packed = 1;
res.nz = 0;
}
else
{
res.packed = 0;
res.nz = mat.innerNonZeroPtr();
}
res.dtype = 0;
res.stype = -1;
if (internal::is_same<_StorageIndex,int>::value)
{
res.itype = CHOLMOD_INT;
}
else if (internal::is_same<_StorageIndex,long>::value)
{
res.itype = CHOLMOD_LONG;
}
else
{
eigen_assert(false && "Index type not supported yet");
}
// setup res.xtype
internal::cholmod_configure_matrix<_Scalar>::run(res);
res.stype = 0;
return res;
}
template<typename _Scalar, int _Options, typename _Index>
const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat)
{
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
return res;
}
template<typename _Scalar, int _Options, typename _Index>
const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat)
{
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived()));
return res;
}
/** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix.
* The data are not copied but shared. */
template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo>
cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat)
{
cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived()));
if(UpLo==Upper) res.stype = 1;
if(UpLo==Lower) res.stype = -1;
return res;
}
/** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix.
* The data are not copied but shared. */
template<typename Derived>
cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat)
{
EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
typedef typename Derived::Scalar Scalar;
cholmod_dense res;
res.nrow = mat.rows();
res.ncol = mat.cols();
res.nzmax = res.nrow * res.ncol;
res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride();
res.x = (void*)(mat.derived().data());
res.z = 0;
internal::cholmod_configure_matrix<Scalar>::run(res);
return res;
}
/** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix.
* The data are not copied but shared. */
template<typename Scalar, int Flags, typename StorageIndex>
MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm)
{
return MappedSparseMatrix<Scalar,Flags,StorageIndex>
(cm.nrow, cm.ncol, static_cast<StorageIndex*>(cm.p)[cm.ncol],
static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
}
enum CholmodMode {
CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
};
/** \ingroup CholmodSupport_Module
* \class CholmodBase
* \brief The base class for the direct Cholesky factorization of Cholmod
* \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT
*/
template<typename _MatrixType, int _UpLo, typename Derived>
class CholmodBase : public SparseSolverBase<Derived>
{
protected:
typedef SparseSolverBase<Derived> Base;
using Base::derived;
using Base::m_isInitialized;
public:
typedef _MatrixType MatrixType;
enum { UpLo = _UpLo };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef MatrixType CholMatrixType;
typedef typename MatrixType::StorageIndex StorageIndex;
enum {
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
public:
CholmodBase()
: m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
{
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
cholmod_start(&m_cholmod);
}
explicit CholmodBase(const MatrixType& matrix)
: m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false)
{
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
cholmod_start(&m_cholmod);
compute(matrix);
}
~CholmodBase()
{
if(m_cholmodFactor)
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
cholmod_finish(&m_cholmod);
}
inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
/** \brief Reports whether previous computation was successful.
*
* \returns \c Success if computation was succesful,
* \c NumericalIssue if the matrix.appears to be negative.
*/
ComputationInfo info() const
{
eigen_assert(m_isInitialized && "Decomposition is not initialized.");
return m_info;
}
/** Computes the sparse Cholesky decomposition of \a matrix */
Derived& compute(const MatrixType& matrix)
{
analyzePattern(matrix);
factorize(matrix);
return derived();
}
/** Performs a symbolic decomposition on the sparsity pattern of \a matrix.
*
* This function is particularly useful when solving for several problems having the same structure.
*
* \sa factorize()
*/
void analyzePattern(const MatrixType& matrix)
{
if(m_cholmodFactor)
{
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
m_cholmodFactor = 0;
}
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
this->m_isInitialized = true;
this->m_info = Success;
m_analysisIsOk = true;
m_factorizationIsOk = false;
}
/** Performs a numeric decomposition of \a matrix
*
* The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed.
*
* \sa analyzePattern()
*/
void factorize(const MatrixType& matrix)
{
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
// If the factorization failed, minor is the column at which it did. On success minor == n.
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
m_factorizationIsOk = true;
}
/** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations.
* See the Cholmod user guide for details. */
cholmod_common& cholmod() { return m_cholmod; }
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal */
template<typename Rhs,typename Dest>
void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const
{
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
const Index size = m_cholmodFactor->n;
EIGEN_UNUSED_VARIABLE(size);
eigen_assert(size==b.rows());
// Cholmod needs column-major stoarge without inner-stride, which corresponds to the default behavior of Ref.
Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.derived());
cholmod_dense b_cd = viewAsCholmod(b_ref);
cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
if(!x_cd)
{
this->m_info = NumericalIssue;
return;
}
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
cholmod_free_dense(&x_cd, &m_cholmod);
}
/** \internal */
template<typename RhsDerived, typename DestDerived>
void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const
{
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
const Index size = m_cholmodFactor->n;
EIGEN_UNUSED_VARIABLE(size);
eigen_assert(size==b.rows());
// note: cs stands for Cholmod Sparse
Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
cholmod_sparse b_cs = viewAsCholmod(b_ref);
cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
if(!x_cs)
{
this->m_info = NumericalIssue;
return;
}
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
cholmod_free_sparse(&x_cs, &m_cholmod);
}
#endif // EIGEN_PARSED_BY_DOXYGEN
/** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization.
*
* During the numerical factorization, an offset term is added to the diagonal coefficients:\n
* \c d_ii = \a offset + \c d_ii
*
* The default is \a offset=0.
*
* \returns a reference to \c *this.
*/
Derived& setShift(const RealScalar& offset)
{
m_shiftOffset[0] = double(offset);
return derived();
}
/** \returns the determinant of the underlying matrix from the current factorization */
Scalar determinant() const
{
using std::exp;
return exp(logDeterminant());
}
/** \returns the log determinant of the underlying matrix from the current factorization */
Scalar logDeterminant() const
{
using std::log;
using numext::real;
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()");
RealScalar logDet = 0;
Scalar *x = static_cast<Scalar*>(m_cholmodFactor->x);
if (m_cholmodFactor->is_super)
{
// Supernodal factorization stored as a packed list of dense column-major blocs,
// as described by the following structure:
// super[k] == index of the first column of the j-th super node
StorageIndex *super = static_cast<StorageIndex*>(m_cholmodFactor->super);
// pi[k] == offset to the description of row indices
StorageIndex *pi = static_cast<StorageIndex*>(m_cholmodFactor->pi);
// px[k] == offset to the respective dense block
StorageIndex *px = static_cast<StorageIndex*>(m_cholmodFactor->px);
Index nb_super_nodes = m_cholmodFactor->nsuper;
for (Index k=0; k < nb_super_nodes; ++k)
{
StorageIndex ncols = super[k + 1] - super[k];
StorageIndex nrows = pi[k + 1] - pi[k];
Map<const Array<Scalar,1,Dynamic>, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows+1));
logDet += sk.real().log().sum();
}
}
else
{
// Simplicial factorization stored as standard CSC matrix.
StorageIndex *p = static_cast<StorageIndex*>(m_cholmodFactor->p);
Index size = m_cholmodFactor->n;
for (Index k=0; k<size; ++k)
logDet += log(real( x[p[k]] ));
}
if (m_cholmodFactor->is_ll)
logDet *= 2.0;
return logDet;
};
template<typename Stream>
void dumpMemory(Stream& /*s*/)
{}
protected:
mutable cholmod_common m_cholmod;
cholmod_factor* m_cholmodFactor;
double m_shiftOffset[2];
mutable ComputationInfo m_info;
int m_factorizationIsOk;
int m_analysisIsOk;
};
/** \ingroup CholmodSupport_Module
* \class CholmodSimplicialLLT
* \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod
*
* This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization
* using the Cholmod library.
* This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical interest.
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
*
* \implsparsesolverconcept
*
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
*
* \warning Only double precision real and complex scalar types are supported by Cholmod.
*
* \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT
*/
template<typename _MatrixType, int _UpLo = Lower>
class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> >
{
typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base;
using Base::m_cholmod;
public:
typedef _MatrixType MatrixType;
CholmodSimplicialLLT() : Base() { init(); }
CholmodSimplicialLLT(const MatrixType& matrix) : Base()
{
init();
this->compute(matrix);
}
~CholmodSimplicialLLT() {}
protected:
void init()
{
m_cholmod.final_asis = 0;
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
m_cholmod.final_ll = 1;
}
};
/** \ingroup CholmodSupport_Module
* \class CholmodSimplicialLDLT
* \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod
*
* This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization
* using the Cholmod library.
* This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical interest.
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
*
* \implsparsesolverconcept
*
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
*
* \warning Only double precision real and complex scalar types are supported by Cholmod.
*
* \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT
*/
template<typename _MatrixType, int _UpLo = Lower>
class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> >
{
typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base;
using Base::m_cholmod;
public:
typedef _MatrixType MatrixType;
CholmodSimplicialLDLT() : Base() { init(); }
CholmodSimplicialLDLT(const MatrixType& matrix) : Base()
{
init();
this->compute(matrix);
}
~CholmodSimplicialLDLT() {}
protected:
void init()
{
m_cholmod.final_asis = 1;
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
}
};
/** \ingroup CholmodSupport_Module
* \class CholmodSupernodalLLT
* \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod
*
* This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization
* using the Cholmod library.
* This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM.
* The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
*
* \implsparsesolverconcept
*
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
*
* \warning Only double precision real and complex scalar types are supported by Cholmod.
*
* \sa \ref TutorialSparseSolverConcept
*/
template<typename _MatrixType, int _UpLo = Lower>
class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> >
{
typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base;
using Base::m_cholmod;
public:
typedef _MatrixType MatrixType;
CholmodSupernodalLLT() : Base() { init(); }
CholmodSupernodalLLT(const MatrixType& matrix) : Base()
{
init();
this->compute(matrix);
}
~CholmodSupernodalLLT() {}
protected:
void init()
{
m_cholmod.final_asis = 1;
m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
}
};
/** \ingroup CholmodSupport_Module
* \class CholmodDecomposition
* \brief A general Cholesky factorization and solver based on Cholmod
*
* This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization
* using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices
* X and B can be either dense or sparse.
*
* This variant permits to change the underlying Cholesky method at runtime.
* On the other hand, it does not provide access to the result of the factorization.
* The default is to let Cholmod automatically choose between a simplicial and supernodal factorization.
*
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<>
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower
* or Upper. Default is Lower.
*
* \implsparsesolverconcept
*
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed.
*
* \warning Only double precision real and complex scalar types are supported by Cholmod.
*
* \sa \ref TutorialSparseSolverConcept
*/
template<typename _MatrixType, int _UpLo = Lower>
class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> >
{
typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base;
using Base::m_cholmod;
public:
typedef _MatrixType MatrixType;
CholmodDecomposition() : Base() { init(); }
CholmodDecomposition(const MatrixType& matrix) : Base()
{
init();
this->compute(matrix);
}
~CholmodDecomposition() {}
void setMode(CholmodMode mode)
{
switch(mode)
{
case CholmodAuto:
m_cholmod.final_asis = 1;
m_cholmod.supernodal = CHOLMOD_AUTO;
break;
case CholmodSimplicialLLt:
m_cholmod.final_asis = 0;
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
m_cholmod.final_ll = 1;
break;
case CholmodSupernodalLLt:
m_cholmod.final_asis = 1;
m_cholmod.supernodal = CHOLMOD_SUPERNODAL;
break;
case CholmodLDLt:
m_cholmod.final_asis = 1;
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL;
break;
default:
break;
}
}
protected:
void init()
{
m_cholmod.final_asis = 1;
m_cholmod.supernodal = CHOLMOD_AUTO;
}
};
} // end namespace Eigen
#endif // EIGEN_CHOLMODSUPPORT_H

329
external/include/eigen3/Eigen/src/Core/Array.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,329 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ARRAY_H
#define EIGEN_ARRAY_H
namespace Eigen {
namespace internal {
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
struct traits<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > : traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
{
typedef ArrayXpr XprKind;
typedef ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > XprBase;
};
}
/** \class Array
* \ingroup Core_Module
*
* \brief General-purpose arrays with easy API for coefficient-wise operations
*
* The %Array class is very similar to the Matrix class. It provides
* general-purpose one- and two-dimensional arrays. The difference between the
* %Array and the %Matrix class is primarily in the API: the API for the
* %Array class provides easy access to coefficient-wise operations, while the
* API for the %Matrix class provides easy access to linear-algebra
* operations.
*
* See documentation of class Matrix for detailed information on the template parameters
* storage layout.
*
* This class can be extended with the help of the plugin mechanism described on the page
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_ARRAY_PLUGIN.
*
* \sa \blank \ref TutorialArrayClass, \ref TopicClassHierarchy
*/
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
class Array
: public PlainObjectBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
{
public:
typedef PlainObjectBase<Array> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Array)
enum { Options = _Options };
typedef typename Base::PlainObject PlainObject;
protected:
template <typename Derived, typename OtherDerived, bool IsVector>
friend struct internal::conservative_resize_like_impl;
using Base::m_storage;
public:
using Base::base;
using Base::coeff;
using Base::coeffRef;
/**
* The usage of
* using Base::operator=;
* fails on MSVC. Since the code below is working with GCC and MSVC, we skipped
* the usage of 'using'. This should be done only for operator=.
*/
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const EigenBase<OtherDerived> &other)
{
return Base::operator=(other);
}
/** Set all the entries to \a value.
* \sa DenseBase::setConstant(), DenseBase::fill()
*/
/* This overload is needed because the usage of
* using Base::operator=;
* fails on MSVC. Since the code below is working with GCC and MSVC, we skipped
* the usage of 'using'. This should be done only for operator=.
*/
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const Scalar &value)
{
Base::setConstant(value);
return *this;
}
/** Copies the value of the expression \a other into \c *this with automatic resizing.
*
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
* it will be initialized.
*
* Note that copying a row-vector into a vector (and conversely) is allowed.
* The resizing, if any, is then done in the appropriate way so that row-vectors
* remain row-vectors and vectors remain vectors.
*/
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const DenseBase<OtherDerived>& other)
{
return Base::_set(other);
}
/** This is a special case of the templated operator=. Its purpose is to
* prevent a default operator= from hiding the templated operator=.
*/
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array& operator=(const Array& other)
{
return Base::_set(other);
}
/** Default constructor.
*
* For fixed-size matrices, does nothing.
*
* For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix
* is called a null matrix. This constructor is the unique way to create null matrices: resizing
* a matrix to 0 is not supported.
*
* \sa resize(Index,Index)
*/
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array() : Base()
{
Base::_check_template_params();
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
// FIXME is it still needed ??
/** \internal */
EIGEN_DEVICE_FUNC
Array(internal::constructor_without_unaligned_array_assert)
: Base(internal::constructor_without_unaligned_array_assert())
{
Base::_check_template_params();
EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
}
#endif
#if EIGEN_HAS_RVALUE_REFERENCES
EIGEN_DEVICE_FUNC
Array(Array&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_constructible<Scalar>::value)
: Base(std::move(other))
{
Base::_check_template_params();
}
EIGEN_DEVICE_FUNC
Array& operator=(Array&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value)
{
other.swap(*this);
return *this;
}
#endif
#ifndef EIGEN_PARSED_BY_DOXYGEN
template<typename T>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE explicit Array(const T& x)
{
Base::_check_template_params();
Base::template _init1<T>(x);
}
template<typename T0, typename T1>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const T0& val0, const T1& val1)
{
Base::_check_template_params();
this->template _init2<T0,T1>(val0, val1);
}
#else
/** \brief Constructs a fixed-sized array initialized with coefficients starting at \a data */
EIGEN_DEVICE_FUNC explicit Array(const Scalar *data);
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
*
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors,
* it is redundant to pass the dimension here, so it makes more sense to use the default
* constructor Array() instead.
*/
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE explicit Array(Index dim);
/** constructs an initialized 1x1 Array with the given coefficient */
Array(const Scalar& value);
/** constructs an uninitialized array with \a rows rows and \a cols columns.
*
* This is useful for dynamic-size arrays. For fixed-size arrays,
* it is redundant to pass these parameters, so one should use the default constructor
* Array() instead. */
Array(Index rows, Index cols);
/** constructs an initialized 2D vector with given coefficients */
Array(const Scalar& val0, const Scalar& val1);
#endif
/** constructs an initialized 3D vector with given coefficients */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2)
{
Base::_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3)
m_storage.data()[0] = val0;
m_storage.data()[1] = val1;
m_storage.data()[2] = val2;
}
/** constructs an initialized 4D vector with given coefficients */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const Scalar& val0, const Scalar& val1, const Scalar& val2, const Scalar& val3)
{
Base::_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4)
m_storage.data()[0] = val0;
m_storage.data()[1] = val1;
m_storage.data()[2] = val2;
m_storage.data()[3] = val3;
}
/** Copy constructor */
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const Array& other)
: Base(other)
{ }
private:
struct PrivateType {};
public:
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other,
typename internal::enable_if<internal::is_convertible<typename OtherDerived::Scalar,Scalar>::value,
PrivateType>::type = PrivateType())
: Base(other.derived())
{ }
EIGEN_DEVICE_FUNC inline Index innerStride() const { return 1; }
EIGEN_DEVICE_FUNC inline Index outerStride() const { return this->innerSize(); }
#ifdef EIGEN_ARRAY_PLUGIN
#include EIGEN_ARRAY_PLUGIN
#endif
private:
template<typename MatrixType, typename OtherDerived, bool SwapPointers>
friend struct internal::matrix_swap_impl;
};
/** \defgroup arraytypedefs Global array typedefs
* \ingroup Core_Module
*
* Eigen defines several typedef shortcuts for most common 1D and 2D array types.
*
* The general patterns are the following:
*
* \c ArrayRowsColsType where \c Rows and \c Cols can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size,
* and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c cd
* for complex double.
*
* For example, \c Array33d is a fixed-size 3x3 array type of doubles, and \c ArrayXXf is a dynamic-size matrix of floats.
*
* There are also \c ArraySizeType which are self-explanatory. For example, \c Array4cf is
* a fixed-size 1D array of 4 complex floats.
*
* \sa class Array
*/
#define EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
/** \ingroup arraytypedefs */ \
typedef Array<Type, Size, Size> Array##SizeSuffix##SizeSuffix##TypeSuffix; \
/** \ingroup arraytypedefs */ \
typedef Array<Type, Size, 1> Array##SizeSuffix##TypeSuffix;
#define EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \
/** \ingroup arraytypedefs */ \
typedef Array<Type, Size, Dynamic> Array##Size##X##TypeSuffix; \
/** \ingroup arraytypedefs */ \
typedef Array<Type, Dynamic, Size> Array##X##Size##TypeSuffix;
#define EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 2, 2) \
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 3, 3) \
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 4, 4) \
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 4)
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(int, i)
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(float, f)
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(double, d)
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<float>, cf)
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
#undef EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES
#undef EIGEN_MAKE_ARRAY_TYPEDEFS
#undef EIGEN_MAKE_ARRAY_TYPEDEFS_LARGE
#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
using Eigen::Matrix##SizeSuffix##TypeSuffix; \
using Eigen::Vector##SizeSuffix##TypeSuffix; \
using Eigen::RowVector##SizeSuffix##TypeSuffix;
#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(TypeSuffix) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
#define EIGEN_USING_ARRAY_TYPEDEFS \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(i) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(f) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(d) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cf) \
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cd)
} // end namespace Eigen
#endif // EIGEN_ARRAY_H

226
external/include/eigen3/Eigen/src/Core/ArrayBase.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,226 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ARRAYBASE_H
#define EIGEN_ARRAYBASE_H
namespace Eigen {
template<typename ExpressionType> class MatrixWrapper;
/** \class ArrayBase
* \ingroup Core_Module
*
* \brief Base class for all 1D and 2D array, and related expressions
*
* An array is similar to a dense vector or matrix. While matrices are mathematical
* objects with well defined linear algebra operators, an array is just a collection
* of scalar values arranged in a one or two dimensionnal fashion. As the main consequence,
* all operations applied to an array are performed coefficient wise. Furthermore,
* arrays support scalar math functions of the c++ standard library (e.g., std::sin(x)), and convenient
* constructors allowing to easily write generic code working for both scalar values
* and arrays.
*
* This class is the base that is inherited by all array expression types.
*
* \tparam Derived is the derived type, e.g., an array or an expression type.
*
* This class can be extended with the help of the plugin mechanism described on the page
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_ARRAYBASE_PLUGIN.
*
* \sa class MatrixBase, \ref TopicClassHierarchy
*/
template<typename Derived> class ArrayBase
: public DenseBase<Derived>
{
public:
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** The base class for a given storage type. */
typedef ArrayBase StorageBaseType;
typedef ArrayBase Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl;
typedef typename internal::traits<Derived>::StorageKind StorageKind;
typedef typename internal::traits<Derived>::Scalar Scalar;
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef DenseBase<Derived> Base;
using Base::RowsAtCompileTime;
using Base::ColsAtCompileTime;
using Base::SizeAtCompileTime;
using Base::MaxRowsAtCompileTime;
using Base::MaxColsAtCompileTime;
using Base::MaxSizeAtCompileTime;
using Base::IsVectorAtCompileTime;
using Base::Flags;
using Base::derived;
using Base::const_cast_derived;
using Base::rows;
using Base::cols;
using Base::size;
using Base::coeff;
using Base::coeffRef;
using Base::lazyAssign;
using Base::operator=;
using Base::operator+=;
using Base::operator-=;
using Base::operator*=;
using Base::operator/=;
typedef typename Base::CoeffReturnType CoeffReturnType;
#endif // not EIGEN_PARSED_BY_DOXYGEN
#ifndef EIGEN_PARSED_BY_DOXYGEN
typedef typename Base::PlainObject PlainObject;
/** \internal Represents a matrix with all coefficients equal to one another*/
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,PlainObject> ConstantReturnType;
#endif // not EIGEN_PARSED_BY_DOXYGEN
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase
#define EIGEN_DOC_UNARY_ADDONS(X,Y)
# include "../plugins/CommonCwiseUnaryOps.h"
# include "../plugins/MatrixCwiseUnaryOps.h"
# include "../plugins/ArrayCwiseUnaryOps.h"
# include "../plugins/CommonCwiseBinaryOps.h"
# include "../plugins/MatrixCwiseBinaryOps.h"
# include "../plugins/ArrayCwiseBinaryOps.h"
# ifdef EIGEN_ARRAYBASE_PLUGIN
# include EIGEN_ARRAYBASE_PLUGIN
# endif
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
#undef EIGEN_DOC_UNARY_ADDONS
/** Special case of the template operator=, in order to prevent the compiler
* from generating a default operator= (issue hit with g++ 4.1)
*/
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator=(const ArrayBase& other)
{
internal::call_assignment(derived(), other.derived());
return derived();
}
/** Set all the entries to \a value.
* \sa DenseBase::setConstant(), DenseBase::fill() */
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator=(const Scalar &value)
{ Base::setConstant(value); return derived(); }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator+=(const Scalar& scalar);
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator-=(const Scalar& scalar);
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator+=(const ArrayBase<OtherDerived>& other);
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator-=(const ArrayBase<OtherDerived>& other);
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator*=(const ArrayBase<OtherDerived>& other);
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
Derived& operator/=(const ArrayBase<OtherDerived>& other);
public:
EIGEN_DEVICE_FUNC
ArrayBase<Derived>& array() { return *this; }
EIGEN_DEVICE_FUNC
const ArrayBase<Derived>& array() const { return *this; }
/** \returns an \link Eigen::MatrixBase Matrix \endlink expression of this array
* \sa MatrixBase::array() */
EIGEN_DEVICE_FUNC
MatrixWrapper<Derived> matrix() { return MatrixWrapper<Derived>(derived()); }
EIGEN_DEVICE_FUNC
const MatrixWrapper<const Derived> matrix() const { return MatrixWrapper<const Derived>(derived()); }
// template<typename Dest>
// inline void evalTo(Dest& dst) const { dst = matrix(); }
protected:
EIGEN_DEVICE_FUNC
ArrayBase() : Base() {}
private:
explicit ArrayBase(Index);
ArrayBase(Index,Index);
template<typename OtherDerived> explicit ArrayBase(const ArrayBase<OtherDerived>&);
protected:
// mixing arrays and matrices is not legal
template<typename OtherDerived> Derived& operator+=(const MatrixBase<OtherDerived>& )
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;}
// mixing arrays and matrices is not legal
template<typename OtherDerived> Derived& operator-=(const MatrixBase<OtherDerived>& )
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;}
};
/** replaces \c *this by \c *this - \a other.
*
* \returns a reference to \c *this
*/
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
ArrayBase<Derived>::operator-=(const ArrayBase<OtherDerived> &other)
{
call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
return derived();
}
/** replaces \c *this by \c *this + \a other.
*
* \returns a reference to \c *this
*/
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
ArrayBase<Derived>::operator+=(const ArrayBase<OtherDerived>& other)
{
call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
return derived();
}
/** replaces \c *this by \c *this * \a other coefficient wise.
*
* \returns a reference to \c *this
*/
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
ArrayBase<Derived>::operator*=(const ArrayBase<OtherDerived>& other)
{
call_assignment(derived(), other.derived(), internal::mul_assign_op<Scalar,typename OtherDerived::Scalar>());
return derived();
}
/** replaces \c *this by \c *this / \a other coefficient wise.
*
* \returns a reference to \c *this
*/
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
ArrayBase<Derived>::operator/=(const ArrayBase<OtherDerived>& other)
{
call_assignment(derived(), other.derived(), internal::div_assign_op<Scalar,typename OtherDerived::Scalar>());
return derived();
}
} // end namespace Eigen
#endif // EIGEN_ARRAYBASE_H

209
external/include/eigen3/Eigen/src/Core/ArrayWrapper.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,209 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ARRAYWRAPPER_H
#define EIGEN_ARRAYWRAPPER_H
namespace Eigen {
/** \class ArrayWrapper
* \ingroup Core_Module
*
* \brief Expression of a mathematical vector or matrix as an array object
*
* This class is the return type of MatrixBase::array(), and most of the time
* this is the only way it is use.
*
* \sa MatrixBase::array(), class MatrixWrapper
*/
namespace internal {
template<typename ExpressionType>
struct traits<ArrayWrapper<ExpressionType> >
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
{
typedef ArrayXpr XprKind;
// Let's remove NestByRefBit
enum {
Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
LvalueBitFlag = is_lvalue<ExpressionType>::value ? LvalueBit : 0,
Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag
};
};
}
template<typename ExpressionType>
class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
{
public:
typedef ArrayBase<ArrayWrapper> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper)
typedef typename internal::remove_all<ExpressionType>::type NestedExpression;
typedef typename internal::conditional<
internal::is_lvalue<ExpressionType>::value,
Scalar,
const Scalar
>::type ScalarWithConstIfNotLvalue;
typedef typename internal::ref_selector<ExpressionType>::non_const_type NestedExpressionType;
using Base::coeffRef;
EIGEN_DEVICE_FUNC
explicit EIGEN_STRONG_INLINE ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_expression.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_expression.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_expression.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_expression.innerStride(); }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return m_expression.data(); }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index rowId, Index colId) const
{
return m_expression.coeffRef(rowId, colId);
}
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const
{
return m_expression.coeffRef(index);
}
template<typename Dest>
EIGEN_DEVICE_FUNC
inline void evalTo(Dest& dst) const { dst = m_expression; }
const typename internal::remove_all<NestedExpressionType>::type&
EIGEN_DEVICE_FUNC
nestedExpression() const
{
return m_expression;
}
/** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index) */
EIGEN_DEVICE_FUNC
void resize(Index newSize) { m_expression.resize(newSize); }
/** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index,Index)*/
EIGEN_DEVICE_FUNC
void resize(Index rows, Index cols) { m_expression.resize(rows,cols); }
protected:
NestedExpressionType m_expression;
};
/** \class MatrixWrapper
* \ingroup Core_Module
*
* \brief Expression of an array as a mathematical vector or matrix
*
* This class is the return type of ArrayBase::matrix(), and most of the time
* this is the only way it is use.
*
* \sa MatrixBase::matrix(), class ArrayWrapper
*/
namespace internal {
template<typename ExpressionType>
struct traits<MatrixWrapper<ExpressionType> >
: public traits<typename remove_all<typename ExpressionType::Nested>::type >
{
typedef MatrixXpr XprKind;
// Let's remove NestByRefBit
enum {
Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
LvalueBitFlag = is_lvalue<ExpressionType>::value ? LvalueBit : 0,
Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag
};
};
}
template<typename ExpressionType>
class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
{
public:
typedef MatrixBase<MatrixWrapper<ExpressionType> > Base;
EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper)
typedef typename internal::remove_all<ExpressionType>::type NestedExpression;
typedef typename internal::conditional<
internal::is_lvalue<ExpressionType>::value,
Scalar,
const Scalar
>::type ScalarWithConstIfNotLvalue;
typedef typename internal::ref_selector<ExpressionType>::non_const_type NestedExpressionType;
using Base::coeffRef;
EIGEN_DEVICE_FUNC
explicit inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {}
EIGEN_DEVICE_FUNC
inline Index rows() const { return m_expression.rows(); }
EIGEN_DEVICE_FUNC
inline Index cols() const { return m_expression.cols(); }
EIGEN_DEVICE_FUNC
inline Index outerStride() const { return m_expression.outerStride(); }
EIGEN_DEVICE_FUNC
inline Index innerStride() const { return m_expression.innerStride(); }
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
EIGEN_DEVICE_FUNC
inline const Scalar* data() const { return m_expression.data(); }
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index rowId, Index colId) const
{
return m_expression.derived().coeffRef(rowId, colId);
}
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const
{
return m_expression.coeffRef(index);
}
EIGEN_DEVICE_FUNC
const typename internal::remove_all<NestedExpressionType>::type&
nestedExpression() const
{
return m_expression;
}
/** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index) */
EIGEN_DEVICE_FUNC
void resize(Index newSize) { m_expression.resize(newSize); }
/** Forwards the resizing request to the nested expression
* \sa DenseBase::resize(Index,Index)*/
EIGEN_DEVICE_FUNC
void resize(Index rows, Index cols) { m_expression.resize(rows,cols); }
protected:
NestedExpressionType m_expression;
};
} // end namespace Eigen
#endif // EIGEN_ARRAYWRAPPER_H

90
external/include/eigen3/Eigen/src/Core/Assign.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,90 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2007 Michael Olbrich <michael.olbrich@gmx.net>
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ASSIGN_H
#define EIGEN_ASSIGN_H
namespace Eigen {
template<typename Derived>
template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
::lazyAssign(const DenseBase<OtherDerived>& other)
{
enum{
SameType = internal::is_same<typename Derived::Scalar,typename OtherDerived::Scalar>::value
};
EIGEN_STATIC_ASSERT_LVALUE(Derived)
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
eigen_assert(rows() == other.rows() && cols() == other.cols());
internal::call_assignment_no_alias(derived(),other.derived());
return derived();
}
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
{
internal::call_assignment(derived(), other.derived());
return derived();
}
template<typename Derived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other)
{
internal::call_assignment(derived(), other.derived());
return derived();
}
template<typename Derived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other)
{
internal::call_assignment(derived(), other.derived());
return derived();
}
template<typename Derived>
template <typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
{
internal::call_assignment(derived(), other.derived());
return derived();
}
template<typename Derived>
template <typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
{
internal::call_assignment(derived(), other.derived());
return derived();
}
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
{
other.derived().evalTo(derived());
return derived();
}
} // end namespace Eigen
#endif // EIGEN_ASSIGN_H

935
external/include/eigen3/Eigen/src/Core/AssignEvaluator.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,935 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2011-2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef EIGEN_ASSIGN_EVALUATOR_H
#define EIGEN_ASSIGN_EVALUATOR_H
namespace Eigen {
// This implementation is based on Assign.h
namespace internal {
/***************************************************************************
* Part 1 : the logic deciding a strategy for traversal and unrolling *
***************************************************************************/
// copy_using_evaluator_traits is based on assign_traits
template <typename DstEvaluator, typename SrcEvaluator, typename AssignFunc>
struct copy_using_evaluator_traits
{
typedef typename DstEvaluator::XprType Dst;
typedef typename Dst::Scalar DstScalar;
enum {
DstFlags = DstEvaluator::Flags,
SrcFlags = SrcEvaluator::Flags
};
public:
enum {
DstAlignment = DstEvaluator::Alignment,
SrcAlignment = SrcEvaluator::Alignment,
DstHasDirectAccess = (DstFlags & DirectAccessBit) == DirectAccessBit,
JointAlignment = EIGEN_PLAIN_ENUM_MIN(DstAlignment,SrcAlignment)
};
private:
enum {
InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime)
: int(DstFlags)&RowMajorBit ? int(Dst::ColsAtCompileTime)
: int(Dst::RowsAtCompileTime),
InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime)
: int(DstFlags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime)
: int(Dst::MaxRowsAtCompileTime),
OuterStride = int(outer_stride_at_compile_time<Dst>::ret),
MaxSizeAtCompileTime = Dst::SizeAtCompileTime
};
// TODO distinguish between linear traversal and inner-traversals
typedef typename find_best_packet<DstScalar,Dst::SizeAtCompileTime>::type LinearPacketType;
typedef typename find_best_packet<DstScalar,InnerSize>::type InnerPacketType;
enum {
LinearPacketSize = unpacket_traits<LinearPacketType>::size,
InnerPacketSize = unpacket_traits<InnerPacketType>::size
};
public:
enum {
LinearRequiredAlignment = unpacket_traits<LinearPacketType>::alignment,
InnerRequiredAlignment = unpacket_traits<InnerPacketType>::alignment
};
private:
enum {
DstIsRowMajor = DstFlags&RowMajorBit,
SrcIsRowMajor = SrcFlags&RowMajorBit,
StorageOrdersAgree = (int(DstIsRowMajor) == int(SrcIsRowMajor)),
MightVectorize = bool(StorageOrdersAgree)
&& (int(DstFlags) & int(SrcFlags) & ActualPacketAccessBit)
&& bool(functor_traits<AssignFunc>::PacketAccess),
MayInnerVectorize = MightVectorize
&& int(InnerSize)!=Dynamic && int(InnerSize)%int(InnerPacketSize)==0
&& int(OuterStride)!=Dynamic && int(OuterStride)%int(InnerPacketSize)==0
&& (EIGEN_UNALIGNED_VECTORIZE || int(JointAlignment)>=int(InnerRequiredAlignment)),
MayLinearize = bool(StorageOrdersAgree) && (int(DstFlags) & int(SrcFlags) & LinearAccessBit),
MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize) && bool(DstHasDirectAccess)
&& (EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)) || MaxSizeAtCompileTime == Dynamic),
/* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
so it's only good for large enough sizes. */
MaySliceVectorize = bool(MightVectorize) && bool(DstHasDirectAccess)
&& (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=(EIGEN_UNALIGNED_VECTORIZE?InnerPacketSize:(3*InnerPacketSize)))
/* slice vectorization can be slow, so we only want it if the slices are big, which is
indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
in a fixed-size matrix
However, with EIGEN_UNALIGNED_VECTORIZE and unrolling, slice vectorization is still worth it */
};
public:
enum {
Traversal = int(MayLinearVectorize) && (LinearPacketSize>InnerPacketSize) ? int(LinearVectorizedTraversal)
: int(MayInnerVectorize) ? int(InnerVectorizedTraversal)
: int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
: int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
: int(MayLinearize) ? int(LinearTraversal)
: int(DefaultTraversal),
Vectorized = int(Traversal) == InnerVectorizedTraversal
|| int(Traversal) == LinearVectorizedTraversal
|| int(Traversal) == SliceVectorizedTraversal
};
typedef typename conditional<int(Traversal)==LinearVectorizedTraversal, LinearPacketType, InnerPacketType>::type PacketType;
private:
enum {
ActualPacketSize = int(Traversal)==LinearVectorizedTraversal ? LinearPacketSize
: Vectorized ? InnerPacketSize
: 1,
UnrollingLimit = EIGEN_UNROLLING_LIMIT * ActualPacketSize,
MayUnrollCompletely = int(Dst::SizeAtCompileTime) != Dynamic
&& int(Dst::SizeAtCompileTime) * (int(DstEvaluator::CoeffReadCost)+int(SrcEvaluator::CoeffReadCost)) <= int(UnrollingLimit),
MayUnrollInner = int(InnerSize) != Dynamic
&& int(InnerSize) * (int(DstEvaluator::CoeffReadCost)+int(SrcEvaluator::CoeffReadCost)) <= int(UnrollingLimit)
};
public:
enum {
Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal))
? (
int(MayUnrollCompletely) ? int(CompleteUnrolling)
: int(MayUnrollInner) ? int(InnerUnrolling)
: int(NoUnrolling)
)
: int(Traversal) == int(LinearVectorizedTraversal)
? ( bool(MayUnrollCompletely) && ( EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)))
? int(CompleteUnrolling)
: int(NoUnrolling) )
: int(Traversal) == int(LinearTraversal)
? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
: int(NoUnrolling) )
#if EIGEN_UNALIGNED_VECTORIZE
: int(Traversal) == int(SliceVectorizedTraversal)
? ( bool(MayUnrollInner) ? int(InnerUnrolling)
: int(NoUnrolling) )
#endif
: int(NoUnrolling)
};
#ifdef EIGEN_DEBUG_ASSIGN
static void debug()
{
std::cerr << "DstXpr: " << typeid(typename DstEvaluator::XprType).name() << std::endl;
std::cerr << "SrcXpr: " << typeid(typename SrcEvaluator::XprType).name() << std::endl;
std::cerr.setf(std::ios::hex, std::ios::basefield);
std::cerr << "DstFlags" << " = " << DstFlags << " (" << demangle_flags(DstFlags) << " )" << std::endl;
std::cerr << "SrcFlags" << " = " << SrcFlags << " (" << demangle_flags(SrcFlags) << " )" << std::endl;
std::cerr.unsetf(std::ios::hex);
EIGEN_DEBUG_VAR(DstAlignment)
EIGEN_DEBUG_VAR(SrcAlignment)
EIGEN_DEBUG_VAR(LinearRequiredAlignment)
EIGEN_DEBUG_VAR(InnerRequiredAlignment)
EIGEN_DEBUG_VAR(JointAlignment)
EIGEN_DEBUG_VAR(InnerSize)
EIGEN_DEBUG_VAR(InnerMaxSize)
EIGEN_DEBUG_VAR(LinearPacketSize)
EIGEN_DEBUG_VAR(InnerPacketSize)
EIGEN_DEBUG_VAR(ActualPacketSize)
EIGEN_DEBUG_VAR(StorageOrdersAgree)
EIGEN_DEBUG_VAR(MightVectorize)
EIGEN_DEBUG_VAR(MayLinearize)
EIGEN_DEBUG_VAR(MayInnerVectorize)
EIGEN_DEBUG_VAR(MayLinearVectorize)
EIGEN_DEBUG_VAR(MaySliceVectorize)
std::cerr << "Traversal" << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl;
EIGEN_DEBUG_VAR(SrcEvaluator::CoeffReadCost)
EIGEN_DEBUG_VAR(UnrollingLimit)
EIGEN_DEBUG_VAR(MayUnrollCompletely)
EIGEN_DEBUG_VAR(MayUnrollInner)
std::cerr << "Unrolling" << " = " << Unrolling << " (" << demangle_unrolling(Unrolling) << ")" << std::endl;
std::cerr << std::endl;
}
#endif
};
/***************************************************************************
* Part 2 : meta-unrollers
***************************************************************************/
/************************
*** Default traversal ***
************************/
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling
{
// FIXME: this is not very clean, perhaps this information should be provided by the kernel?
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
typedef typename DstEvaluatorType::XprType DstXprType;
enum {
outer = Index / DstXprType::InnerSizeAtCompileTime,
inner = Index % DstXprType::InnerSizeAtCompileTime
};
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
kernel.assignCoeffByOuterInner(outer, inner);
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Index+1, Stop>::run(kernel);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Stop, Stop>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
};
template<typename Kernel, int Index_, int Stop>
struct copy_using_evaluator_DefaultTraversal_InnerUnrolling
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
{
kernel.assignCoeffByOuterInner(outer, Index_);
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, Index_+1, Stop>::run(kernel, outer);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, Stop, Stop>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&, Index) { }
};
/***********************
*** Linear traversal ***
***********************/
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_LinearTraversal_CompleteUnrolling
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel)
{
kernel.assignCoeff(Index);
copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Index+1, Stop>::run(kernel);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Stop, Stop>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
};
/**************************
*** Inner vectorization ***
**************************/
template<typename Kernel, int Index, int Stop>
struct copy_using_evaluator_innervec_CompleteUnrolling
{
// FIXME: this is not very clean, perhaps this information should be provided by the kernel?
typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
typedef typename DstEvaluatorType::XprType DstXprType;
typedef typename Kernel::PacketType PacketType;
enum {
outer = Index / DstXprType::InnerSizeAtCompileTime,
inner = Index % DstXprType::InnerSizeAtCompileTime,
SrcAlignment = Kernel::AssignmentTraits::SrcAlignment,
DstAlignment = Kernel::AssignmentTraits::DstAlignment
};
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, inner);
enum { NextIndex = Index + unpacket_traits<PacketType>::size };
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, NextIndex, Stop>::run(kernel);
}
};
template<typename Kernel, int Stop>
struct copy_using_evaluator_innervec_CompleteUnrolling<Kernel, Stop, Stop>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
};
template<typename Kernel, int Index_, int Stop, int SrcAlignment, int DstAlignment>
struct copy_using_evaluator_innervec_InnerUnrolling
{
typedef typename Kernel::PacketType PacketType;
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
{
kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, Index_);
enum { NextIndex = Index_ + unpacket_traits<PacketType>::size };
copy_using_evaluator_innervec_InnerUnrolling<Kernel, NextIndex, Stop, SrcAlignment, DstAlignment>::run(kernel, outer);
}
};
template<typename Kernel, int Stop, int SrcAlignment, int DstAlignment>
struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop, SrcAlignment, DstAlignment>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &, Index) { }
};
/***************************************************************************
* Part 3 : implementation of all cases
***************************************************************************/
// dense_assignment_loop is based on assign_impl
template<typename Kernel,
int Traversal = Kernel::AssignmentTraits::Traversal,
int Unrolling = Kernel::AssignmentTraits::Unrolling>
struct dense_assignment_loop;
/************************
*** Default traversal ***
************************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, DefaultTraversal, NoUnrolling>
{
EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE run(Kernel &kernel)
{
for(Index outer = 0; outer < kernel.outerSize(); ++outer) {
for(Index inner = 0; inner < kernel.innerSize(); ++inner) {
kernel.assignCoeffByOuterInner(outer, inner);
}
}
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, DefaultTraversal, CompleteUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, DefaultTraversal, InnerUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
const Index outerSize = kernel.outerSize();
for(Index outer = 0; outer < outerSize; ++outer)
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime>::run(kernel, outer);
}
};
/***************************
*** Linear vectorization ***
***************************/
// The goal of unaligned_dense_assignment_loop is simply to factorize the handling
// of the non vectorizable beginning and ending parts
template <bool IsAligned = false>
struct unaligned_dense_assignment_loop
{
// if IsAligned = true, then do nothing
template <typename Kernel>
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&, Index, Index) {}
};
template <>
struct unaligned_dense_assignment_loop<false>
{
// MSVC must not inline this functions. If it does, it fails to optimize the
// packet access path.
// FIXME check which version exhibits this issue
#if EIGEN_COMP_MSVC
template <typename Kernel>
static EIGEN_DONT_INLINE void run(Kernel &kernel,
Index start,
Index end)
#else
template <typename Kernel>
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel,
Index start,
Index end)
#endif
{
for (Index index = start; index < end; ++index)
kernel.assignCoeff(index);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, NoUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
const Index size = kernel.size();
typedef typename Kernel::Scalar Scalar;
typedef typename Kernel::PacketType PacketType;
enum {
requestedAlignment = Kernel::AssignmentTraits::LinearRequiredAlignment,
packetSize = unpacket_traits<PacketType>::size,
dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment)>=int(requestedAlignment),
dstAlignment = packet_traits<Scalar>::AlignedOnScalar ? int(requestedAlignment)
: int(Kernel::AssignmentTraits::DstAlignment),
srcAlignment = Kernel::AssignmentTraits::JointAlignment
};
const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned<requestedAlignment>(kernel.dstDataPtr(), size);
const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
unaligned_dense_assignment_loop<dstIsAligned!=0>::run(kernel, 0, alignedStart);
for(Index index = alignedStart; index < alignedEnd; index += packetSize)
kernel.template assignPacket<dstAlignment, srcAlignment, PacketType>(index);
unaligned_dense_assignment_loop<>::run(kernel, alignedEnd, size);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, CompleteUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
typedef typename Kernel::PacketType PacketType;
enum { size = DstXprType::SizeAtCompileTime,
packetSize =unpacket_traits<PacketType>::size,
alignedSize = (size/packetSize)*packetSize };
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, alignedSize>::run(kernel);
copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, alignedSize, size>::run(kernel);
}
};
/**************************
*** Inner vectorization ***
**************************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, NoUnrolling>
{
typedef typename Kernel::PacketType PacketType;
enum {
SrcAlignment = Kernel::AssignmentTraits::SrcAlignment,
DstAlignment = Kernel::AssignmentTraits::DstAlignment
};
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
const Index innerSize = kernel.innerSize();
const Index outerSize = kernel.outerSize();
const Index packetSize = unpacket_traits<PacketType>::size;
for(Index outer = 0; outer < outerSize; ++outer)
for(Index inner = 0; inner < innerSize; inner+=packetSize)
kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, inner);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, CompleteUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, InnerUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
typedef typename Kernel::AssignmentTraits Traits;
const Index outerSize = kernel.outerSize();
for(Index outer = 0; outer < outerSize; ++outer)
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime,
Traits::SrcAlignment, Traits::DstAlignment>::run(kernel, outer);
}
};
/***********************
*** Linear traversal ***
***********************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearTraversal, NoUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
const Index size = kernel.size();
for(Index i = 0; i < size; ++i)
kernel.assignCoeff(i);
}
};
template<typename Kernel>
struct dense_assignment_loop<Kernel, LinearTraversal, CompleteUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
}
};
/**************************
*** Slice vectorization ***
***************************/
template<typename Kernel>
struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::Scalar Scalar;
typedef typename Kernel::PacketType PacketType;
enum {
packetSize = unpacket_traits<PacketType>::size,
requestedAlignment = int(Kernel::AssignmentTraits::InnerRequiredAlignment),
alignable = packet_traits<Scalar>::AlignedOnScalar || int(Kernel::AssignmentTraits::DstAlignment)>=sizeof(Scalar),
dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment)>=int(requestedAlignment),
dstAlignment = alignable ? int(requestedAlignment)
: int(Kernel::AssignmentTraits::DstAlignment)
};
const Scalar *dst_ptr = kernel.dstDataPtr();
if((!bool(dstIsAligned)) && (UIntPtr(dst_ptr) % sizeof(Scalar))>0)
{
// the pointer is not aligend-on scalar, so alignment is not possible
return dense_assignment_loop<Kernel,DefaultTraversal,NoUnrolling>::run(kernel);
}
const Index packetAlignedMask = packetSize - 1;
const Index innerSize = kernel.innerSize();
const Index outerSize = kernel.outerSize();
const Index alignedStep = alignable ? (packetSize - kernel.outerStride() % packetSize) & packetAlignedMask : 0;
Index alignedStart = ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned<requestedAlignment>(dst_ptr, innerSize);
for(Index outer = 0; outer < outerSize; ++outer)
{
const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
// do the non-vectorizable part of the assignment
for(Index inner = 0; inner<alignedStart ; ++inner)
kernel.assignCoeffByOuterInner(outer, inner);
// do the vectorizable part of the assignment
for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize)
kernel.template assignPacketByOuterInner<dstAlignment, Unaligned, PacketType>(outer, inner);
// do the non-vectorizable part of the assignment
for(Index inner = alignedEnd; inner<innerSize ; ++inner)
kernel.assignCoeffByOuterInner(outer, inner);
alignedStart = numext::mini((alignedStart+alignedStep)%packetSize, innerSize);
}
}
};
#if EIGEN_UNALIGNED_VECTORIZE
template<typename Kernel>
struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, InnerUnrolling>
{
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
{
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
typedef typename Kernel::PacketType PacketType;
enum { size = DstXprType::InnerSizeAtCompileTime,
packetSize =unpacket_traits<PacketType>::size,
vectorizableSize = (size/packetSize)*packetSize };
for(Index outer = 0; outer < kernel.outerSize(); ++outer)
{
copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, vectorizableSize, 0, 0>::run(kernel, outer);
copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, vectorizableSize, size>::run(kernel, outer);
}
}
};
#endif
/***************************************************************************
* Part 4 : Generic dense assignment kernel
***************************************************************************/
// This class generalize the assignment of a coefficient (or packet) from one dense evaluator
// to another dense writable evaluator.
// It is parametrized by the two evaluators, and the actual assignment functor.
// This abstraction level permits to keep the evaluation loops as simple and as generic as possible.
// One can customize the assignment using this generic dense_assignment_kernel with different
// functors, or by completely overloading it, by-passing a functor.
template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor, int Version = Specialized>
class generic_dense_assignment_kernel
{
protected:
typedef typename DstEvaluatorTypeT::XprType DstXprType;
typedef typename SrcEvaluatorTypeT::XprType SrcXprType;
public:
typedef DstEvaluatorTypeT DstEvaluatorType;
typedef SrcEvaluatorTypeT SrcEvaluatorType;
typedef typename DstEvaluatorType::Scalar Scalar;
typedef copy_using_evaluator_traits<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor> AssignmentTraits;
typedef typename AssignmentTraits::PacketType PacketType;
EIGEN_DEVICE_FUNC generic_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
: m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr)
{
#ifdef EIGEN_DEBUG_ASSIGN
AssignmentTraits::debug();
#endif
}
EIGEN_DEVICE_FUNC Index size() const { return m_dstExpr.size(); }
EIGEN_DEVICE_FUNC Index innerSize() const { return m_dstExpr.innerSize(); }
EIGEN_DEVICE_FUNC Index outerSize() const { return m_dstExpr.outerSize(); }
EIGEN_DEVICE_FUNC Index rows() const { return m_dstExpr.rows(); }
EIGEN_DEVICE_FUNC Index cols() const { return m_dstExpr.cols(); }
EIGEN_DEVICE_FUNC Index outerStride() const { return m_dstExpr.outerStride(); }
EIGEN_DEVICE_FUNC DstEvaluatorType& dstEvaluator() { return m_dst; }
EIGEN_DEVICE_FUNC const SrcEvaluatorType& srcEvaluator() const { return m_src; }
/// Assign src(row,col) to dst(row,col) through the assignment functor.
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index row, Index col)
{
m_functor.assignCoeff(m_dst.coeffRef(row,col), m_src.coeff(row,col));
}
/// \sa assignCoeff(Index,Index)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index index)
{
m_functor.assignCoeff(m_dst.coeffRef(index), m_src.coeff(index));
}
/// \sa assignCoeff(Index,Index)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner)
{
Index row = rowIndexByOuterInner(outer, inner);
Index col = colIndexByOuterInner(outer, inner);
assignCoeff(row, col);
}
template<int StoreMode, int LoadMode, typename PacketType>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index row, Index col)
{
m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(row,col), m_src.template packet<LoadMode,PacketType>(row,col));
}
template<int StoreMode, int LoadMode, typename PacketType>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index index)
{
m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode,PacketType>(index));
}
template<int StoreMode, int LoadMode, typename PacketType>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner)
{
Index row = rowIndexByOuterInner(outer, inner);
Index col = colIndexByOuterInner(outer, inner);
assignPacket<StoreMode,LoadMode,PacketType>(row, col);
}
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner)
{
typedef typename DstEvaluatorType::ExpressionTraits Traits;
return int(Traits::RowsAtCompileTime) == 1 ? 0
: int(Traits::ColsAtCompileTime) == 1 ? inner
: int(DstEvaluatorType::Flags)&RowMajorBit ? outer
: inner;
}
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner)
{
typedef typename DstEvaluatorType::ExpressionTraits Traits;
return int(Traits::ColsAtCompileTime) == 1 ? 0
: int(Traits::RowsAtCompileTime) == 1 ? inner
: int(DstEvaluatorType::Flags)&RowMajorBit ? inner
: outer;
}
EIGEN_DEVICE_FUNC const Scalar* dstDataPtr() const
{
return m_dstExpr.data();
}
protected:
DstEvaluatorType& m_dst;
const SrcEvaluatorType& m_src;
const Functor &m_functor;
// TODO find a way to avoid the needs of the original expression
DstXprType& m_dstExpr;
};
/***************************************************************************
* Part 5 : Entry point for dense rectangular assignment
***************************************************************************/
template<typename DstXprType,typename SrcXprType, typename Functor>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const Functor &/*func*/)
{
EIGEN_ONLY_USED_FOR_DEBUG(dst);
EIGEN_ONLY_USED_FOR_DEBUG(src);
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
}
template<typename DstXprType,typename SrcXprType, typename T1, typename T2>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const internal::assign_op<T1,T2> &/*func*/)
{
Index dstRows = src.rows();
Index dstCols = src.cols();
if(((dst.rows()!=dstRows) || (dst.cols()!=dstCols)))
dst.resize(dstRows, dstCols);
eigen_assert(dst.rows() == dstRows && dst.cols() == dstCols);
}
template<typename DstXprType, typename SrcXprType, typename Functor>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func)
{
typedef evaluator<DstXprType> DstEvaluatorType;
typedef evaluator<SrcXprType> SrcEvaluatorType;
SrcEvaluatorType srcEvaluator(src);
// NOTE To properly handle A = (A*A.transpose())/s with A rectangular,
// we need to resize the destination after the source evaluator has been created.
resize_if_allowed(dst, src, func);
DstEvaluatorType dstEvaluator(dst);
typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
dense_assignment_loop<Kernel>::run(kernel);
}
template<typename DstXprType, typename SrcXprType>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src)
{
call_dense_assignment_loop(dst, src, internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
}
/***************************************************************************
* Part 6 : Generic assignment
***************************************************************************/
// Based on the respective shapes of the destination and source,
// the class AssignmentKind determine the kind of assignment mechanism.
// AssignmentKind must define a Kind typedef.
template<typename DstShape, typename SrcShape> struct AssignmentKind;
// Assignement kind defined in this file:
struct Dense2Dense {};
struct EigenBase2EigenBase {};
template<typename,typename> struct AssignmentKind { typedef EigenBase2EigenBase Kind; };
template<> struct AssignmentKind<DenseShape,DenseShape> { typedef Dense2Dense Kind; };
// This is the main assignment class
template< typename DstXprType, typename SrcXprType, typename Functor,
typename Kind = typename AssignmentKind< typename evaluator_traits<DstXprType>::Shape , typename evaluator_traits<SrcXprType>::Shape >::Kind,
typename EnableIf = void>
struct Assignment;
// The only purpose of this call_assignment() function is to deal with noalias() / "assume-aliasing" and automatic transposition.
// Indeed, I (Gael) think that this concept of "assume-aliasing" was a mistake, and it makes thing quite complicated.
// So this intermediate function removes everything related to "assume-aliasing" such that Assignment
// does not has to bother about these annoying details.
template<typename Dst, typename Src>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment(Dst& dst, const Src& src)
{
call_assignment(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
}
template<typename Dst, typename Src>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment(const Dst& dst, const Src& src)
{
call_assignment(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
}
// Deal with "assume-aliasing"
template<typename Dst, typename Src, typename Func>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if< evaluator_assume_aliasing<Src>::value, void*>::type = 0)
{
typename plain_matrix_type<Src>::type tmp(src);
call_assignment_no_alias(dst, tmp, func);
}
template<typename Dst, typename Src, typename Func>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if<!evaluator_assume_aliasing<Src>::value, void*>::type = 0)
{
call_assignment_no_alias(dst, src, func);
}
// by-pass "assume-aliasing"
// When there is no aliasing, we require that 'dst' has been properly resized
template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment(NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
{
call_assignment_no_alias(dst.expression(), src, func);
}
template<typename Dst, typename Src, typename Func>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
{
enum {
NeedToTranspose = ( (int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1)
|| (int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)
) && int(Dst::SizeAtCompileTime) != 1
};
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst>::type ActualDstTypeCleaned;
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
ActualDstType actualDst(dst);
// TODO check whether this is the right place to perform these checks:
EIGEN_STATIC_ASSERT_LVALUE(Dst)
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned,Src)
EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename ActualDstTypeCleaned::Scalar,typename Src::Scalar);
Assignment<ActualDstTypeCleaned,Src,Func>::run(actualDst, src, func);
}
template<typename Dst, typename Src>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment_no_alias(Dst& dst, const Src& src)
{
call_assignment_no_alias(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
}
template<typename Dst, typename Src, typename Func>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src, const Func& func)
{
// TODO check whether this is the right place to perform these checks:
EIGEN_STATIC_ASSERT_LVALUE(Dst)
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Dst,Src)
EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename Dst::Scalar,typename Src::Scalar);
Assignment<Dst,Src,Func>::run(dst, src, func);
}
template<typename Dst, typename Src>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src)
{
call_assignment_no_alias_no_transpose(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
}
// forward declaration
template<typename Dst, typename Src> void check_for_aliasing(const Dst &dst, const Src &src);
// Generic Dense to Dense assignment
// Note that the last template argument "Weak" is needed to make it possible to perform
// both partial specialization+SFINAE without ambiguous specialization
template< typename DstXprType, typename SrcXprType, typename Functor, typename Weak>
struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Weak>
{
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
{
#ifndef EIGEN_NO_DEBUG
internal::check_for_aliasing(dst, src);
#endif
call_dense_assignment_loop(dst, src, func);
}
};
// Generic assignment through evalTo.
// TODO: not sure we have to keep that one, but it helps porting current code to new evaluator mechanism.
// Note that the last template argument "Weak" is needed to make it possible to perform
// both partial specialization+SFINAE without ambiguous specialization
template< typename DstXprType, typename SrcXprType, typename Functor, typename Weak>
struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Weak>
{
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
{
Index dstRows = src.rows();
Index dstCols = src.cols();
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
dst.resize(dstRows, dstCols);
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
src.evalTo(dst);
}
// NOTE The following two functions are templated to avoid their instanciation if not needed
// This is needed because some expressions supports evalTo only and/or have 'void' as scalar type.
template<typename SrcScalarType>
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<typename DstXprType::Scalar,SrcScalarType> &/*func*/)
{
Index dstRows = src.rows();
Index dstCols = src.cols();
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
dst.resize(dstRows, dstCols);
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
src.addTo(dst);
}
template<typename SrcScalarType>
EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<typename DstXprType::Scalar,SrcScalarType> &/*func*/)
{
Index dstRows = src.rows();
Index dstCols = src.cols();
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
dst.resize(dstRows, dstCols);
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
src.subTo(dst);
}
};
} // namespace internal
} // end namespace Eigen
#endif // EIGEN_ASSIGN_EVALUATOR_H

178
external/include/eigen3/Eigen/src/Core/Assign_MKL.h فروخته شده Normal file
مشاهده پرونده

@@ -0,0 +1,178 @@
/*
Copyright (c) 2011, Intel Corporation. All rights reserved.
Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************
* Content : Eigen bindings to Intel(R) MKL
* MKL VML support for coefficient-wise unary Eigen expressions like a=b.sin()
********************************************************************************
*/
#ifndef EIGEN_ASSIGN_VML_H
#define EIGEN_ASSIGN_VML_H
namespace Eigen {
namespace internal {
template<typename Dst, typename Src>
class vml_assign_traits
{
private:
enum {
DstHasDirectAccess = Dst::Flags & DirectAccessBit,
SrcHasDirectAccess = Src::Flags & DirectAccessBit,
StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Src::IsRowMajor)),
InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime)
: int(Dst::Flags)&RowMajorBit ? int(Dst::ColsAtCompileTime)
: int(Dst::RowsAtCompileTime),
InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime)
: int(Dst::Flags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime)
: int(Dst::MaxRowsAtCompileTime),
MaxSizeAtCompileTime = Dst::SizeAtCompileTime,
MightEnableVml = StorageOrdersAgree && DstHasDirectAccess && SrcHasDirectAccess && Src::InnerStrideAtCompileTime==1 && Dst::InnerStrideAtCompileTime==1,
MightLinearize = MightEnableVml && (int(Dst::Flags) & int(Src::Flags) & LinearAccessBit),
VmlSize = MightLinearize ? MaxSizeAtCompileTime : InnerMaxSize,
LargeEnough = VmlSize==Dynamic || VmlSize>=EIGEN_MKL_VML_THRESHOLD
};
public:
enum {
EnableVml = MightEnableVml && LargeEnough,
Traversal = MightLinearize ? LinearTraversal : DefaultTraversal
};
};
#define EIGEN_PP_EXPAND(ARG) ARG
#if !defined (EIGEN_FAST_MATH) || (EIGEN_FAST_MATH != 1)
#define EIGEN_VMLMODE_EXPAND_LA , VML_HA
#else
#define EIGEN_VMLMODE_EXPAND_LA , VML_LA
#endif
#define EIGEN_VMLMODE_EXPAND__
#define EIGEN_VMLMODE_PREFIX_LA vm
#define EIGEN_VMLMODE_PREFIX__ v
#define EIGEN_VMLMODE_PREFIX(VMLMODE) EIGEN_CAT(EIGEN_VMLMODE_PREFIX_,VMLMODE)
#define EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE, VMLMODE) \
template< typename DstXprType, typename SrcXprNested> \
struct Assignment<DstXprType, CwiseUnaryOp<scalar_##EIGENOP##_op<EIGENTYPE>, SrcXprNested>, assign_op<EIGENTYPE,EIGENTYPE>, \
Dense2Dense, typename enable_if<vml_assign_traits<DstXprType,SrcXprNested>::EnableVml>::type> { \
typedef CwiseUnaryOp<scalar_##EIGENOP##_op<EIGENTYPE>, SrcXprNested> SrcXprType; \
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE,EIGENTYPE> &func) { \
resize_if_allowed(dst, src, func); \
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \
if(vml_assign_traits<DstXprType,SrcXprNested>::Traversal==LinearTraversal) { \
VMLOP(dst.size(), (const VMLTYPE*)src.nestedExpression().data(), \
(VMLTYPE*)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE) ); \
} else { \
const Index outerSize = dst.outerSize(); \
for(Index outer = 0; outer < outerSize; ++outer) { \
const EIGENTYPE *src_ptr = src.IsRowMajor ? &(src.nestedExpression().coeffRef(outer,0)) : \
&(src.nestedExpression().coeffRef(0, outer)); \
EIGENTYPE *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer,0)) : &(dst.coeffRef(0, outer)); \
VMLOP( dst.innerSize(), (const VMLTYPE*)src_ptr, \
(VMLTYPE*)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE)); \
} \
} \
} \
}; \
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP, VMLMODE) \
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE),s##VMLOP), float, float, VMLMODE) \
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE),d##VMLOP), double, double, VMLMODE)
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_CPLX(EIGENOP, VMLOP, VMLMODE) \
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE),c##VMLOP), scomplex, MKL_Complex8, VMLMODE) \
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, EIGEN_CAT(EIGEN_VMLMODE_PREFIX(VMLMODE),z##VMLOP), dcomplex, MKL_Complex16, VMLMODE)
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS(EIGENOP, VMLOP, VMLMODE) \
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP, VMLMODE) \
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_CPLX(EIGENOP, VMLOP, VMLMODE)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sin, Sin, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(asin, Asin, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sinh, Sinh, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(cos, Cos, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(acos, Acos, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(cosh, Cosh, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(tan, Tan, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(atan, Atan, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(tanh, Tanh, LA)
// EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs, _)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(exp, Exp, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(log, Ln, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(log10, Log10, LA)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS(sqrt, Sqrt, _)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(square, Sqr, _)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_CPLX(arg, Arg, _)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(round, Round, _)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(floor, Floor, _)
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(ceil, Ceil, _)
#define EIGEN_MKL_VML_DECLARE_POW_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE, VMLMODE) \
template< typename DstXprType, typename SrcXprNested, typename Plain> \
struct Assignment<DstXprType, CwiseBinaryOp<scalar_##EIGENOP##_op<EIGENTYPE,EIGENTYPE>, SrcXprNested, \
const CwiseNullaryOp<internal::scalar_constant_op<EIGENTYPE>,Plain> >, assign_op<EIGENTYPE,EIGENTYPE>, \
Dense2Dense, typename enable_if<vml_assign_traits<DstXprType,SrcXprNested>::EnableVml>::type> { \
typedef CwiseBinaryOp<scalar_##EIGENOP##_op<EIGENTYPE,EIGENTYPE>, SrcXprNested, \
const CwiseNullaryOp<internal::scalar_constant_op<EIGENTYPE>,Plain> > SrcXprType; \
static void run(DstXprType &dst, const SrcXprType &src, const assign_op<EIGENTYPE,EIGENTYPE> &func) { \
resize_if_allowed(dst, src, func); \
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); \
VMLTYPE exponent = reinterpret_cast<const VMLTYPE&>(src.rhs().functor().m_other); \
if(vml_assign_traits<DstXprType,SrcXprNested>::Traversal==LinearTraversal) \
{ \
VMLOP( dst.size(), (const VMLTYPE*)src.lhs().data(), exponent, \
(VMLTYPE*)dst.data() EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE) ); \
} else { \
const Index outerSize = dst.outerSize(); \
for(Index outer = 0; outer < outerSize; ++outer) { \
const EIGENTYPE *src_ptr = src.IsRowMajor ? &(src.lhs().coeffRef(outer,0)) : \
&(src.lhs().coeffRef(0, outer)); \
EIGENTYPE *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer,0)) : &(dst.coeffRef(0, outer)); \
VMLOP( dst.innerSize(), (const VMLTYPE*)src_ptr, exponent, \
(VMLTYPE*)dst_ptr EIGEN_PP_EXPAND(EIGEN_VMLMODE_EXPAND_##VMLMODE)); \
} \
} \
} \
};
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmsPowx, float, float, LA)
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmdPowx, double, double, LA)
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmcPowx, scomplex, MKL_Complex8, LA)
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmzPowx, dcomplex, MKL_Complex16, LA)
} // end namespace internal
} // end namespace Eigen
#endif // EIGEN_ASSIGN_VML_H

برخی از فایل ها نشان داده نشدند زیرا تعداد زیادی فایل در این تفاوت تغییر کرده اند نمایش بیشتر