diff --git a/admin/vendor/autoload.php b/admin/vendor/autoload.php new file mode 100644 index 000000000..5cfb7cd31 --- /dev/null +++ b/admin/vendor/autoload.php @@ -0,0 +1,25 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var ?string */ + private $vendorDir; + + // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ + private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ + private $missingClasses = array(); + + /** @var ?string */ + private $apcuPrefix; + + /** + * @var self[] + */ + private static $registeredLoaders = array(); + + /** + * @param ?string $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return string[] + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array[] + * @psalm-return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return array[] + * @psalm-return array + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return string[] Array of classname => path + * @psalm-return array + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + $includeFile = self::$includeFile; + $includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders indexed by their corresponding vendor directories. + * + * @return self[] + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } + + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } +} diff --git a/admin/vendor/composer/InstalledVersions.php b/admin/vendor/composer/InstalledVersions.php new file mode 100644 index 000000000..c6b54af7b --- /dev/null +++ b/admin/vendor/composer/InstalledVersions.php @@ -0,0 +1,352 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints($constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = require __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + $installed[] = self::$installed; + + return $installed; + } +} diff --git a/admin/vendor/composer/LICENSE b/admin/vendor/composer/LICENSE new file mode 100644 index 000000000..f27399a04 --- /dev/null +++ b/admin/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/admin/vendor/composer/autoload_classmap.php b/admin/vendor/composer/autoload_classmap.php new file mode 100644 index 000000000..0fb0a2c19 --- /dev/null +++ b/admin/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $vendorDir . '/composer/InstalledVersions.php', +); diff --git a/admin/vendor/composer/autoload_namespaces.php b/admin/vendor/composer/autoload_namespaces.php new file mode 100644 index 000000000..15a2ff3ad --- /dev/null +++ b/admin/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/mjaschen/phpgeo/src'), +); diff --git a/admin/vendor/composer/autoload_real.php b/admin/vendor/composer/autoload_real.php new file mode 100644 index 000000000..596da34e5 --- /dev/null +++ b/admin/vendor/composer/autoload_real.php @@ -0,0 +1,38 @@ +register(true); + + return $loader; + } +} diff --git a/admin/vendor/composer/autoload_static.php b/admin/vendor/composer/autoload_static.php new file mode 100644 index 000000000..6d5f9316a --- /dev/null +++ b/admin/vendor/composer/autoload_static.php @@ -0,0 +1,36 @@ + + array ( + 'Location\\' => 9, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Location\\' => + array ( + 0 => __DIR__ . '/..' . '/mjaschen/phpgeo/src', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitf5da4e3fca64ccd39e0027088099d184::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitf5da4e3fca64ccd39e0027088099d184::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitf5da4e3fca64ccd39e0027088099d184::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/admin/vendor/composer/installed.json b/admin/vendor/composer/installed.json new file mode 100644 index 000000000..335dddbe2 --- /dev/null +++ b/admin/vendor/composer/installed.json @@ -0,0 +1,88 @@ +{ + "packages": [ + { + "name": "mjaschen/phpgeo", + "version": "4.2.0", + "version_normalized": "4.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/mjaschen/phpgeo.git", + "reference": "b2e593cf1e9aceea36510158ddb80c7395a80d5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mjaschen/phpgeo/zipball/b2e593cf1e9aceea36510158ddb80c7395a80d5a", + "reference": "b2e593cf1e9aceea36510158ddb80c7395a80d5a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.6", + "vimeo/psalm": "^4.13" + }, + "time": "2022-07-25T08:36:36+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Location\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marcus Jaschen", + "email": "mjaschen@gmail.com", + "homepage": "https://www.marcusjaschen.de/" + } + ], + "description": "Simple Yet Powerful Geo Library", + "homepage": "https://phpgeo.marcusjaschen.de/", + "keywords": [ + "Polygon", + "area", + "bearing", + "bounds", + "calculation", + "coordinate", + "distance", + "earth", + "ellipsoid", + "geo", + "geofence", + "gis", + "gps", + "haversine", + "length", + "perpendicular", + "point", + "polyline", + "projection", + "simplify", + "track", + "vincenty" + ], + "support": { + "docs": "https://phpgeo.marcusjaschen.de/Installation.html", + "email": "mjaschen@gmail.com", + "issues": "https://github.com/mjaschen/phpgeo/issues", + "source": "https://github.com/mjaschen/phpgeo/tree/4.2.0" + }, + "install-path": "../mjaschen/phpgeo" + } + ], + "dev": true, + "dev-package-names": [] +} diff --git a/admin/vendor/composer/installed.php b/admin/vendor/composer/installed.php new file mode 100644 index 000000000..ff6ef8652 --- /dev/null +++ b/admin/vendor/composer/installed.php @@ -0,0 +1,32 @@ + array( + 'name' => '__root__', + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => '0e6af7d100b3d33b511309de65f355528845c27f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => true, + ), + 'versions' => array( + '__root__' => array( + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => '0e6af7d100b3d33b511309de65f355528845c27f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'mjaschen/phpgeo' => array( + 'pretty_version' => '4.2.0', + 'version' => '4.2.0.0', + 'reference' => 'b2e593cf1e9aceea36510158ddb80c7395a80d5a', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mjaschen/phpgeo', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/admin/vendor/composer/platform_check.php b/admin/vendor/composer/platform_check.php new file mode 100644 index 000000000..92370c5a0 --- /dev/null +++ b/admin/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70300)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/admin/vendor/mjaschen/phpgeo/.github/workflows/php.yml b/admin/vendor/mjaschen/phpgeo/.github/workflows/php.yml new file mode 100644 index 000000000..a1d14e422 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/.github/workflows/php.yml @@ -0,0 +1,61 @@ +name: phpgeo Tests + +on: + push: + branches: + - "**" + pull_request: + branches: + - master + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: + - "7.3" + - "7.4" + - "8.0" + - "8.1" + + name: "phpgeo build - PHP ${{ matrix.php-versions }}" + + steps: + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + coverage: xdebug + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v2 + with: + path: vendor + key: ${{ runner.os }}-php-${{ matrix.php-versions }}-${{ hashFiles('composer.json') }} + restore-keys: | + ${{ runner.os }}-php-${{ matrix.php-versions }}- + + - name: Install dependencies + if: steps.composer-cache.outputs.cache-hit != 'true' + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Lint PHP Sources + run: composer run-script ci:lint + + - name: PHP Code Sniffer + run: composer run-script ci:sniff + + - name: Static Analysis + run: composer run-script ci:psalm + + - name: Unit Tests + run: composer run-script ci:tests diff --git a/admin/vendor/mjaschen/phpgeo/.gitignore b/admin/vendor/mjaschen/phpgeo/.gitignore new file mode 100644 index 000000000..577f1626e --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +*~ +/.idea/ +/composer.lock +/vendor/ +/docs/phpgeo.html +/docs/coverage/ +/docs/phpdox/ +/tools/ +/build/ +.phpunit.result.cache diff --git a/admin/vendor/mjaschen/phpgeo/.scrutinizer.yml b/admin/vendor/mjaschen/phpgeo/.scrutinizer.yml new file mode 100644 index 000000000..27dc67dcc --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/.scrutinizer.yml @@ -0,0 +1,9 @@ +filter: + paths: ["src/*"] +tools: + php_code_coverage: true + php_sim: true + php_mess_detector: true + php_pdepend: true + php_analyzer: true + php_cpd: false diff --git a/admin/vendor/mjaschen/phpgeo/.travis.yml b/admin/vendor/mjaschen/phpgeo/.travis.yml new file mode 100644 index 000000000..1836d1bad --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/.travis.yml @@ -0,0 +1,50 @@ +os: linux +dist: xenial +language: php + +php: + - "7.4" + - "7.3" + - "7.2" + +cache: + directories: + - vendor + - $HOME/.composer/cache + +env: + jobs: + - DEPENDENCIES=latest + - DEPENDENCIES=oldest + +install: +- > + if [ "$DEPENDENCIES" = "latest" ]; then + echo "Installing the latest dependencies"; + composer update --with-dependencies --prefer-stable --prefer-dist + else + echo "Installing the lowest dependencies"; + composer update --with-dependencies --prefer-stable --prefer-dist --prefer-lowest + fi; + composer show; + +script: +- > + echo; + echo "Validating the composer.json"; + composer ci:composer-validate; + +- > + echo; + echo "Linting all PHP files"; + composer ci:lint; + +- > + echo; + echo "Running the Psalm static analyzer"; + composer ci:psalm; + +- > + echo; + echo "Running the PHPUnit tests"; + composer ci:tests; diff --git a/admin/vendor/mjaschen/phpgeo/CHANGELOG.md b/admin/vendor/mjaschen/phpgeo/CHANGELOG.md new file mode 100644 index 000000000..613aa6a29 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/CHANGELOG.md @@ -0,0 +1,317 @@ +# Change Log + +All notable changes to `mjaschen/phpgeo` will be documented in this file. +Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## Unreleased/Upcoming + +### Added + +- `GeometryInterface` provides two new methods: `getBounds()` and `getSegments()` + +### Removed + +- Support for PHP 7.3 +- `setPoint1()` and `setPoint2()` methods from `Line` +- `setSeparator()`, `useCardinalLetters()` and `setUnits()` methods from `DMS` + +## [4.2.0] - Current Version, 2022-07-25 + +## Changed + +- point-to-line distance is calculated iteratively now, fixes #92 +- improved intersection checking for polygon/polygon + +## [4.1.0] - 2022-06-03 + +This release has no breaking changes. + +Thanks, @nilshoerrmann, for contributing! + +### Added + +- method `Bounds::getAsPolygon()` which returns a polygon containing the four nodes of the Bounds instance +- methods `Bounds::getNorthEast()` and `Bounds::getSouthWest()` +- new public methods: `CardinalDirection::isStrictlyNorth()`, `CardinalDirection::isStrictlyEast()`, `CardinalDirection::isStrictlySouth()` and `CardinalDirection::isStrictlyWest()` +- new class `Direction` for checking if one point is north, eat, south or west from another point +- new Class `Intersection` for checking if two geometries intersect each other + +## [4.0.0] - 2021-11-29 + +### Changed + +- drop support for PHP 7.2 **breaking change** +- add support for PHP 8.1 +- add deprecations for setter methods in `DMS` and `Line` classes + +## [3.2.1] - 2021-03-04 + +### Fixed + +- Division by zero in `SimplifyBearing` if two consecutive points share the same location, fixes #79. + +## [3.2.0] - 2020-10-09 + +### Added + +- Calculation of [Cardinal Distances](https://phpgeo.marcusjaschen.de/Calculations/Cardinal_Distance.html) between two points. Thanks @LeoVie! + +### Changed + +- change `static` to `self` to prevent accidentally calling the constructor with wrong arguments in child classes (`Ellipsoid`, `Line`, `Polygon`, `Polyline`) + +## [3.1.0] - 2020-07-24 + +### Added + +- Simplifying polygons is now supported as well, see `simplifyGeometry()` methods in `SimplifyBearing` and `SimplifyDouglasPeucker` classes (fixes #69). + +## [3.0.1] - 2020-05-18 + +### Fixed + +- \#68 `CoordinateFactory` emitted a warning if a coordindates string without arc seconds was passed to the `fromString()` method + +## [3.0.0] - 2020-02-07 + +### Changed + +- *phpgeo* requires PHP >= 7.2 now +- **backwards compatibility breaking:** fix double space in Ellipsoid Name `World␣Geodetic␣System␣␣1984` → `World␣Geodetic␣System␣1984` (#49) +- updated tests for PHPUnit 8 + +### Added + +- class constant visibiliy modifiers + +### Removed + +- support for PHP 7.0 and PHP 7.1 from Travis CI config + +## [2.6.0] - 2020-02-05 + +### Added + +- method `getIntermediatePoint()` to the `Line` class which calculates an intermediate point on a line by following the Great Circle between the two line ends and dividing the line by the given fraction (0.0 ... 1.0) + +## [2.5.0] - 2020-02-04 + +### Added + +- method `getMidpoint()` to the `Line` class which calculates the midpoint of a line by following the Great Circle between the two line ends and dividing the line into two halves. +- utility class `Cartesian` which abstracts three-dimensional cartesian coordinates *x*, *y*, and *z* + +## [2.4.1] - 2020-01-29 + +### Changed + +- access modifier for the `tolerance` attribute is now protected (`SimplifyDouglasPeucker`) + +## [2.4.0] - 2020-01-27 + +### Added + +- `BoundsFactory` to create a bounds instance for a center point and a given distance to the bounds' corners. Thanks @sdennler! + +## [2.3.1] - 2019-12-21 + +### Fixed + +- improve precision in `PointToLineDistance` + +## [2.3.0] - 2019-12-19 + +### Added + +- `PointToLineDistance` calculates the smallest distance between a point and a line + +## [2.2.0] - 2019-11-25 + +### Added + +- `hasSameLocation()` checks if two points share the same location (optionally within a distance which defaults to 0.001 m = 1 mm) +- `addUniquePoint` adds unique points to a polyline (i.e., points that doesn't already exist in that polyline) +- `getAveragePoint()` returns the average value of latitude and longitude values for a polyline + +### Fixed + +- wrongly placed parenthesis in `Polygon::contains()` + +## [2.1.0] - 2019-03-22 + +### Added + +- The bounds for a `Polyline` can now be retrieved in form of a `Bound` object. + +### Changed + +- The auto-loader is now PSR-4 compatible; directory structure was flattened by one level. + +## [2.0.5] - 2019-02-27 + +### Changed + +- improvements to the Douglas-Peucker processor. Thanks @iamskey! + +## [2.0.3] - 2018-07-19 + +### Fixed + +- Links to documentation in README. Thanks @JonathanMH + +### Changed + +- better floating point number comparisons in `Vincenty` +- add exception message in `Vincenty` +- type-cast regexp matches before doing calculations in `CoordinateFactory` + +## [2.0.2] - 2018-03-27 + +### Added + +- Information on how to run checks and tests for developers in the README. + +### Changed + +- Updated internal stuff like type and return hints after running a static analysis. +- Updated some PHPDoc blocks after running a static analysis. + +### Fixed + +- Wrongly typed return value in `BearingEllipsoidal::inverseVincenty()`. + +## [2.0.1] - 2018-02-16 + +### Added + +- new supported format for coordinates parser. Thanks to @petrknap + +## [2.0.0] - 2017-09-27 + +### Changed + +* License: *phpgeo* is now distributed under the MIT license +* phpgeo requires at least PHP 7.0 + +### Removed + +* deprecated class `Simplify` was removed; alternatives: `SimplifyBearing` or `SimplifyDouglasPeucker` +* PHP versions 5.4, 5.5, and 5.6 are no longer supported + +## [1.3.8] - 2017-07-05 + +### Fixed + +* Area calculation for polygons works now. Thanks to @felixveysseyre + +## [1.3.7] - 2017-07-01 + +### Fixed + +* GeoJSON output for polygon is now compliant with RFC 7946. Thanks to @arsonik + +## [1.3.5] - 2016-08-19 + +### Added + +* add method for calculating the final bearing for a `Line` object + +## [1.3.3] - 2016-08-16 + +### Fixed + +* bugifx for a division-by-zero error which occurred when symplifying a polyline + with the Douglas-Peucker algorithm. + +## [1.3.2] - 2016-03-26 + +### Added + +* add an utility class to calculate the perpendicular distance between a point + and a line; [documentation](https://phpgeo.marcusjaschen.de/#_perpendicular_distance) + +## [1.3.1] - 2016-03-26 + +### Added + +* add method to calculate the bearing of a `Line` instance (point 1 -> point 2) + +## [1.3.0] - 2016-03-26 + +### Added + +* A new `SimplifyInterface` was introduced and is implemented in two classes: + `SimplifyDouglasPeucker` and `SimplifyBearing` +* Added documentation + +### Deprecated + +* The `Simplify` processor class is now deprecated and will be removed in the + 2.0 release. + +## [1.2.1] - 2016-03-15 + +### Added + +* Added functionality to change the direction of Polygon instances +* Added documentation + +## [1.2.0] - 2016-03-14 + +### Added + +* Added geofence check for arbitrary geometry objects +* Extended and updated documentation + +## [1.1.1] - 2016-03-13 + +### Added + +* Added formatter for "Decimal Minutes" format, e.g. `43° 37.386' N, 070° 12.472' W` +* Added documentation for the new formatter + +## [1.1.0] - 2016-03-12 + +### Added + +* Added calculation of the bearing angle between two points (initial and final bearing) +* Added calculation of the destination point for a given starting point, the bearing angle, and the distance +* Support for spherical and ellipsoidal algorithms for the described bearing calculations +* Added documentation for the bearing calculations + +## [1.0.4] - 2016-03-11 + +### Added + +* Added functionality to change the direction of Line/Polyline instances +* Added documentation + +## [1.0.3] - 2016-03-10 + +### Added + +* Added documentation sources in mkdocs format. Documentation is now available online at http://phpgeo.marcusjaschen.de/ + +## [1.0.2] - 2016-03-04 + +### Changed + +* several optimizations in control structures + +## [1.0.0] - 2016-02-11 + +### Added + +* Added license information. *phpgeo* is now licensed under the GPL 3. (see issue [#8](https://github.com/mjaschen/phpgeo/issues/8)) + +## [0.4.0] - 2015-10-29 + +### Deprecated + +* removed support for PHP 5.3; introduced short array syntax + +## [0.3.0] - 2015-10-29 + +### Added + +* added the new Polyline class (thanks [@paulvl](https://github.com/paulvl)) diff --git a/admin/vendor/mjaschen/phpgeo/CODE_OF_CONDUCT.md b/admin/vendor/mjaschen/phpgeo/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..2f26c6c53 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mjaschen@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/admin/vendor/mjaschen/phpgeo/CONTRIBUTING.md b/admin/vendor/mjaschen/phpgeo/CONTRIBUTING.md new file mode 100644 index 000000000..df7b8bd68 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contributing to phpgeo + +Note: It's a good idea to [open an issue](https://github.com/mjaschen/phpgeo/issues) +for bugs or feature proposals first. + +The contribution workflow is described as follows: + +1. Fork phpgeo, clone repository (`git clone git@github.com:yourname/phpgeo.git`) +2. Checkout your feature or bug-fix branch (e. g. `git checkout -b fix-random-bug`) +3. Install dependencies: `composer install` +4. Add tests for your changes +5. Make your changes +6. Run the tests (`composer ci`) +7. Iterate through steps 3 to 5 until all tests pass. +8. Commit your changes (`git add -A -- . && git commit`) +9. Push to your fork (`git push --set-upstream origin fix-random-bug`) +10. Create a pull request from your feature or bug-fix branch to phpgeo's "master" branch diff --git a/admin/vendor/mjaschen/phpgeo/LICENSE b/admin/vendor/mjaschen/phpgeo/LICENSE new file mode 100644 index 000000000..1fa7b6180 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright 2017 Marcus Jaschen, https://www.marcusjaschen.de/ + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/admin/vendor/mjaschen/phpgeo/Makefile b/admin/vendor/mjaschen/phpgeo/Makefile new file mode 100644 index 000000000..08f852f2a --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/Makefile @@ -0,0 +1,48 @@ +UPLOAD_HOST=phpgeo.marcusjaschen.de +UPLOAD_PATH=phpgeo.marcusjaschen.de + +PHP ?= php + +.PHONY: docs +docs: daux + +.PHONY: daux +daux: + rm -Rf build/daux + mkdir -p build/daux + docker run --rm -v "$(PWD)":/src -w /src daux/daux.io daux generate -d build/daux + +.PHONY: clean +clean: + rm -Rf build + +.PHONY: upload_docs +upload_docs: docs + rsync --recursive --delete build/daux/ $(UPLOAD_HOST):$(UPLOAD_PATH)/ + +.PHONY: ci +ci: lint coding-standards composer-validate sniff static-analysis-psalm unit-tests + +.PHONY: coding-standards +coding-standards: sniff + +.PHONY: composer-validate +composer-validate: + composer validate --no-check-publish + +.PHONY: lint +lint: + $(PHP) ./vendor/bin/parallel-lint src + +.PHONY: sniff +sniff: + # the `-` prefix ignores the exit status of the command + -$(PHP) ./vendor/bin/phpcs --standard=codesniffer_rules.xml src + +.PHONY: static-analysis-psalm +static-analysis-psalm: + $(PHP) ./vendor/bin/psalm + +.PHONY: unit-tests +unit-tests: + $(PHP) ./vendor/bin/phpunit diff --git a/admin/vendor/mjaschen/phpgeo/README.md b/admin/vendor/mjaschen/phpgeo/README.md new file mode 100644 index 000000000..09627b4ab --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/README.md @@ -0,0 +1,273 @@ +# phpgeo - A Simple Geo Library for PHP + +phpgeo provides abstractions to geographical coordinates (including support for different ellipsoids) and allows you to calculate geographical distances between coordinates with high precision. + +[![Latest Stable Version](https://poser.pugx.org/mjaschen/phpgeo/v)](//packagist.org/packages/mjaschen/phpgeo) +[![Total Downloads](https://poser.pugx.org/mjaschen/phpgeo/downloads)](//packagist.org/packages/mjaschen/phpgeo) +[![phpgeo Tests](https://github.com/mjaschen/phpgeo/actions/workflows/php.yml/badge.svg)](https://github.com/mjaschen/phpgeo/actions/workflows/php.yml) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/mjaschen/phpgeo/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/mjaschen/phpgeo/?branch=master) +[![License](https://poser.pugx.org/mjaschen/phpgeo/license)](//packagist.org/packages/mjaschen/phpgeo) + +## Table of Contents + + + +- [phpgeo - A Simple Geo Library for PHP](#phpgeo---a-simple-geo-library-for-php) + - [Table of Contents](#table-of-contents) + - [Requirements](#requirements) + - [Documentation](#documentation) + - [Installation](#installation) + - [License](#license) + - [Features](#features) + - [Examples/Usage](#examplesusage) + - [Distance between two coordinates (Vincenty's Formula)](#distance-between-two-coordinates-vincentys-formula) + - [Simplifying a polyline](#simplifying-a-polyline) + - [Polygon contains a point (e.g. "GPS geofence")](#polygon-contains-a-point-eg-gps-geofence) + - [Formatted output of coordinates](#formatted-output-of-coordinates) + - [Decimal Degrees](#decimal-degrees) + - [Degrees/Minutes/Seconds (DMS)](#degreesminutesseconds-dms) + - [GeoJSON](#geojson) + - [Development](#development) + - [Run Tests](#run-tests) + - [Miscellaneous](#miscellaneous) + - [Credits](#credits) + + + +## Requirements + +Minimum required PHP version is 7.3. *phpgeo* fully supports PHP 8. + +The 3.x releases require PHP >= 7.2 but don't get feature updates any longer. Bugfixes will be backported. + +The 2.x releases require PHP >= 7.0 but don't get feature updates any longer. Bugfixes won't be backported. + +The 1.x release line has support for PHP >= 5.4. Bugfixes won't be backported. + +## Documentation + +The documentation is available at https://phpgeo.marcusjaschen.de/ + +## Installation + +Using [Composer](https://getcomposer.org), just add it to your `composer.json` by running: + +``` +composer require mjaschen/phpgeo +``` + +## Upgrading + +Update the version constraint in the project's `composer.json` and +run `composer update` or require the new version by running: + +```shell +composer require mjaschen/phpgeo:^4.0 +``` + +## License + +Starting with version 2.0.0 phpgeo is licensed under the MIT license. Older versions were GPL-licensed. + +## Features + +**Info:** Please visit the **[documentation site](https://phpgeo.marcusjaschen.de/)** for complete and up-to-date documentation with many examples! + +phpgeo provides the following features (follow the links for examples): + +- abstractions of several geometry objects ([coordinate/point](https://phpgeo.marcusjaschen.de/Geometries/Coordinate.html), + [line](https://phpgeo.marcusjaschen.de/Geometries/Line.html), + [polyline/GPS track](https://phpgeo.marcusjaschen.de/Geometries/Polyline.html), + [polygon](https://phpgeo.marcusjaschen.de/Geometries/Polygon.html) +- support for different [ellipsoids](https://phpgeo.marcusjaschen.de/Geometries/Ellipsoid.html), e.g. WGS-84 +- [length/distance/perimeter calculations](https://phpgeo.marcusjaschen.de/Calculations/Distance_and_Length.html) + with different implementations (Haversine, Vincenty) +- [Geofence](https://phpgeo.marcusjaschen.de/Calculations/Geofence.html) calculation, + i.e. answering the question "Is this point contained in that area/polygon?" and other [intersection](https://phpgeo.marcusjaschen.de/Comparisons/Intersections.html) checks between different geometries +- [formatting and output](https://phpgeo.marcusjaschen.de/Formatting_and_Output/index.html) of geometry objects + (GeoJSON, nice strings, e. g. `18° 54′ 41″ -155° 40′ 42″`) +- calculation of [bearing angle between two points](https://phpgeo.marcusjaschen.de/Calculations/Bearing_and_Destination.html#page_Bearing-between-two-points) + (spherical or with Vincenty's formula) +- calculation of a [destination point for a given starting point](https://phpgeo.marcusjaschen.de/Calculations/Bearing_and_Destination.html#page_Destination-point-for-given-bearing-and-distance), + bearing angle, and distance (spherical or with Vincenty's formula) +- calculation of the [perpendicular distance between a point and a line](https://phpgeo.marcusjaschen.de/Calculations/Perpendicular_Distance.html) +- calculation of the [Cardinal Distances between two points](https://phpgeo.marcusjaschen.de/Calculations/Cardinal_Distance.html) +- getting segments of a [polyline](https://phpgeo.marcusjaschen.de/Geometries/Polyline.html#page_Segments) + /[polygon](https://phpgeo.marcusjaschen.de/Geometries/Polygon.html#page_Segments), +- [reversing direction](https://phpgeo.marcusjaschen.de/Geometries/Polygon.html#page_Reverse-Direction) + of polyline/polygon + +## Examples/Usage + +This list is incomplete, please visit the [documentation site](https://phpgeo.marcusjaschen.de/) +for the full monty of documentation and examples! + +### Distance between two coordinates (Vincenty's Formula) + +Use the calculator object directly: + +```php +getDistance($coordinate1, $coordinate2); // returns 128130.850 (meters; ≈128 kilometers) +``` + +or call the `getDistance()` method of a Coordinate object by injecting a calculator object: + +```php +getDistance($coordinate2, new Vincenty()); // returns 128130.850 (meters; ≈128 kilometers) +``` + +### Simplifying a polyline + +Polylines can be simplified to save storage space or bandwidth. Simplification is done with the [Ramer–Douglas–Peucker algorithm](https://en.wikipedia.org/wiki/Ramer–Douglas–Peucker_algorithm) (AKA Douglas-Peucker algorithm). + +```php +addPoint(new Coordinate(10.0, 10.0)); +$polyline->addPoint(new Coordinate(20.0, 20.0)); +$polyline->addPoint(new Coordinate(30.0, 10.0)); + +$processor = new Simplify($polyline); + +// remove all points which perpendicular distance is less +// than 1500 km from the surrounding points. +$simplified = $processor->simplify(1500000); + +// simplified is the polyline without the second point (which +// perpendicular distance is ~1046 km and therefore below +// the simplification threshold) +``` + +### Polygon contains a point (e.g. "GPS geofence") + +phpgeo has a polygon implementation which can be used to determinate if a point is contained in it or not. +A polygon consists of at least three points. Points are instances of the `Coordinate` class. + +**Warning:** The calculation gives wrong results if the polygons has points on both sides of the 180/-180 degrees meridian. + +```php +addPoint(new Coordinate(-12.085870,-77.016261)); +$geofence->addPoint(new Coordinate(-12.086373,-77.033813)); +$geofence->addPoint(new Coordinate(-12.102823,-77.030938)); +$geofence->addPoint(new Coordinate(-12.098669,-77.006476)); + +$outsidePoint = new Coordinate(-12.075452, -76.985079); +$insidePoint = new Coordinate(-12.092542, -77.021540); + +var_dump($geofence->contains($outsidePoint)); // returns bool(false) the point is outside the polygon +var_dump($geofence->contains($insidePoint)); // returns bool(true) the point is inside the polygon +``` + +### Formatted output of coordinates + +You can format a coordinate in different styles. + +#### Decimal Degrees + +```php +format(new DecimalDegrees()); +``` + +#### Degrees/Minutes/Seconds (DMS) + +```php +format($formatter); // 18° 54′ 41″ -155° 40′ 42″ + +$formatter->setSeparator(", ") + ->useCardinalLetters(true) + ->setUnits(DMS::UNITS_ASCII); + +echo $coordinate->format($formatter); // 18° 54' 41" N, 155° 40' 42" W +``` + +#### GeoJSON + +```php +format(new GeoJSON()); // { "type" : "point" , "coordinates" : [ -155.678268, 18.911306 ] } +``` + +## Development + +### Run Tests + +Before submitting a pull request, please be sure to run all checks and tests and ensure everything is green. + +- lint PHP files for syntax errors: `composer ci:lint` +- run static analysis with [Psalm][] and report errors: `composer ci:psalm` +- run unit tests with PHPUnit: `composer ci:tests` + +To run all checks and tests at once, just use `composer ci`. + +Of course, it's possible to use the test runners directly, e.g. for PHPUnit: + +```shell +./vendor/bin/phpunit +``` + +Psalm: + +```shell +./vendor/bin/psalm +``` + +## Credits + +* Marcus Jaschen and [all contributors](https://github.com/mjaschen/phpgeo/graphs/contributors) +* [Chris Veness](http://www.movable-type.co.uk/scripts/latlong-vincenty.html) - JavaScript implementation of the [Vincenty formula](http://en.wikipedia.org/wiki/Vincenty%27s_formulae) for distance calculation +* Ersts,P.J., Horning, N., and M. Polin[Internet] Perpendicular Distance Calculator(version 1.2.2) [Documentation](http://biodiversityinformatics.amnh.org/open_source/pdc/documentation.php). American Museum of Natural History, Center for Biodiversity and Conservation. Available from http://biodiversityinformatics.amnh.org/open_source/pdc. Accessed on 2013-07-07. +* W. Randolph Franklin, PNPOLY - Point Inclusion in Polygon Test [Documentation](http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html) + +[Psalm]: https://github.com/vimeo/psalm diff --git a/admin/vendor/mjaschen/phpgeo/composer.json b/admin/vendor/mjaschen/phpgeo/composer.json new file mode 100644 index 000000000..d4145f8c7 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/composer.json @@ -0,0 +1,77 @@ +{ + "name": "mjaschen/phpgeo", + "description": "Simple Yet Powerful Geo Library", + "keywords": [ + "distance", + "area", + "coordinate", + "geo", + "gis", + "bounds", + "ellipsoid", + "calculation", + "polyline", + "polygon", + "geofence", + "simplify", + "length", + "vincenty", + "haversine", + "bearing", + "projection", + "gps", + "earth", + "track", + "point", + "perpendicular" + ], + "homepage": "https://phpgeo.marcusjaschen.de/", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Marcus Jaschen", + "email": "mjaschen@gmail.com", + "homepage": "https://www.marcusjaschen.de/" + } + ], + "readme": "README.md", + "support" : { + "issues" : "https://github.com/mjaschen/phpgeo/issues", + "docs": "https://phpgeo.marcusjaschen.de/Installation.html", + "email" : "mjaschen@gmail.com" + }, + "require": { + "php": "^7.3 || ^8.0" + }, + "autoload": { + "psr-4": { + "Location\\": "src/" + } + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.13", + "squizlabs/php_codesniffer": "^3.6" + }, + "scripts": { + "ci:composer-validate": "composer validate --no-check-all --no-check-lock --strict", + "ci:lint": "find src tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l", + "ci:psalm": "./vendor/bin/psalm", + "ci:sniff": "./vendor/bin/phpcs src tests", + "ci:tests": "./vendor/bin/phpunit tests/", + "ci:static": [ + "@ci:composer-validate", + "@ci:lint", + "@ci:psalm", + "@ci:sniff" + ], + "ci:dynamic": [ + "@ci:tests" + ], + "ci": [ + "@ci:static", + "@ci:dynamic" + ] + } +} diff --git a/admin/vendor/mjaschen/phpgeo/docs/#intersection-polyline-simple.dxf b/admin/vendor/mjaschen/phpgeo/docs/#intersection-polyline-simple.dxf new file mode 100644 index 000000000..b8939b47e --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/#intersection-polyline-simple.dxf @@ -0,0 +1,3408 @@ +999 +dxfrw 0.6.3 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1021 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$EXTMIN + 10 +-8 + 20 +-5 + 30 +0 + 9 +$EXTMAX + 10 +5 + 20 +10 + 30 +0 + 9 +$LIMMIN + 10 +0 + 20 +0 + 9 +$LIMMAX + 10 +420 + 20 +297 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +1 + 9 +$ATTMODE + 70 + 0 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +15.68 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +Bounds 5 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +2.5 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0 + 9 +$DIMDLE + 40 +0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0 + 9 +$DIMTM + 40 +0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937 + 9 +$DIMLFAC + 40 +1 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +STANDARD + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 4 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 2 + 9 +$DIMALTRND + 40 +0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 44 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 +STANDARD + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$DIMFXL + 40 +1 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.7854 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1 + 9 +$FILLETRAD + 40 +0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0 + 9 +$PELEVATION + 40 +0 + 9 +$THICKNESS + 40 +0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0 + 9 +$CHAMFERB + 40 +0 + 9 +$CHAMFERC + 40 +0 + 9 +$CHAMFERD + 40 +0 + 9 +$SKPOLY + 70 + 0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 34 + 9 +$PDSIZE + 40 +0 + 9 +$PLINEWID + 40 +0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 2 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +20000 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$UCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$PUCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0 + 9 +$USERR2 + 40 +0 + 9 +$USERR3 + 40 +0 + 9 +$USERR4 + 40 +0 + 9 +$USERR5 + 40 +0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +0 + 20 +0 + 30 +0 + 9 +$PEXTMAX + 10 +0 + 20 +0 + 30 +0 + 9 +$GRIDMODE + 70 + 1 + 9 +$SNAPSTYLE + 70 + 0 + 9 +$PLIMMIN + 10 +0 + 20 +0 + 9 +$PLIMMAX + 10 +297 + 20 +210 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 0 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +290 + 0 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 1 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50 + 9 +$CAMERAHEIGHT + 40 +0 + 9 +$STEPSPERSEC + 40 +2 + 9 +$STEPSIZE + 40 +50 + 9 +$3DDWFPREC + 40 +2 + 9 +$PSOLWIDTH + 40 +5 + 9 +$PSOLHEIGHT + 40 +80 + 9 +$LOFTANG1 + 40 +1.570796326794897 + 9 +$LOFTANG2 + 40 +1.570796326794897 + 9 +$LOFTMAG1 + 40 +0 + 9 +$LOFTMAG2 + 40 +0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +1 + 9 +$LONGITUDE + 40 +1 + 9 +$NORTHDIRECTION + 40 +0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$SOLIDHIST +280 + 1 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0 + 20 +0 + 11 +1 + 21 +1 + 12 +10.80843339947816 + 22 +7.089026436766691 + 13 +0 + 23 +0 + 14 +10 + 24 +10 + 15 +10 + 25 +10 + 16 +0 + 26 +0 + 36 +1 + 17 +0 + 27 +0 + 37 +0 + 40 +26.91031746062092 + 41 +1.720970537261698 + 42 +50 + 43 +0 + 44 +0 + 50 +0 + 51 +0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0 +120 +0 +130 +0 +111 +1 +121 +0 +131 +0 +112 +0 +122 +1 +132 +0 + 79 + 0 +146 +0 +348 +10020 + 60 + 7 + 61 + 5 +292 +1 +282 + 1 +141 +0 +142 +0 + 63 + 250 +421 +3358443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +6.35 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTTINY + 70 + 0 + 3 +Dot (.15x) ..................................... + 72 + 65 + 73 + 2 + 40 +0.9525 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 +3.175 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 + 0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +12.7 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +36 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +19.05 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +37 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDTINY + 70 + 0 + 3 +Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.8575 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +38 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 + 0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +9.524999999999999 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +39 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 + 0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 +38.09999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +25.4 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTTINY + 70 + 0 + 3 +Dash dot (.15x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +3.81 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 + 0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 + 0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDETINY + 70 + 0 + 3 +Divide (.15x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +4.7625 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 + 0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +15.875 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 + 0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 +63.5 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 + 0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 +44.45 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERTINY + 70 + 0 + 3 +Border (.15x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +6.6675 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 + 0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +22.225 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 + 0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 +88.89999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERTINY + 70 + 0 + 3 +Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +7.619999999999999 + 49 +4.7625 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0.9525 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +101.6 + 49 +63.5 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 1 + 70 + 0 + 62 + 16 +420 +8388608 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 2 + 70 + 0 + 62 + 56 +420 +8421376 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 3 + 70 + 1 + 62 + 96 +420 +32768 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 4 + 70 + 0 + 62 + 136 +420 +32896 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 5 + 70 + 1 + 62 + 176 +420 + 128 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 1 + 70 + 0 + 62 + 1 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +50 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 2 + 70 + 0 + 62 + 2 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +51 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 3 + 70 + 1 + 62 + 3 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +52 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 4 + 70 + 0 + 62 + 4 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +53 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 5 + 70 + 1 + 62 + 5 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 3 + 0 +STYLE + 5 +54 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0 + 41 +1 + 50 +0 + 71 + 0 + 42 +1 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +55 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +LibreCad + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 71 + 1 + 0 +DIMSTYLE +105 +56 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 40 +2.5 + 41 +2.5 + 42 +0.625 + 43 +0.38 + 44 +1.25 + 45 +0 + 46 +0 + 47 +0 + 48 +0 + 49 +1 +140 +2.5 +141 +0.09 +142 +0 +143 +25.4 +144 +1 +145 +0 +146 +1 +147 +0.625 +148 +0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 8 + 79 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +179 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +275 + 0 +276 + 0 +277 + 2 +278 + 44 +279 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +288 + 0 +289 + 3 +340 +STANDARD +341 + +371 + -2 +372 + -2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +1E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +57 +100 +AcDbEntity + 8 +Line 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-4 + 20 +-2 + 11 +5 + 21 +2 + 0 +LINE + 5 +58 +100 +AcDbEntity + 8 +Line 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +5 + 20 +2 + 11 +-1 + 21 +7 + 0 +LINE + 5 +59 +100 +AcDbEntity + 8 +Line 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-1 + 20 +7 + 11 +-3 + 21 +4 + 0 +LINE + 5 +5A +100 +AcDbEntity + 8 +Line 2 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-8 + 20 +3 + 11 +-5 + 21 +-5 + 0 +LINE + 5 +5B +100 +AcDbEntity + 8 +Line 2 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-5 + 20 +-5 + 11 +4 + 21 +-3 + 0 +LINE + 5 +5C +100 +AcDbEntity + 8 +Line 3 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +18 + 11 +21 + 21 +14 + 0 +LINE + 5 +5D +100 +AcDbEntity + 8 +Line 3 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +21 + 20 +14 + 11 +11 + 21 +13 + 0 +LWPOLYLINE + 5 +5E +100 +AcDbEntity + 8 +Bounds 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +-4 + 20 +-2 + 10 +5 + 20 +-2 + 10 +5 + 20 +7 + 10 +-4 + 20 +7 + 0 +LWPOLYLINE + 5 +5F +100 +AcDbEntity + 8 +Bounds 2 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +4 + 20 +-5 + 10 +-8 + 20 +-5 + 10 +-8 + 20 +3 + 10 +4 + 20 +3 + 0 +LWPOLYLINE + 5 +60 +100 +AcDbEntity + 8 +Bounds 3 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +11 + 20 +13 + 10 +21 + 20 +13 + 10 +21 + 20 +18 + 10 +11 + 20 +18 + 0 +LINE + 5 +61 +100 +AcDbEntity + 8 +Line 4 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-6 + 20 +9 + 11 +-1 + 21 +5 + 0 +LINE + 5 +62 +100 +AcDbEntity + 8 +Line 4 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-1 + 20 +5 + 11 +1 + 21 +10 + 0 +LWPOLYLINE + 5 +63 +100 +AcDbEntity + 8 +Bounds 4 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +1 + 20 +10 + 10 +-6 + 20 +10 + 10 +-6 + 20 +5 + 10 +1 + 20 +5 + 0 +LINE + 5 +64 +100 +AcDbEntity + 8 +Line 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +13 + 20 +24 + 11 +9 + 21 +22 + 0 +LINE + 5 +65 +100 +AcDbEntity + 8 +Line 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +8 + 20 +15 + 11 +14 + 21 +20 + 0 +LINE + 5 +66 +100 +AcDbEntity + 8 +Line 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +14 + 20 +20 + 11 +13 + 21 +24 + 0 +LWPOLYLINE + 5 +67 +100 +AcDbEntity + 8 +Bounds 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +8 + 20 +15 + 10 +14 + 20 +15 + 10 +14 + 20 +24 + 10 +8 + 20 +24 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary +281 + 1 + 0 +PLOTSETTINGS + 5 +68 +100 +AcDbPlotSettings + 6 +1x1 + 40 +0 + 41 +0 + 42 +0 + 43 +0 + 0 +ENDSEC + 0 +EOF diff --git a/admin/vendor/mjaschen/phpgeo/docs/000_Introduction.md b/admin/vendor/mjaschen/phpgeo/docs/000_Introduction.md new file mode 100644 index 000000000..dff0156ac --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/000_Introduction.md @@ -0,0 +1,22 @@ +# What is *phpgeo?* + +_phpgeo_ is a small PHP library which provides abstractions to geographical +coordinates (including support for different ellipsoids), polylines +("GPS Tracks"), polygons, bounds, and more. _phpgeo_ allows you to perform +different calculations with these abstractions, as distances, track +lengths, etc. + +_phpgeo_ is developed by [Marcus Jaschen](https://www.marcusjaschen.de/) and all +[contributors](https://github.com/mjaschen/phpgeo/graphs/contributors). + +_phpgeo_ is licensed under the [MIT License](https://opensource.org/licenses/MIT). + +The project is hosted on Github: + +- [Github Project Site](https://github.com/mjaschen/phpgeo) +- [Issue Tracker](https://github.com/mjaschen/phpgeo/issues) + +## Privacy + +The privacy statement for this documentation site can be found here: +[Datenschutzerklärung](https://www.marcusjaschen.de/datenschutzerklaerung/) diff --git a/admin/vendor/mjaschen/phpgeo/docs/010_Installation.md b/admin/vendor/mjaschen/phpgeo/docs/010_Installation.md new file mode 100644 index 000000000..a67123376 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/010_Installation.md @@ -0,0 +1,24 @@ +# Getting phpgeo + +## Requirements + +_phpgeo_ requires at least PHP 7.3. _phpgeo_ fully supports PHP 8. + +The 3.x releases require PHP >= 7.2 but don't get feature updates any longer. Bugfixes will be backported. + +The 2.x releases require PHP >= 7.0 but don't get feature updates any longer. Bugfixes won't be backported. + +The 1.x release line has support for PHP >= 5.4. Bugfixes won't be backported. + +## Installation + +_phpgeo_ is best be installed using Composer. Please visit the +[Composer website](https://getcomposer.org/) website for more information. + +To install _phpgeo,_ simply “require” it using Composer: + +``` shell +composer require mjaschen/phpgeo +``` + +_phpgeo_ is now ready to be used in your project! diff --git a/admin/vendor/mjaschen/phpgeo/docs/015_Upgrading.md b/admin/vendor/mjaschen/phpgeo/docs/015_Upgrading.md new file mode 100644 index 000000000..454fe7336 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/015_Upgrading.md @@ -0,0 +1,38 @@ +# Upgrading phpgeo + +## Update from phpgeo 3.x to phpgeo 4.x + +### Requirements + +- _phpgeo_ 4.x requires at least PHP 7.3 and fully supports PHP 8 + +### Update phpgeo + +- run `composer require mjaschen/phpgeo:^4.0` or +- update the version constraint in your `composer.json` to `^4.0` and run `composer update` + +### Update Your Code + +- Setters in `DMS` and `Line` classes are deprecated and will be removed + with the next release. Use constructor arguments instead. + +No breaking changes were introduced with *phpgeo* 3.0. + +## Update from phpgeo 2.x to phpgeo 3.x + +### Requirements + +- _phpgeo_ 3.x requires at least PHP 7.2 + +### Update phpgeo + +- run `composer require mjaschen/phpgeo:^3.0` or +- update the version constraint in your `composer.json` to `^3.0` and run `composer update` + +### Update Your Code + +The result of `Ellipsoid::getName()` for the built-in *WGS-84* ellipsoid returned `World␣Geodetic␣System␣␣1984` in *phpgeo* 2.x (two space characters before `1984`). Starting with *phpgeo* 3.0, the result is `World␣Geodetic␣System␣1984` (single space character before `1984`). Please verify that your code is still working if you're using that result. + +Starting with *phpgeo* 3.0 class constant visiblity modifiers are used. One class constant was changed to *private* visibility: `BearingSpherical::EARTH_RADIUS`. Please verify that your code isn't using that class constant. + +No further breaking changes were introduced with *phpgeo* 3.0. diff --git a/admin/vendor/mjaschen/phpgeo/docs/020_Development.md b/admin/vendor/mjaschen/phpgeo/docs/020_Development.md new file mode 100644 index 000000000..7a8bead75 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/020_Development.md @@ -0,0 +1,96 @@ +# Development + +## Run Tests + +_phpgeo_ provides unit tests with a quite good coverage. For an easy usage, +the test command is wrapped as a Composer script: + +``` shell +composer ci:tests +``` + +Of course it's possible to run PHPUnit directly: + +``` shell +./vendor/bin/phpunit +``` + +To test against another PHP version you can use Docker. The following command runs +the tests using PHP 7.3: + +``` shell +docker run -it --rm --name phpgeo-phpunit \ + -v "$PWD":/usr/src/phpgeo \ + -w /usr/src/phpgeo php:7.3-cli \ + php vendor/bin/phpunit +``` + +Or PHP 7.4: + +``` shell +docker run -it --rm --name phpgeo-phpunit \ + -v "$PWD":/usr/src/phpgeo \ + -w /usr/src/phpgeo php:7.4-cli \ + php vendor/bin/phpunit +``` + +PHP 8.0: + +``` shell +docker run -it --rm --name phpgeo-phpunit \ + -v "$PWD":/usr/src/phpgeo \ + -w /usr/src/phpgeo php:8.0-cli \ + php vendor/bin/phpunit +``` + +PHP 8.1: + +``` shell +docker run -it --rm --name phpgeo-phpunit \ + -v "$PWD":/usr/src/phpgeo \ + -w /usr/src/phpgeo php:8.1-cli \ + php vendor/bin/phpunit +``` + +Alongside with the unit tests, static test runners are also provided. Run the lint +command to ensure the sources don't contain any syntax error: + +``` shell +composer ci:lint +``` + +A static code analysis with [Psalm](https://psalm.dev/) is configured as well: + +``` shell +composer ci:psalm +``` + +It's possible to run all tests at once: + +``` shell +composer ci +``` + +… or run all CI tasks with different PHP versions one after another: + +```shell +for PHP_VERSION in 7.3 7.4 8.0 8.1 ; do \ + docker run -it --rm -v "$PWD":/phpgeo -w /phpgeo \ + ghcr.io/mjaschen/php:${PHP_VERSION}-cli-mj composer ci || break ; \ +done +``` + +## Creating the documentation + +*phpgeo's* documentation is generated with [Daux](https://daux.io/) from Markdown files. +The `Makefile` provides a helper target for generating the complete documentation: + +``` shell +make docs +``` + +*Daux* can also be run from its official Docker image: + +``` shell +docker run --rm -it -v "$(pwd)":/phpgeo -w /phpgeo daux/daux.io daux generate -d build/daux +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/110_Coordinate.md b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/110_Coordinate.md new file mode 100644 index 000000000..3692808de --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/110_Coordinate.md @@ -0,0 +1,15 @@ +# Coordinate + +The `Coordinate` class is the most important class of phpgeo and provides the +base for all features. It's a representation of a geographic location and +consists of three parts: + +- Geographic Latitude +- Geographic Longitude +- Ellipsoid + +Geographic latitude and longitude values are float numbers between +-90.0 and 90.0 (degrees latitude) and -180.0 and 180.0 (degrees longitude). + +The Ellipsoid is a representation of an approximated shape of the earth and +is abstracted in its own [`Ellipsoid`](Ellipsoid) Link class. diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/120_Line.md b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/120_Line.md new file mode 100644 index 000000000..36b596f82 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/120_Line.md @@ -0,0 +1,170 @@ +# Line + +[TOC] + +A line consists of two points, i. e. instances of the `Coordinate` class. + +## Length + +The `Line` class provides a method to calculate its own length. The method +expects an instance of a class which implements the `DistanceInterface`. + +``` php +getLength(new Haversine()); + +printf("The line has a length of %.3f meters\n", $length); +``` + +`Haversine` is one of the currently two available classes for +distance calculation. The other one is named `Vincenty`. + +The code above will produce the output below: + +``` plaintext +The line has a length of 13013.849 meters +``` + +## Midpoint + +The midpoint of a line is calculated by following the Great Circle (defined by the two endpoints) and dividing the line into two halves. + +``` php +getMidpoint(); + +printf( + 'The midpoint of the line is located at %.3f degrees latitude and %.3f degrees longitude.%s', + $midpoint->getLat(), + $midpoint->getLng(), + PHP_EOL +); + +printf( + 'Its distance from the first point is %.1f meters, its distance from the second point is %.1f meters.%s', + $line->getPoint1()->getDistance($midpoint, new Haversine()), + $line->getPoint2()->getDistance($midpoint, new Haversine()), + PHP_EOL +); +``` + +The code above produces the output below: + +``` plaintext +The midpoint of the line is located at 44.719 degrees latitude and 90.000 degrees longitude. +Its distance from the first point is 3935890.0 meters, its distance from the second point is 3935890.0 meters. +``` + +## Intermediate Point + +Similar to the midpoint calculation but divides the line at the given fraction (between 0.0 … 1.0; but values outside that range work as well). + +``` php +getIntermediatePoint(0.25); + +printf( + 'The first quarter of the line ends at %s%s', + $result->format(new DecimalMinutes(' ')), + PHP_EOL +); +``` + +The code above produces the output below: + +``` plaintext +The first quarter of the line ends at 00° 15.001′ 000° 14.999′ +``` + +## Bearing + +The bearing of an instance can be calculated using the `getBearing()` method. +An instance of `BearingInterface` must be provided as method argument. + +``` php +getBearing(new BearingEllipsoidal()); + +printf("The line has a bearing of %.2f degrees\n", $bearing); +``` + +`BearingEllipsoidal` is one of the currently two available classes for +bearing calculation. The other one is named `BearingSpherical`. + +The code above will produce the output below: + +``` plaintext +The line has a bearing of 328.67 degrees +``` + +This ist the so called _initial bearing._ There exist another bearing angle, +called the _final bearing._ It can be calculated as well: + +``` php +getFinalBearing(new BearingEllipsoidal()); + +printf("The line has a final bearing of %.2f degrees\n", $bearing); +``` + +The code above will produce the output below: + +``` plaintext +The line has a final bearing of 328.59 degrees +``` + +See Bearing between two points @TODO Link for more information about bearings. diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/130_Polyline.md b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/130_Polyline.md new file mode 100644 index 000000000..3ec8a0766 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/130_Polyline.md @@ -0,0 +1,126 @@ +# Polyline + +[TOC] + +A polyline consists of an ordered list of locations, i. e. instances of +the `Coordinate` class. + +## Create a polyline + +To create a polyline, just instantiate the class and add points: + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$polyline->addPoint(new Coordinate(54.5, 12.5)); +$polyline->addPoint(new Coordinate(55.5, 14.5)); +?> +``` + +It's possible to add points to the end of the polyline at every time with the `addPoint()` method. + +Use `addUniquePoint()` to add unique points, i.e. points which doesn't exist already in the polyline. + +## Segments + +It's possible to get a list of polyline segments. Segments are returned as an +array of `Line` instances. + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$track->addPoint(new Coordinate(54.5, 12.5)); +$track->addPoint(new Coordinate(55.5, 14.5)); + +foreach ($track->getSegments() as $segment) { + printf( + "Segment length: %0.2f kilometers\n", + ($segment->getLength(new Haversine()) / 1000) + ); +} +``` + +The code above will produce the output below: + +``` plaintext +Segment length: 232.01 kilometers +Segment length: 169.21 kilometers +``` + +## Length + +Length calculation is described in the [Distance and Length](../Calculations/Distance_and_Length) section. + +## Average Point + +The `getAveragePoint()` method returns a point which latitude and longitude is the average of latitude/longitude values from all polyline points. + +CAUTION: This method currently returns wrong values if the polyline crosses the date line at 180/-180 degrees longitude. + +## Reverse Direction + +It's possible to get a new instance with reversed direction while the +original polyline stays unchanged: + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$track->addPoint(new Coordinate(54.5, 12.5)); + +$reversed = $track->getReverse(); + +print_r($reversed); +``` + +The code above will produce the output below: + +``` plaintext +Location\Polyline Object +( + [points:protected] => Array + ( + [0] => Location\Coordinate Object + ( + [lat:protected] => 54.5 + [lng:protected] => 12.5 + [ellipsoid:protected] => Location\Ellipsoid Object + ( + [name:protected] => WGS-84 + [a:protected] => 6378137 + [f:protected] => 298.257223563 + ) + + ) + + [1] => Location\Coordinate Object + ( + [lat:protected] => 52.5 + [lng:protected] => 13.5 + [ellipsoid:protected] => Location\Ellipsoid Object + ( + [name:protected] => WGS-84 + [a:protected] => 6378137 + [f:protected] => 298.257223563 + ) + + ) + + ) + +) +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/140_Polygon.md b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/140_Polygon.md new file mode 100644 index 000000000..36e571a5d --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/140_Polygon.md @@ -0,0 +1,167 @@ +# Polygon + +[TOC] + +A polygon consists of an ordered list of locations, i. e. instances of +the `Coordinate` class. It's very similar to a polyline, but its start +and end points are connected. + +## Create a polygon + +To create a polygon, just instantiate the class and add points: + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$polygon->addPoint(new Coordinate(54.5, 12.5)); +$polygon->addPoint(new Coordinate(55.5, 14.5)); +?> +``` + +It's possible to add points to the end at every time. + +## Get list of points + +`getPoints()` is used to get the list of points, the number of points can be +retrieved by calling `getNumberOfPoints()`: + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$polygon->addPoint(new Coordinate(54.5, 12.5)); +$polygon->addPoint(new Coordinate(55.5, 14.5)); + +printf("The polygon consists of %d points:\n", $polygon->getNumberOfPoints()); + +foreach ($polygon->getPoints() as $point) { + echo $point->format(new DMS()) . PHP_EOL; +} +``` + +The code above will produce the output below: + +``` plaintext +The polygon consists of 3 points: +52° 30′ 00″ 013° 30′ 00″ +54° 30′ 00″ 012° 30′ 00″ +55° 30′ 00″ 014° 30′ 00″ +``` + +## Segments + +It's possible to get a list of polygon segments. Segments are +returned as an array of `Line` instances. + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$polygon->addPoint(new Coordinate(54.5, 12.5)); +$polygon->addPoint(new Coordinate(55.5, 14.5)); + +foreach ($polygon->getSegments() as $line) { + printf("%0.3f m\n", $line->getLength(new Haversine())); +} +``` + +The code above will produce the output below: + +``` plaintext +232011.020 m +169207.795 m +339918.069 m +``` + +## Length/Perimeter + +Length calculation is described in the [Distance and Length](../Calculations/Distance_and_Length) section. + +## Area + +It's possible to calculate the area of an polygon. The result is given in square meters (m²). + +WARNING: The calculation gives inaccurate results. For relatively small polygons the error should be less than 1 %. + +``` php +addPoint(new Coordinate(0.0000000000, 0.0000000000)); +$polygon->addPoint(new Coordinate(0.0000000000, 0.0008983153)); +$polygon->addPoint(new Coordinate(0.0009043695, 0.0008983153)); +$polygon->addPoint(new Coordinate(0.0009043695, 0.0000000000)); + +printf( + 'Polygon Area = %f m², Perimeter = %f m%s', + $polygon->getArea(), + $polygon->getPerimeter(new \Location\Distance\Vincenty()), + PHP_EOL +); +``` + +The code above produces the output below: + +``` plaintext +Polygon Area = 10044.905261 m², Perimeter = 400.000000 m +``` + +## Geofence + +It's possible to check if a geometry object (point, line, polyline, +polygon) lies inside a polygon. The documentation can be found in +the <> @TODO section. + +## Reverse Direction + +It's possible to get a new instance with reversed direction while the +original polygon stays unchanged: + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$polygon->addPoint(new Coordinate(64.1, - 21.9)); +$polygon->addPoint(new Coordinate(40.7, - 74.0)); +$polygon->addPoint(new Coordinate(33.9, - 118.4)); + +$reversed = $polygon->getReverse(); + +foreach ($reversed->getPoints() as $point) { + echo $point->format(new DecimalDegrees(', ')) . PHP_EOL; +} +``` + +The code above produces the output below: + +``` plaintext +33.90000, -118.40000 +40.70000, -74.00000 +64.10000, -21.90000 +52.50000, 13.50000 +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/200_Bounds.md b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/200_Bounds.md new file mode 100644 index 000000000..2f5b4f421 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/200_Bounds.md @@ -0,0 +1,26 @@ +# Bounds + +Bounds describe an area which is defined by its north-eastern and south-western points. + +All of *phpgeo's* geometries except for the `Coordindate` class provide a `getBounds()` method via the `GetBoundsTrait`. + +The `Bounds` class has a method to calculate the center point of the bounds object (works correctly for bounds that cross the dateline at 180/-180 degrees longitude too). + +## Create Bounds for a given center point and distance to the corners + +``` php +getName(), + $ellipsoid->getA(), + $ellipsoid->getB(), + $ellipsoid->getF() +); + +$ellipsoid = new Ellipsoid('GRS-80', 6378137, 298.257222); + +printf( + "%s: a=%f; b=%f; 1/f=%f\n", + $ellipsoid->getName(), + $ellipsoid->getA(), + $ellipsoid->getB(), + $ellipsoid->getF() +); +``` + +The first ellipsoid is created from one the the default configurations. The second one is created by providing a name and the values of *a* and *1/f.* + +The code above will produce the output below: + +``` plaintext +WGS-84: a=6378137.000000; b=6356752.314245; 1/f=298.257224 +GRS-80: a=6378137.000000; b=6356752.314133; 1/f=298.257222 +``` + +Please take a look into the [`Ellipsoid` source file](https://github.com/mjaschen/phpgeo/blob/master/src/Ellipsoid.php) +for a list of pre-defined ellipsoids. diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/bounds-factory.png b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/bounds-factory.png new file mode 100644 index 000000000..4662da89c Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/bounds-factory.png differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/index.md b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/index.md new file mode 100644 index 000000000..c7eca1893 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/100_Geometries/index.md @@ -0,0 +1,14 @@ +# Geometries + +_phpgeo_ provides several geometry classes: + +* [`Coordinate`](Coordinate) +* [`Line`](Line) +* [`Polyline`](Polyline) +* [`Polygon`](Polygon) + +A Coordinate represents a geographic location, i. e. it contains a latitude +and a longitude - together with an so called Ellipsoid. + +A Line consists of two coordinates, while polylines and polygons are built +from two or more coordinates. diff --git a/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/310_Same_Point_Comparison.md b/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/310_Same_Point_Comparison.md new file mode 100644 index 000000000..d9bff926e --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/310_Same_Point_Comparison.md @@ -0,0 +1,30 @@ +## Same Point Comparison + +It's possible to check if two points describe the same location – and optionally allow an error margin. + +``` php +hasSameLocation($coordinate2) + ? 'Mauna Kea and Haleakala share the same location.' + : 'Mauna Kea and Haleakala have different locations.'; + +$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit +$coordinate2 = new Coordinate(19.82365, -155.46905); // Gemini North Telescope + +echo $coordinate1->hasSameLocation($coordinate2, 1000) + ? 'Mauna Kea and the Gemini North Telescope are located within the same 1 km-radius.' + : 'Mauna Kea and the Gemini North Telescope are located more than 1 km apart.'; +``` + +The code above will produce the output below: + +``` plaintext +Mauna Kea and Haleakala have different locations. +Mauna Kea and the Gemini North Telescope are located within the same 1 km-radius. +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/320_Directions.md b/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/320_Directions.md new file mode 100644 index 000000000..cfe34db70 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/320_Directions.md @@ -0,0 +1,34 @@ +## Directions + +With the `Direction` class it's possible to determine if one point is north, east, south or west of another point. + +```php +pointIsNorthOf(point: $helsinki, compareAgainst: $berlin)) { + echo 'Helsinki is located north of Berlin.' . PHP_EOL; +} else { + echo 'Berlin is located north of Helsinki.' . PHP_EOL; +} + +if ($direction->pointIsEastOf(point: $rome, compareAgainst: $berlin)) { + echo 'Rome is located east of Berlin.' . PHP_EOL; +} else { + echo 'Berlin is located east of Rome.' . PHP_EOL; +} +``` + +The code above will produce the output below: + +``` plaintext +Helsinki is located north of Berlin. +Berlin is located east of Rome. +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/340_Intersections.md b/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/340_Intersections.md new file mode 100644 index 000000000..65e6da944 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/300_Comparisons/340_Intersections.md @@ -0,0 +1,14 @@ +## Intersection Checking + +It's possible to check if two geometries intersect each other. + +(Until this documentation page is finished, take a look into `IntersectionTest` – here you'll find some examples on how to use this feature.) + +The following combinations of geometries can be checked for intersection: + +| | Point | Line | Polyline | Polygon | +|----------|----------------------------------------------------------------|------|----------|-----------------------------------------------------------| +| Point | yes ([same location](/Comparisons/Same_Point_Comparison.html)) | no | no | yes ([point inside polygon](/Calculations/Geofence.html)) | +| Line | no | yes | yes | yes | +| Polyline | no | yes | yes | yes | +| Polygon | yes ([point inside polygon](/Calculations/Geofence.html)) | yes | yes | yes | diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/410_Distance_and_Length.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/410_Distance_and_Length.md new file mode 100644 index 000000000..91caa09d9 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/410_Distance_and_Length.md @@ -0,0 +1,121 @@ +# Distance and Length + +[TOC] + +## Distance Between Two Points (Vincenty's Formula) + +Use the calculator object directly: + +``` php +getDistance($coordinate1, $coordinate2); +``` + +The code above will produce the output below: + +``` plaintext +128130.850 +``` + +or call the `getDistance()` method of a `Coordinate` instance by injecting +a calculator instance: + +``` php +getDistance($coordinate2, new Vincenty()); +``` + +The code above will produce the output below: + +``` plaintext +128130.850 +``` + +## Distance Between Two Points (Haversine Formula) + +There exist different methods for calculating the distance between +two points. The [Haversine formula](https://en.wikipedia.org/wiki/Haversine_formula#Law) +is much faster than Vincenty's method but less precise: + +``` php +getDistance($coordinate2, new Haversine()); +``` + +The code above will produce the output below: + +``` plaintext +128384.515 +``` + +## Length of a Polyline + +*phpgeo* has a polyline implementation which can be used to calculate the +length of a GPS track or a route. A polyline consists of at least two points. +Points are instances of the `Coordinate` class. + +For more details about polylines/GPS tracks see the [`Polyline`](../Geometries/Polyline) section. + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$track->addPoint(new Coordinate(54.5, 12.5)); + +echo $track->getLength(new Vincenty()); +``` + +## Perimeter of a Polygon + +The perimeter is calculated as the sum of the length of all segments. +The result is given in meters. + +``` php +addPoint(new Coordinate(10, 10)); +$polygon->addPoint(new Coordinate(10, 20)); +$polygon->addPoint(new Coordinate(20, 20)); +$polygon->addPoint(new Coordinate(20, 10)); + +echo $polygon->getPerimeter(new Vincenty()); +``` + +The code above will produce the output below: + +``` plaintext +4355689.472 +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/420_Bearing_and_Destination.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/420_Bearing_and_Destination.md new file mode 100644 index 000000000..640aec1d1 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/420_Bearing_and_Destination.md @@ -0,0 +1,143 @@ +# Bearing and Destination + +[TOC] + +phpgeo can be used to calculate the bearing between two points and to +get a destination point for a given start point together with a bearing +angle and a distance. + +Multiple calculation algorithms are supported. Currently phpgeo provides +methods for calculations with a _spherical_ earth model and with an +_ellipsoidal_ model. The spherical calculations are very fast, compared +to the ellipsoidal methods. The ellipsoidal algorithms are a bit more +precise on the other hand. + +## Bearing between two points + +Given two points, it's possible to calculate the bearing angled between +those points. + +phpgeo can calculate the initial bearing (bearing as seen from the first +point) and the final bearing (bearing as seen approaching the destination +point). + +### Calculation with a spherical earth model + +``` php +calculateBearing($berlin, $london)); +var_dump($bearingCalculator->calculateFinalBearing($berlin, $london)); +$endTime = microtime(true); +printf("Time elapsed: %0.6f s\n", ($endTime - $startTime)); +``` + +The code above will produce the following output: + +``` plaintext +double(268.60722336693) +double(257.85494586285) +Time elapsed: 0.000285 s +``` + +### Calculation with an ellipsoidal earth model + +``` php +calculateBearing($berlin, $london)); +var_dump($bearingCalculator->calculateFinalBearing($berlin, $london)); +$endTime = microtime(true); +printf("Time elapsed: %0.6f s\n", ($endTime - $startTime)); +``` + +The code above will produce the following output: + +``` plaintext +double(268.62436347111) +double(257.87203657292) +Time elapsed: 0.000304 s +``` + +Both calculations finish in roughly the same time. One would expect the +second calculation to be clearly slower than the first one. It seems +the exit condition for the iteration is reached quite fast. There might +exist other conditions where the ellipsoidal calculation is noticeable +slower. + +## Destination point for given bearing and distance + +As an example, starting from Berlin, calculate the destination point in +56.1 km distance with an initial bearing of 153 degrees: + +``` php +calculateDestination($berlin, 153, 56100); +$destination2 = $bearingEllipsoidal->calculateDestination($berlin, 153, 56100); + +echo "Spherical: " . $destination1->format(new DecimalDegrees()) . PHP_EOL; +echo "Ellipsoidal: " . $destination2->format(new DecimalDegrees()) . PHP_EOL; +``` + +The code above will produce the output below: + +``` plaintext +Spherical: 52.04988 13.87628 +Ellipsoidal: 52.05020 13.87126 +``` + +Oh, look, what a [beautiful spot on earth](https://www.openstreetmap.org/?mlat=52.0499&mlon=13.8762#map=13/52.0499/13.8762) it is. ;-) + +## Final Bearing for a calculated destination + +*phpgeo* can calculate the final bearing angle for a given starting point, +an initial bearing, and the distance to the destination. + +``` php +calculateDestinationFinalBearing($berlin, 153, 56100); + +var_dump($finalBearing); +``` + +The code above will produce the output below: + +``` plaintext +float(153.29365182147) +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/425_Cardinal_Distance.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/425_Cardinal_Distance.md new file mode 100644 index 000000000..5d04b131f --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/425_Cardinal_Distance.md @@ -0,0 +1,70 @@ +# Cardinal Distance Between Two Points + +The distances how far you have to go to one cardinal direction and eventually to another to reach the second point +*P2* from the first one *P1* is called the Cardinal Distances. + +In the following example the Cardinal Distances are labeled *N* and *E:* + +![Cardinal Distance](cardinal-distance.png) + +[TOC] + +With *phpgeo* there are two ways to calculate the Cardinal Distances: + +## Using the Calculator Instance + +```php +getCardinalDirectionDistances($coordinate1, $coordinate2, $calculator); + +echo 'Cardinal Distances: north=' . $result->getNorth() +. ' m; east=' . $result->getEast() +. ' m; south=' . $result->getSouth( +. ' m; west=' . $result->getWest() . ' m.'; +``` + +The code above will produce the following output: + +``` +Cardinal Distances: north=98425.507 m; east=0 m; south=0 m; west=82268.492 m. +``` + +## Using the `getCardinalDirectionDistances()` method of a Coordinate instance + +```php +getCardinalDirection($point1, $point2); + +$result = $point1->getCardinalDirectionDistances($point2, new Vincenty()); + +echo 'Cardinal Distances: direction=' . $direction + . '; north=' . $result->getNorth() + . ' m; east=' . $result->getEast() + . ' m; south=' . $result->getSouth() + . ' m; west=' . $result->getWest() . ' m.'; +``` + +The code above will produce the following output: + +``` +Cardinal Distances: direction=north-east; north=0 m; east=0 m; south=8768.566 m; west=26969.504 m. +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/430_Perpendicular_Distance.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/430_Perpendicular_Distance.md new file mode 100644 index 000000000..a6af64d1d --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/430_Perpendicular_Distance.md @@ -0,0 +1,43 @@ +# Perpendicular Distance + +The _perpendicular distance_ is defined as the shortest distance between a point +a line (in the two-dimensional plane) respectively between a point and a +[great circle](https://en.wikipedia.org/wiki/Great_circle) on a spherical surface. + +With _phpgeo_ it is possible to calculate the perpendicular distance between a +point (instance of the [`Coordinate`](../Geometries/Coordinate) class) and a +Great Circle - which is defined by a [`Line`](../Geometries/Line). A line is +defined by a pair of coordinates. + +The distance between points *P* and *X* is the perpendicular distance in the following sketch: + +![perpendicular_distance](perpendicular-distance.png) + +## Example + +``` php +getPerpendicularDistance($point, $line) +); +``` + +The code above will produce the output below: + +``` plaintext +perpendicular distance: 936.7 meters +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/435_Distance_Between_Point_and_Line.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/435_Distance_Between_Point_and_Line.md new file mode 100644 index 000000000..e56bce11b --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/435_Distance_Between_Point_and_Line.md @@ -0,0 +1,46 @@ +# Distance Between a Point and a Line + +It's possible to calculate the shortest distance between a point and a +[`Line`](../Geometries/Line). As [`Polyline`](../Geometries/Polyline) +and [`Polygon`](../Geometries/Polygon) are also built upon the `Line` class +it's also possible to calculate distances from a point the polyline/polygon +by iterating over their segments. + +The following image explains how the distance is calcualated: *P* and *R* are +located in such a way that the nearest distance to the line is the distance between +*P*, *R* and the line end points. Point *Q* is nearer to the actual line than to +any of the end points, so the actual distance is the perpendicular distance between *Q* +and the line. + +![Point to Line Distance](point-to-line-distance.png) + +## Example + +``` php +getDistance($point, $line), + PHP_EOL +); +``` + +The code above will produce the output below: + +``` plaintext +Distance from point to line: 27164.1 meters +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/440_Geofence.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/440_Geofence.md new file mode 100644 index 000000000..5f5495bef --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/440_Geofence.md @@ -0,0 +1,40 @@ +# Geofence + +_phpgeo_ has a polygon implementation which can be used to determinate +if a geometry (point, line, polyline, polygon) is contained in it or not. +A polygon consists of at least three points. + +WARNING: The calculation gives wrong results if the polygons crosses +the 180/-180 degrees meridian. + +``` php +addPoint(new Coordinate(-12.085870,-77.016261)); +$geofence->addPoint(new Coordinate(-12.086373,-77.033813)); +$geofence->addPoint(new Coordinate(-12.102823,-77.030938)); +$geofence->addPoint(new Coordinate(-12.098669,-77.006476)); + +$outsidePoint = new Coordinate(-12.075452, -76.985079); +$insidePoint = new Coordinate(-12.092542, -77.021540); + +echo $geofence->contains($outsidePoint) + ? 'Point 1 is located inside the polygon' . PHP_EOL + : 'Point 1 is located outside the polygon' . PHP_EOL; + +echo $geofence->contains($insidePoint) + ? 'Point 2 is located inside the polygon' . PHP_EOL + : 'Point 2 is located outside the polygon' . PHP_EOL; +``` + +The code above will produce the output below: + +``` plaintext +Point 1 is located outside the polygon +Point 2 is located inside the polygon +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/cardinal-distance.png b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/cardinal-distance.png new file mode 100644 index 000000000..9dca3f487 Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/cardinal-distance.png differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/index.md b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/index.md new file mode 100644 index 000000000..af687af45 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/index.md @@ -0,0 +1,3 @@ +# Calculations + +The following chapters describe the possibilities to do geographical calculations with *phpgeo,* e.g. length and distance calculations, determining bearings, etc. diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/perpendicular-distance.png b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/perpendicular-distance.png new file mode 100644 index 000000000..49171e03a Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/perpendicular-distance.png differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/point-to-line-distance.png b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/point-to-line-distance.png new file mode 100644 index 000000000..ff46a079f Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/400_Calculations/point-to-line-distance.png differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/510_Simplifying_a_Polyline_or_Polygon.md b/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/510_Simplifying_a_Polyline_or_Polygon.md new file mode 100644 index 000000000..621fabfae --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/510_Simplifying_a_Polyline_or_Polygon.md @@ -0,0 +1,91 @@ +# Simplifying a polyline/polygon + +[TOC] + +Polylines and polygons can be simplified to save storage space or bandwidth. + +_phpgeo_ provides two implementations for simplifying polyline/polygons. + +The first implementation uses the [_Ramer–Douglas–Peucker algorithm_](https://en.wikipedia.org/wiki/Ramer–Douglas–Peucker_algorithm) +(also known as _Douglas-Peucker algorithm_). The other implementation examines +the bearings of the segments and removes a segment when its bearing +angle is similar to the bearing angle of its predecessor segment. I named it +the _Delta-Bearing algorithm_. + +## Ramer-Douglas-Peucker Algorithm + +``` php +addPoint(new Coordinate(10.0, 10.0)); +$polyline->addPoint(new Coordinate(20.0, 20.0)); +$polyline->addPoint(new Coordinate(30.0, 10.0)); + +$processor = new SimplifyDouglasPeucker(1500000); + +$simplified = $processor->simplify($polyline); + +foreach ($simplified->getPoints() as $point) { + echo $point->format(new DecimalDegrees()) . PHP_EOL; +} +``` + +The example code will remove all points which perpendicular distance is less +than 1,500,000 meters (1,500 km) from the surrounding points. + +The code above produces the output below: + +``` plaintext +10.00000 10.00000 +30.00000 10.00000 +``` + +## Delta-Bearing Algorithm + +``` php +addPoint(new Coordinate(10.0, 10.0)); +$polyline->addPoint(new Coordinate(20.0, 20.0)); +$polyline->addPoint(new Coordinate(30.0, 10.0)); + +$processor = new SimplifyBearing(90); + +$simplified = $processor->simplify($polyline); + +foreach ($simplified->getPoints() as $point) { + echo $point->format(new DecimalDegrees()) . PHP_EOL; +} +``` + +The constructor argument for the `SimplifyBearing` class is the minimum +required angle in degrees between two adjacent polyline segments so that +no points will be removed. If the bearing angle difference is less that +the given value, the middle point will be removed from the resulting +polyline. + +The code above produces the output below: + +``` plaintext +10.00000 10.00000 +30.00000 10.00000 +``` + +The following image shows both a polyline and its simplified version. The +simplification was done with the Delta-Bearing Algorithm with a threshold angle +of 20 degrees. The original polyline is painted in blue, the simplified polyline +is magenta. + +![Delta-Bearing simplifying](simplify.png) diff --git a/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/index.md b/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/index.md new file mode 100644 index 000000000..2142ee762 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/index.md @@ -0,0 +1,5 @@ +# Transformations and Processing + +*phpgeo* provides tools for transforming and processing geometry instances. +It's possible to simplify a Polyline by removing unneeded points to save +storage space for example. diff --git a/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/simplify.png b/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/simplify.png new file mode 100644 index 000000000..3bcbfbe2e Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/500_Transformations_and_Processing/simplify.png differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/100_Coordinates.md b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/100_Coordinates.md new file mode 100644 index 000000000..5ea51b69b --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/100_Coordinates.md @@ -0,0 +1,125 @@ +# Formatting Coordinates + +You can format a coordinate in different styles. + +## Decimal Degrees + +``` php +format(new DecimalDegrees()); +``` + +The code above produces the output below: + +``` plaintext +19.82066 -155.46807 +``` + +The separator string between latitude and longitude can be configured via +constructor argument, as well as the number of decimals (default value is +5 digits): + +``` php +format(new DecimalDegrees(', ', 3)); +``` + +The code above produces the output below: + +``` plaintext +19.821, -155.468 +``` + +## Degrees/Minutes/Seconds (DMS) + +``` php +format($formatter) . PHP_EOL; + +$formatter->setSeparator(', ') + ->useCardinalLetters(true) + ->setUnits(DMS::UNITS_ASCII); + +echo $coordinate->format($formatter) . PHP_EOL; +``` + +The code above produces the output below: + +``` plaintext +18° 54′ 41″ -155° 40′ 42″ +18° 54' 41" N, 155° 40' 42" W +``` + +## Decimal Minutes + +This format is commonly used in the Geocaching community. + +``` php +format($formatter) . PHP_EOL; + +$formatter->setSeparator(', ') + ->useCardinalLetters(true) + ->setUnits(DecimalMinutes::UNITS_ASCII); + +echo $coordinate->format($formatter) . PHP_EOL; +``` + +The code above produces the output below: + +``` plaintext +43° 37.386′ -070° 12.472′ +43° 37.386' N, 070° 12.472' W +``` + +## GeoJSON + +``` php +format(new GeoJSON()); +``` + +The code above produces the output below: + +``` json +{"type":"Point","coordinates":[-155.678268,18.911306]} +``` + +NOTE: Float values processed by `json_encode()` are affected by the ini-setting +[`serialize_precision`](https://secure.php.net/manual/en/ini.core.php#ini.serialize-precision). +You can change the number of decimal places in the JSON output by changing +that ini-option, e. g. with `ini_set('serialize_precision', 8)`. diff --git a/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/130_Polylines.md b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/130_Polylines.md new file mode 100644 index 000000000..02eedb590 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/130_Polylines.md @@ -0,0 +1,32 @@ +# Formatting Polylines + +You can format a polyline in different styles. + +## GeoJSON + +``` php +addPoint(new Coordinate(52.5, 13.5)); +$polyline->addPoint(new Coordinate(62.5, 14.5)); + +$formatter = new GeoJSON; + +echo $formatter->format($polyline); +``` + +The code above produces the output below: + +``` json +{"type":"LineString","coordinates":[[13.5,52.5],[14.5,62.5]]} +``` + +NOTE: Float values processed by `json_encode()` are affected by the ini-setting +[`serialize_precision`](https://secure.php.net/manual/en/ini.core.php#ini.serialize-precision). +You can change the number of decimal places in the JSON output by changing +that ini-option, e. g. with `ini_set('serialize_precision', 8)`. diff --git a/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/140_Polygons.md b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/140_Polygons.md new file mode 100644 index 000000000..c92cccc40 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/140_Polygons.md @@ -0,0 +1,34 @@ +# Formatting Polygons + +You can format a polygon in different styles. + +## GeoJSON + +``` php +addPoint(new Coordinate(10, 20)); +$polygon->addPoint(new Coordinate(20, 40)); +$polygon->addPoint(new Coordinate(30, 40)); +$polygon->addPoint(new Coordinate(30, 20)); + +$formatter = new GeoJSON; + +echo $formatter->format($polygon); +``` + +The code above produces the output below: + +``` json +{"type":"Polygon","coordinates":[[20,10],[40,20],[40,30],[20,30]]} +``` + +NOTE: Float values processed by `json_encode()` are affected by the ini-setting +[`serialize_precision`](https://secure.php.net/manual/en/ini.core.php#ini.serialize-precision). +You can change the number of decimal places in the JSON output by changing +that ini-option, e. g. with `ini_set('serialize_precision', 8)`. diff --git a/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/index.md b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/index.md new file mode 100644 index 000000000..f77afd420 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/600_Formatting_and_Output/index.md @@ -0,0 +1,5 @@ +# Formatting and Output + +*phpgeo* is able to output supported Geometry instances in many different +formats. You're able to provide your own Formatter classes for customization +of the output format. diff --git a/admin/vendor/mjaschen/phpgeo/docs/700_Parsing_and_Input/110_Coordinates_Parser.md b/admin/vendor/mjaschen/phpgeo/docs/700_Parsing_and_Input/110_Coordinates_Parser.md new file mode 100644 index 000000000..5b5946e42 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/700_Parsing_and_Input/110_Coordinates_Parser.md @@ -0,0 +1,53 @@ +# Coordinates Parser + +_phpgeo_ comes with a parser for several types of coordinate formats. +The parser works as a factory which creates an instance of the +`Coordinate` class. + +## Supported Formats + +**Decimal Degrees** with or without *cardinal letters*, +with or without a comma as separator, with or without +whitespace between values and cardinal letters. + +Examples of supported formats: + +- 52.5, 13.5 +- 52.5 13.5 +- -52.5 -13.5 +- 52.345 N, 13.456 E +- N52.345 E13.456 + +**Decimal Minutes** with or without cardinal letters, with +or without degree and minute signs, with or without a comma +as separator, with or without whitespace between values +and cardinal letters. + +Examples of supported formats: + +- 345, E13° 34.567 +- 45′ N, E13° 34.567′ E +- 5, 013 34.567 +- 45, -013 34.567 + +The [unit test](https://github.com/mjaschen/phpgeo/blob/master/tests/Location/Factory/CoordinateFactoryTest.php) +shows some more examples. + +## Example + + ```php +use Location\Factory\CoordinateFactory; +use Location\Formatter\Coordinate\DecimalDegrees; + +require_once __DIR__ . '/vendor/autoload.php'; + +$point = CoordinateFactory::fromString('52° 13.698′ 020° 58.536′'); + +echo $point->format(new DecimalDegrees()); +``` + +The code above produces the output below: + +``` plaintext + 52.22830 20.97560 +``` diff --git a/admin/vendor/mjaschen/phpgeo/docs/700_Parsing_and_Input/index.md b/admin/vendor/mjaschen/phpgeo/docs/700_Parsing_and_Input/index.md new file mode 100644 index 000000000..5e590c021 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/700_Parsing_and_Input/index.md @@ -0,0 +1,7 @@ +# Parsing and Input + +The constructor for the `Coordinate` class accepts a pair of float values +for creating an instance. Coordinates often come in formatted versions, +e.g. with cardinal letters, formatted in degrees, arc minutes, and arc +seconds and so on. *phpgeo* provides parsers for many formats which create +correctly instantiated `Coordinate` objects. diff --git a/admin/vendor/mjaschen/phpgeo/docs/900_Further_Reading.md b/admin/vendor/mjaschen/phpgeo/docs/900_Further_Reading.md new file mode 100644 index 000000000..41b4babda --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/900_Further_Reading.md @@ -0,0 +1,6 @@ +# Further Reading / Sources + +- [Movable Type Scripts](https://www.movable-type.co.uk/scripts/latlong.html) +- [Aviation Formulary V1.24 by Ed Williams](https://www.edwilliams.org/ftp/avsig/avform.txt) +- [Perpendicular Distance Calculator](https://biodiversityinformatics.amnh.org/open_source/pdc/index.html) ([Github](https://github.com/persts/GeographicDistanceTools)) +- [W. Randolph Franklin, PNPOLY - Point Inclusion in Polygon Test](https://wrfranklin.org/Research/Short_Notes/pnpoly.html) diff --git a/admin/vendor/mjaschen/phpgeo/docs/BoundsFactory.afdesign b/admin/vendor/mjaschen/phpgeo/docs/BoundsFactory.afdesign new file mode 100644 index 000000000..c763728fa Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/BoundsFactory.afdesign differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/Cardinal_Distance.afdesign b/admin/vendor/mjaschen/phpgeo/docs/Cardinal_Distance.afdesign new file mode 100644 index 000000000..76b6232e1 Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/Cardinal_Distance.afdesign differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/Line_to_Point_Distance.afdesign b/admin/vendor/mjaschen/phpgeo/docs/Line_to_Point_Distance.afdesign new file mode 100644 index 000000000..26db1635e Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/Line_to_Point_Distance.afdesign differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/Perpendicular_Distance.afdesign b/admin/vendor/mjaschen/phpgeo/docs/Perpendicular_Distance.afdesign new file mode 100644 index 000000000..3154fc6f7 Binary files /dev/null and b/admin/vendor/mjaschen/phpgeo/docs/Perpendicular_Distance.afdesign differ diff --git a/admin/vendor/mjaschen/phpgeo/docs/config.json b/admin/vendor/mjaschen/phpgeo/docs/config.json new file mode 100644 index 000000000..f5b9d6db4 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/config.json @@ -0,0 +1,25 @@ +{ + "title": "phpgeo", + "tagline": "A Simple Yet Powerful Geo Library for PHP", + "author": "Marcus Jaschen", + "format": "html", + "timezone": "Europe/Berlin", + "html": { + "theme": "daux-red", + "breadcrumbs": true, + "breadcrumb_separator": "Chevrons", + "toggle_code": true, + "date_modified": true, + "inherit_index": true, + "search": true, + "repo": "mjaschen/phpgeo", + "edit_on_github": "mjaschen/phpgeo/blob/master/docs", + "piwik_analytics": "metrics.m11n.de", + "piwik_analytics_id": "15", + "links": { + "Download": "https://github.com/mjaschen/phpgeo/archive/master.zip", + "GitHub Repo": "https://github.com/mjaschen/phpgeo", + "Help/Support/Bugs": "https://github.com/mjaschen/phpgeo/issues" + } + } +} diff --git a/admin/vendor/mjaschen/phpgeo/docs/intersection-polyline-simple.dxf b/admin/vendor/mjaschen/phpgeo/docs/intersection-polyline-simple.dxf new file mode 100644 index 000000000..52182377e --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/docs/intersection-polyline-simple.dxf @@ -0,0 +1,3400 @@ +999 +dxfrw 0.6.3 + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1021 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$EXTMIN + 10 +-8 + 20 +-5 + 30 +0 + 9 +$EXTMAX + 10 +21 + 20 +24 + 30 +0 + 9 +$LIMMIN + 10 +0 + 20 +0 + 9 +$LIMMAX + 10 +420 + 20 +297 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +1 + 9 +$ATTMODE + 70 + 0 + 9 +$TEXTSIZE + 40 +2.5 + 9 +$TRACEWID + 40 +15.68 + 9 +$TEXTSTYLE + 7 +STANDARD + 9 +$CLAYER + 8 +Bounds 5 + 9 +$CELTYPE + 6 +BYLAYER + 9 +$CECOLOR + 62 + 256 + 9 +$CELTSCALE + 40 +1 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +2.5 + 9 +$DIMASZ + 40 +2.5 + 9 +$DIMEXO + 40 +0.625 + 9 +$DIMDLI + 40 +3.75 + 9 +$DIMRND + 40 +0 + 9 +$DIMDLE + 40 +0 + 9 +$DIMEXE + 40 +1.25 + 9 +$DIMTP + 40 +0 + 9 +$DIMTM + 40 +0 + 9 +$DIMTXT + 40 +2.5 + 9 +$DIMCEN + 40 +2.5 + 9 +$DIMTSZ + 40 +0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 0 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 8 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + + 9 +$DIMAPOST + 1 + + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 3 + 9 +$DIMALTF + 40 +0.03937 + 9 +$DIMLFAC + 40 +1 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +STANDARD + 9 +$DIMCLRD + 70 + 0 + 9 +$DIMCLRE + 70 + 0 + 9 +$DIMCLRT + 70 + 0 + 9 +$DIMTFAC + 40 +1 + 9 +$DIMGAP + 40 +0.625 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 0 + 9 +$DIMTZIN + 70 + 8 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 2 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 3 + 9 +$DIMTXSTY + 7 +STANDARD + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 0 + 9 +$DIMALTRND + 40 +0 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 44 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 0 + 9 +$DIMLDRBLK + 1 +STANDARD + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$DIMFXL + 40 +1 + 9 +$DIMFXLON + 70 + 0 + 9 +$DIMJOGANG + 40 +0.7854 + 9 +$DIMTFILL + 70 + 0 + 9 +$DIMTFILLCLR + 70 + 0 + 9 +$DIMARCSYM + 70 + 0 + 9 +$DIMLTYPE + 6 + + 9 +$DIMLTEX1 + 6 + + 9 +$DIMLTEX2 + 6 + + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 4 + 9 +$SKETCHINC + 40 +1 + 9 +$FILLETRAD + 40 +0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0 + 9 +$PELEVATION + 40 +0 + 9 +$THICKNESS + 40 +0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0 + 9 +$CHAMFERB + 40 +0 + 9 +$CHAMFERC + 40 +0 + 9 +$CHAMFERD + 40 +0 + 9 +$SKPOLY + 70 + 0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 34 + 9 +$PDSIZE + 40 +0 + 9 +$PLINEWID + 40 +0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 2 + 9 +$SPLINESEGS + 70 + 8 + 9 +$HANDSEED + 5 +20000 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$UCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$UCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSXDIR + 10 +1 + 20 +0 + 30 +0 + 9 +$PUCSYDIR + 10 +0 + 20 +1 + 30 +0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBOTTOM + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGLEFT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGRIGHT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGFRONT + 10 +0 + 20 +0 + 30 +0 + 9 +$PUCSORGBACK + 10 +0 + 20 +0 + 30 +0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0 + 9 +$USERR2 + 40 +0 + 9 +$USERR3 + 40 +0 + 9 +$USERR4 + 40 +0 + 9 +$USERR5 + 40 +0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0 + 20 +0 + 30 +0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +0 + 20 +0 + 30 +0 + 9 +$PEXTMAX + 10 +0 + 20 +0 + 30 +0 + 9 +$PLIMMIN + 10 +0 + 20 +0 + 9 +$PLIMMAX + 10 +297 + 20 +210 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +20 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 0 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0 + 9 +$OLESTARTUP +290 + 0 + 9 +$SORTENTS +280 + 127 + 9 +$INDEXCTL +280 + 0 + 9 +$HIDETEXT +280 + 1 + 9 +$XCLIPFRAME +290 + 0 + 9 +$HALOGAP +280 + 0 + 9 +$OBSCOLOR + 70 + 257 + 9 +$OBSLTYPE +280 + 0 + 9 +$INTERSECTIONDISPLAY +280 + 0 + 9 +$INTERSECTIONCOLOR + 70 + 257 + 9 +$DIMASSOC +280 + 1 + 9 +$PROJECTNAME + 1 + + 9 +$CAMERADISPLAY +290 + 0 + 9 +$LENSLENGTH + 40 +50 + 9 +$CAMERAHEIGHT + 40 +0 + 9 +$STEPSPERSEC + 40 +2 + 9 +$STEPSIZE + 40 +50 + 9 +$3DDWFPREC + 40 +2 + 9 +$PSOLWIDTH + 40 +5 + 9 +$PSOLHEIGHT + 40 +80 + 9 +$LOFTANG1 + 40 +1.570796326794897 + 9 +$LOFTANG2 + 40 +1.570796326794897 + 9 +$LOFTMAG1 + 40 +0 + 9 +$LOFTMAG2 + 40 +0 + 9 +$LOFTPARAM + 70 + 7 + 9 +$LOFTNORMALS +280 + 1 + 9 +$LATITUDE + 40 +1 + 9 +$LONGITUDE + 40 +1 + 9 +$NORTHDIRECTION + 40 +0 + 9 +$TIMEZONE + 70 +-8000 + 9 +$LIGHTGLYPHDISPLAY +280 + 1 + 9 +$TILEMODELIGHTSYNCH +280 + 1 + 9 +$SOLIDHIST +280 + 1 + 9 +$SHOWHIST +280 + 1 + 9 +$DWFFRAME +280 + 2 + 9 +$DGNFRAME +280 + 0 + 9 +$REALWORLDSCALE +290 + 1 + 9 +$INTERFERECOLOR + 62 + 1 + 9 +$CSHADOW +280 + 0 + 9 +$SHADOWPLANELOCATION + 40 +0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +31 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*ACTIVE + 70 + 0 + 10 +0 + 20 +0 + 11 +1 + 21 +1 + 12 +23.51971990919577 + 22 +14.78994814505351 + 13 +0 + 23 +0 + 14 +10 + 24 +10 + 15 +10 + 25 +10 + 16 +0 + 26 +0 + 36 +1 + 17 +0 + 27 +0 + 37 +0 + 40 +44.97391346348288 + 41 +1.720970537261698 + 42 +50 + 43 +0 + 44 +0 + 50 +0 + 51 +0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0 +120 +0 +130 +0 +111 +1 +121 +0 +131 +0 +112 +0 +122 +1 +132 +0 + 79 + 0 +146 +0 +348 +10020 + 60 + 7 + 61 + 5 +292 +1 +282 + 1 +141 +0 +142 +0 + 63 + 250 +421 +3358443 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 4 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0 + 0 +LTYPE + 5 +32 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT + 70 + 0 + 3 +Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +6.35 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +33 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTTINY + 70 + 0 + 3 +Dot (.15x) ..................................... + 72 + 65 + 73 + 2 + 40 +0.9525 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +34 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOT2 + 70 + 0 + 3 +Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 +3.175 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +35 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DOTX2 + 70 + 0 + 3 +Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 +12.7 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +36 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED + 70 + 0 + 3 +Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +19.05 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +37 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDTINY + 70 + 0 + 3 +Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +2.8575 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +38 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHED2 + 70 + 0 + 3 +Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 +9.524999999999999 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +39 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHEDX2 + 70 + 0 + 3 +Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 +38.09999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3A +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT + 70 + 0 + 3 +Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 +25.4 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3B +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTTINY + 70 + 0 + 3 +Dash dot (.15x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +3.81 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOT2 + 70 + 0 + 3 +Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 +12.7 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DASHDOTX2 + 70 + 0 + 3 +Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE + 70 + 0 + 3 +Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 +31.75 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDETINY + 70 + 0 + 3 +Divide (.15x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +4.7625 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDE2 + 70 + 0 + 3 +Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 +15.875 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +DIVIDEX2 + 70 + 0 + 3 +Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 +63.5 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER + 70 + 0 + 3 +Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 +44.45 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERTINY + 70 + 0 + 3 +Border (.15x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +6.6675 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +1.905 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDER2 + 70 + 0 + 3 +Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 +22.225 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +45 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +BORDERX2 + 70 + 0 + 3 +Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 +88.89999999999999 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +25.4 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +0 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +LTYPE + 5 +46 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER + 70 + 0 + 3 +Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 +50.8 + 49 +31.75 + 74 + 0 + 49 +-6.35 + 74 + 0 + 49 +6.35 + 74 + 0 + 49 +-6.35 + 74 + 0 + 0 +LTYPE + 5 +47 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERTINY + 70 + 0 + 3 +Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +7.619999999999999 + 49 +4.7625 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 49 +0.9525 + 74 + 0 + 49 +-0.9525 + 74 + 0 + 0 +LTYPE + 5 +48 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTER2 + 70 + 0 + 3 +Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 +28.575 + 49 +19.05 + 74 + 0 + 49 +-3.175 + 74 + 0 + 49 +3.175 + 74 + 0 + 49 +-3.175 + 74 + 0 + 0 +LTYPE + 5 +49 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +CENTERX2 + 70 + 0 + 3 +Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 +101.6 + 49 +63.5 + 74 + 0 + 49 +-12.7 + 74 + 0 + 49 +12.7 + 74 + 0 + 49 +-12.7 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4A +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 1 + 70 + 0 + 62 + 16 +420 +8388608 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4B +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 2 + 70 + 0 + 62 + 56 +420 +8421376 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4C +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 3 + 70 + 0 + 62 + 96 +420 +32768 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4D +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 4 + 70 + 0 + 62 + 136 +420 +32896 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4E +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Bounds 5 + 70 + 0 + 62 + 176 +420 + 128 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +4F +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 1 + 70 + 0 + 62 + 1 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +50 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 2 + 70 + 0 + 62 + 2 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +51 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 3 + 70 + 0 + 62 + 3 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +52 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 4 + 70 + 0 + 62 + 4 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +LAYER + 5 +53 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +Line 5 + 70 + 0 + 62 + 5 + 6 +CONTINUOUS +370 + 0 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 3 + 0 +STYLE + 5 +54 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0 + 41 +1 + 50 +0 + 71 + 0 + 42 +1 + 3 +txt + 4 + + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +55 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +LibreCad + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 71 + 1 + 0 +DIMSTYLE +105 +56 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 40 +1 + 41 +2.5 + 42 +0.625 + 43 +0.38 + 44 +1.25 + 45 +0 + 46 +0 + 47 +0 + 48 +0 + 49 +1 +140 +2.5 +141 +0.09 +142 +0 +143 +25.4 +144 +1 +145 +0 +146 +1 +147 +0.625 +148 +0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 1 + 79 + 0 +170 + 0 +171 + 2 +172 + 0 +173 + 0 +174 + 0 +175 + 0 +176 + 0 +177 + 0 +178 + 0 +179 + 2 +271 + 4 +272 + 4 +273 + 2 +274 + 2 +275 + 0 +276 + 0 +277 + 2 +278 + 0 +279 + 0 +280 + 0 +281 + 0 +282 + 0 +283 + 1 +284 + 0 +285 + 0 +286 + 0 +288 + 0 +289 + 3 +340 +standard +341 + +371 + -2 +372 + -2 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 2 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +BLOCK_RECORD + 5 +1E +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space + 70 + 0 +280 + 1 +281 + 0 + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0 + 20 +0 + 30 +0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 5 +57 +100 +AcDbEntity + 8 +Line 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-4 + 20 +-2 + 11 +5 + 21 +2 + 0 +LINE + 5 +58 +100 +AcDbEntity + 8 +Line 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +5 + 20 +2 + 11 +-1 + 21 +7 + 0 +LINE + 5 +59 +100 +AcDbEntity + 8 +Line 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-1 + 20 +7 + 11 +-3 + 21 +4 + 0 +LINE + 5 +5A +100 +AcDbEntity + 8 +Line 2 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-8 + 20 +3 + 11 +-5 + 21 +-5 + 0 +LINE + 5 +5B +100 +AcDbEntity + 8 +Line 2 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-5 + 20 +-5 + 11 +4 + 21 +-3 + 0 +LINE + 5 +5C +100 +AcDbEntity + 8 +Line 3 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +15 + 20 +18 + 11 +21 + 21 +14 + 0 +LINE + 5 +5D +100 +AcDbEntity + 8 +Line 3 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +21 + 20 +14 + 11 +11 + 21 +13 + 0 +LWPOLYLINE + 5 +5E +100 +AcDbEntity + 8 +Bounds 1 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +-4 + 20 +-2 + 10 +5 + 20 +-2 + 10 +5 + 20 +7 + 10 +-4 + 20 +7 + 0 +LWPOLYLINE + 5 +5F +100 +AcDbEntity + 8 +Bounds 2 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +4 + 20 +-5 + 10 +-8 + 20 +-5 + 10 +-8 + 20 +3 + 10 +4 + 20 +3 + 0 +LWPOLYLINE + 5 +60 +100 +AcDbEntity + 8 +Bounds 3 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +11 + 20 +13 + 10 +21 + 20 +13 + 10 +21 + 20 +18 + 10 +11 + 20 +18 + 0 +LINE + 5 +61 +100 +AcDbEntity + 8 +Line 4 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-6 + 20 +9 + 11 +-1 + 21 +5 + 0 +LINE + 5 +62 +100 +AcDbEntity + 8 +Line 4 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +-1 + 20 +5 + 11 +1 + 21 +10 + 0 +LWPOLYLINE + 5 +63 +100 +AcDbEntity + 8 +Bounds 4 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +1 + 20 +10 + 10 +-6 + 20 +10 + 10 +-6 + 20 +5 + 10 +1 + 20 +5 + 0 +LINE + 5 +64 +100 +AcDbEntity + 8 +Line 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +13 + 20 +24 + 11 +9 + 21 +22 + 0 +LINE + 5 +65 +100 +AcDbEntity + 8 +Line 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +8 + 20 +15 + 11 +14 + 21 +20 + 0 +LINE + 5 +66 +100 +AcDbEntity + 8 +Line 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbLine + 10 +14 + 20 +20 + 11 +13 + 21 +24 + 0 +LWPOLYLINE + 5 +67 +100 +AcDbEntity + 8 +Bounds 5 + 6 +ByLayer + 62 + 256 +370 + -1 +100 +AcDbPolyline + 90 + 4 + 70 + 1 + 43 +0 + 10 +8 + 20 +15 + 10 +14 + 20 +15 + 10 +14 + 20 +24 + 10 +8 + 20 +24 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 0 +DICTIONARY + 5 +D +330 +C +100 +AcDbDictionary +281 + 1 + 0 +PLOTSETTINGS + 5 +68 +100 +AcDbPlotSettings + 6 +1x1 + 40 +0 + 41 +0 + 42 +0 + 43 +0 + 0 +ENDSEC + 0 +EOF diff --git a/admin/vendor/mjaschen/phpgeo/phpcs.xml.dist b/admin/vendor/mjaschen/phpgeo/phpcs.xml.dist new file mode 100644 index 000000000..97f8cf691 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/phpcs.xml.dist @@ -0,0 +1,121 @@ + + + + This standard requires PHP_CodeSniffer >= 3.4. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/vendor/mjaschen/phpgeo/phpunit.xml b/admin/vendor/mjaschen/phpgeo/phpunit.xml new file mode 100644 index 000000000..812e73a7c --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/phpunit.xml @@ -0,0 +1,14 @@ + + + + + src + + + + + tests/Location/ + tests/Regression/ + + + diff --git a/admin/vendor/mjaschen/phpgeo/psalm.xml b/admin/vendor/mjaschen/phpgeo/psalm.xml new file mode 100644 index 000000000..0ae3aefb3 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/psalm.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingEllipsoidal.php b/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingEllipsoidal.php new file mode 100644 index 000000000..01f908c74 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingEllipsoidal.php @@ -0,0 +1,256 @@ + + */ +class BearingEllipsoidal implements BearingInterface +{ + /** + * This method calculates the initial bearing between the + * two points. + * + * If the two points share the same location, the bearing + * value will be 0.0. + * + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float Bearing Angle + */ + public function calculateBearing(Coordinate $point1, Coordinate $point2): float + { + if ($point1->hasSameLocation($point2)) { + return 0.0; + } + + return $this->inverseVincenty($point1, $point2)->getBearingInitial(); + } + + /** + * Calculates the final bearing between the two points. + * + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float + */ + public function calculateFinalBearing(Coordinate $point1, Coordinate $point2): float + { + return $this->inverseVincenty($point1, $point2)->getBearingFinal(); + } + + /** + * Calculates a destination point for the given point, bearing angle, + * and distance. + * + * @param Coordinate $point + * @param float $bearing the bearing angle between 0 and 360 degrees + * @param float $distance the distance to the destination point in meters + * + * @return Coordinate + */ + public function calculateDestination(Coordinate $point, float $bearing, float $distance): Coordinate + { + return $this->directVincenty($point, $bearing, $distance)->getDestination(); + } + + /** + * Calculates the final bearing angle for a destination point. + * The method expects a starting point point, the bearing angle, + * and the distance to destination. + * + * @param Coordinate $point + * @param float $bearing + * @param float $distance + * + * @return float + * + * @throws NotConvergingException + */ + public function calculateDestinationFinalBearing(Coordinate $point, float $bearing, float $distance): float + { + return $this->directVincenty($point, $bearing, $distance)->getBearingFinal(); + } + + /** + * @param Coordinate $point + * @param float $bearing + * @param float $distance + * + * @return DirectVincentyBearing + * + * @throws NotConvergingException + */ + private function directVincenty(Coordinate $point, float $bearing, float $distance): DirectVincentyBearing + { + $phi1 = deg2rad($point->getLat()); + $lambda1 = deg2rad($point->getLng()); + $alpha1 = deg2rad($bearing); + + $a = $point->getEllipsoid()->getA(); + $b = $point->getEllipsoid()->getB(); + $f = 1 / $point->getEllipsoid()->getF(); + + $sinAlpha1 = sin($alpha1); + $cosAlpha1 = cos($alpha1); + + $tanU1 = (1 - $f) * tan($phi1); + $cosU1 = 1 / sqrt(1 + $tanU1 * $tanU1); + $sinU1 = $tanU1 * $cosU1; + $sigma1 = atan2($tanU1, $cosAlpha1); + $sinAlpha = $cosU1 * $sinAlpha1; + $cosSquAlpha = 1 - $sinAlpha * $sinAlpha; + $uSq = $cosSquAlpha * ($a * $a - $b * $b) / ($b * $b); + $A = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq))); + $B = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq))); + + $sigmaS = $distance / ($b * $A); + $sigma = $sigmaS; + $iterations = 0; + + do { + $cos2SigmaM = cos(2 * $sigma1 + $sigma); + $sinSigma = sin($sigma); + $cosSigma = cos($sigma); + $deltaSigma = $B * $sinSigma + * ($cos2SigmaM + $B / 4 + * ($cosSigma + * (-1 + 2 * $cos2SigmaM * $cos2SigmaM) - $B / 6 + * $cos2SigmaM * (-3 + 4 * $sinSigma * $sinSigma) + * (-3 + 4 * $cos2SigmaM * $cos2SigmaM) + ) + ); + $sigmaS = $sigma; + $sigma = $distance / ($b * $A) + $deltaSigma; + $iterations++; + } while (abs($sigma - $sigmaS) > 1e-12 && $iterations < 200); + + if ($iterations >= 200) { + throw new NotConvergingException('Inverse Vincenty Formula did not converge'); + } + + $tmp = $sinU1 * $sinSigma - $cosU1 * $cosSigma * $cosAlpha1; + $phi2 = atan2( + $sinU1 * $cosSigma + $cosU1 * $sinSigma * $cosAlpha1, + (1 - $f) * sqrt($sinAlpha * $sinAlpha + $tmp * $tmp) + ); + $lambda = atan2($sinSigma * $sinAlpha1, $cosU1 * $cosSigma - $sinU1 * $sinSigma * $cosAlpha1); + $C = $f / 16 * $cosSquAlpha * (4 + $f * (4 - 3 * $cosSquAlpha)); + $L = $lambda + - (1 - $C) * $f * $sinAlpha + * ($sigma + $C * $sinSigma * ($cos2SigmaM + $C * $cosSigma * (-1 + 2 * $cos2SigmaM ** 2))); + $lambda2 = fmod($lambda1 + $L + 3 * M_PI, 2 * M_PI) - M_PI; + + $alpha2 = atan2($sinAlpha, -$tmp); + $alpha2 = fmod($alpha2 + 2 * M_PI, 2 * M_PI); + + return new DirectVincentyBearing( + new Coordinate(rad2deg($phi2), rad2deg($lambda2), $point->getEllipsoid()), + rad2deg($alpha2) + ); + } + + /** + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return InverseVincentyBearing + * + * @throws NotConvergingException + */ + private function inverseVincenty(Coordinate $point1, Coordinate $point2): InverseVincentyBearing + { + $φ1 = deg2rad($point1->getLat()); + $φ2 = deg2rad($point2->getLat()); + $λ1 = deg2rad($point1->getLng()); + $λ2 = deg2rad($point2->getLng()); + + $a = $point1->getEllipsoid()->getA(); + $b = $point1->getEllipsoid()->getB(); + $f = 1 / $point1->getEllipsoid()->getF(); + + $L = $λ2 - $λ1; + + $tanU1 = (1 - $f) * tan($φ1); + $cosU1 = 1 / sqrt(1 + $tanU1 * $tanU1); + $sinU1 = $tanU1 * $cosU1; + $tanU2 = (1 - $f) * tan($φ2); + $cosU2 = 1 / sqrt(1 + $tanU2 * $tanU2); + $sinU2 = $tanU2 * $cosU2; + + $λ = $L; + + $iterations = 0; + + do { + $sinλ = sin($λ); + $cosλ = cos($λ); + $sinSqσ = ($cosU2 * $sinλ) * ($cosU2 * $sinλ) + + ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosλ) * ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosλ); + $sinσ = sqrt($sinSqσ); + + if ($sinσ == 0) { + new InverseVincentyBearing(0, 0, 0); + } + + $cosσ = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosλ; + $σ = atan2($sinσ, $cosσ); + $sinα = $cosU1 * $cosU2 * $sinλ / $sinσ; + $cosSqα = 1 - $sinα * $sinα; + + $cos2σM = 0; + if ($cosSqα !== 0.0) { + $cos2σM = $cosσ - 2 * $sinU1 * $sinU2 / $cosSqα; + } + + $C = $f / 16 * $cosSqα * (4 + $f * (4 - 3 * $cosSqα)); + $λp = $λ; + $λ = $L + (1 - $C) * $f * $sinα + * ($σ + $C * $sinσ * ($cos2σM + $C * $cosσ * (-1 + 2 * $cos2σM * $cos2σM))); + $iterations++; + } while (abs($λ - $λp) > 1e-12 && $iterations < 200); + + if ($iterations >= 200) { + throw new NotConvergingException('Inverse Vincenty Formula did not converge'); + } + + $uSq = $cosSqα * ($a * $a - $b * $b) / ($b * $b); + $A = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq))); + $B = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq))); + $Δσ = $B * $sinσ + * ($cos2σM + $B / 4 + * ($cosσ * (-1 + 2 * $cos2σM * $cos2σM) - $B / 6 + * $cos2σM * (-3 + 4 * $sinσ * $sinσ) + * (-3 + 4 * $cos2σM * $cos2σM) + ) + ); + + $s = $b * $A * ($σ - $Δσ); + + $α1 = atan2($cosU2 * $sinλ, $cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosλ); + $α2 = atan2($cosU1 * $sinλ, -$sinU1 * $cosU2 + $cosU1 * $sinU2 * $cosλ); + + $α1 = fmod($α1 + 2 * M_PI, 2 * M_PI); + $α2 = fmod($α2 + 2 * M_PI, 2 * M_PI); + + $s = round($s, 3); + + return new InverseVincentyBearing($s, rad2deg($α1), rad2deg($α2)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingInterface.php b/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingInterface.php new file mode 100644 index 000000000..2557af158 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingInterface.php @@ -0,0 +1,48 @@ + + */ +interface BearingInterface +{ + /** + * This method calculates the initial bearing between the + * two points. + * + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float Bearing Angle + */ + public function calculateBearing(Coordinate $point1, Coordinate $point2): float; + + /** + * Calculates the final bearing between the two points. + * + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float + */ + public function calculateFinalBearing(Coordinate $point1, Coordinate $point2): float; + + /** + * Calculates a destination point for the given point, bearing angle, + * and distance. + * + * @param Coordinate $point + * @param float $bearing the bearing angle between 0 and 360 degrees + * @param float $distance the distance to the destination point in meters + * + * @return Coordinate + */ + public function calculateDestination(Coordinate $point, float $bearing, float $distance): Coordinate; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingSpherical.php b/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingSpherical.php new file mode 100644 index 000000000..d2cd34f91 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Bearing/BearingSpherical.php @@ -0,0 +1,89 @@ + + */ +class BearingSpherical implements BearingInterface +{ + /** + * Earth radius in meters. + */ + private const EARTH_RADIUS = 6371009.0; + + /** + * This method calculates the initial bearing (forward azimut) between + * the two given points. + * + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float Bearing Angle in degrees + */ + public function calculateBearing(Coordinate $point1, Coordinate $point2): float + { + $lat1 = deg2rad($point1->getLat()); + $lat2 = deg2rad($point2->getLat()); + $lng1 = deg2rad($point1->getLng()); + $lng2 = deg2rad($point2->getLng()); + + $y = sin($lng2 - $lng1) * cos($lat2); + $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($lng2 - $lng1); + + $bearing = rad2deg(atan2($y, $x)); + + if ($bearing < 0) { + $bearing = fmod($bearing + 360, 360); + } + + return $bearing; + } + + /** + * Calculates the final bearing between the two points. + * + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float + */ + public function calculateFinalBearing(Coordinate $point1, Coordinate $point2): float + { + $initialBearing = $this->calculateBearing($point2, $point1); + + return fmod($initialBearing + 180, 360); + } + + /** + * Calculates a destination point for the given point, bearing angle, + * and distance. + * + * @param Coordinate $point + * @param float $bearing the bearing angle between 0 and 360 degrees + * @param float $distance the distance to the destination point in meters + * + * @return Coordinate + * @throws InvalidArgumentException + */ + public function calculateDestination(Coordinate $point, float $bearing, float $distance): Coordinate + { + $D = $distance / self::EARTH_RADIUS; + $B = deg2rad($bearing); + $φ = deg2rad($point->getLat()); + $λ = deg2rad($point->getLng()); + + $Φ = asin(sin($φ) * cos($D) + cos($φ) * sin($D) * cos($B)); + $Λ = $λ + atan2(sin($B) * sin($D) * cos($φ), cos($D) - sin($φ) * sin($φ)); + + return new Coordinate(rad2deg($Φ), rad2deg($Λ)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Bearing/DirectVincentyBearing.php b/admin/vendor/mjaschen/phpgeo/src/Bearing/DirectVincentyBearing.php new file mode 100644 index 000000000..19964383b --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Bearing/DirectVincentyBearing.php @@ -0,0 +1,53 @@ + + */ +class DirectVincentyBearing +{ + /** + * @var Coordinate + */ + private $destination; + + /** + * @var float + */ + private $bearingFinal; + + /** + * Bearing constructor. + * + * @param Coordinate $destination + * @param float $bearingFinal + */ + public function __construct(Coordinate $destination, float $bearingFinal) + { + $this->destination = $destination; + $this->bearingFinal = $bearingFinal; + } + + /** + * @return Coordinate + */ + public function getDestination(): Coordinate + { + return $this->destination; + } + + /** + * @return float + */ + public function getBearingFinal(): float + { + return $this->bearingFinal; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Bearing/InverseVincentyBearing.php b/admin/vendor/mjaschen/phpgeo/src/Bearing/InverseVincentyBearing.php new file mode 100644 index 000000000..f918e1ce0 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Bearing/InverseVincentyBearing.php @@ -0,0 +1,66 @@ + + */ +class InverseVincentyBearing +{ + /** + * @var float + */ + private $distance; + + /** + * @var float + */ + private $bearingInitial; + + /** + * @var float + */ + private $bearingFinal; + + /** + * InverseVincentyBearing constructor. + * + * @param float $distance + * @param float $bearingInitial + * @param float $bearingFinal + */ + public function __construct(float $distance, float $bearingInitial, float $bearingFinal) + { + $this->distance = $distance; + $this->bearingInitial = $bearingInitial; + $this->bearingFinal = $bearingFinal; + } + + /** + * @return float + */ + public function getDistance(): float + { + return $this->distance; + } + + /** + * @return float + */ + public function getBearingInitial(): float + { + return $this->bearingInitial; + } + + /** + * @return float + */ + public function getBearingFinal(): float + { + return $this->bearingFinal; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Bounds.php b/admin/vendor/mjaschen/phpgeo/src/Bounds.php new file mode 100644 index 000000000..261fdf44f --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Bounds.php @@ -0,0 +1,118 @@ +northWest = $northWest; + $this->southEast = $southEast; + } + + public function getNorthWest(): Coordinate + { + return $this->northWest; + } + + public function getSouthEast(): Coordinate + { + return $this->southEast; + } + + public function getNorthEast(): Coordinate + { + return new Coordinate($this->getNorth(), $this->getEast()); + } + + public function getSouthWest(): Coordinate + { + return new Coordinate($this->getSouth(), $this->getWest()); + } + + public function getNorth(): float + { + return $this->northWest->getLat(); + } + + public function getSouth(): float + { + return $this->southEast->getLat(); + } + + public function getWest(): float + { + return $this->northWest->getLng(); + } + + public function getEast(): float + { + return $this->southEast->getLng(); + } + + /** + * Calculates the center of this bounds object and returns it as a + * Coordinate instance. + * + * @throws \InvalidArgumentException + */ + public function getCenter(): Coordinate + { + $centerLat = ($this->getNorth() + $this->getSouth()) / 2; + + return new Coordinate($centerLat, $this->getCenterLng()); + } + + protected function getCenterLng(): float + { + $centerLng = ($this->getEast() + $this->getWest()) / 2; + + $overlap = $this->getWest() > 0 && $this->getEast() < 0; + + if ($overlap && $centerLng > 0) { + return -180.0 + $centerLng; + } + + if ($overlap && $centerLng < 0) { + return 180.0 + $centerLng; + } + + if ($overlap && $centerLng == 0) { + return 180.0; + } + + return $centerLng; + } + + /** + * Creates the polygon described by this bounds object and returns the + * Polygon instance. + */ + public function getAsPolygon(): Polygon + { + $polygon = new Polygon(); + + $polygon->addPoint($this->getNorthWest()); + $polygon->addPoint($this->getNorthEast()); + $polygon->addPoint($this->getSouthEast()); + $polygon->addPoint($this->getSouthWest()); + + return $polygon; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirection.php b/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirection.php new file mode 100644 index 000000000..e89e1b9cc --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirection.php @@ -0,0 +1,133 @@ +direction = new Direction(); + } + + public function getCardinalDirection(Coordinate $point1, Coordinate $point2): string + { + $directionFunctionMapping = [ + self::CARDINAL_DIRECTION_NORTH => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isStrictlyNorth($point1, $point2); + }, + self::CARDINAL_DIRECTION_EAST => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isStrictlyEast($point1, $point2); + }, + self::CARDINAL_DIRECTION_SOUTH => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isStrictlySouth($point1, $point2); + }, + self::CARDINAL_DIRECTION_WEST => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isStrictlyWest($point1, $point2); + }, + self::CARDINAL_DIRECTION_NORTHEAST => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isNorthEast($point1, $point2); + }, + self::CARDINAL_DIRECTION_SOUTHEAST => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isSouthEast($point1, $point2); + }, + self::CARDINAL_DIRECTION_SOUTHWEST => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isSouthWest($point1, $point2); + }, + self::CARDINAL_DIRECTION_NORTHWEST => function (Coordinate $point1, Coordinate $point2): bool { + return $this->isNorthWest($point1, $point2); + }, + ]; + + foreach ($directionFunctionMapping as $direction => $checkFunction) { + if ($checkFunction($point1, $point2)) { + return $direction; + } + } + + return self::CARDINAL_DIRECTION_NONE; + } + + private function isStrictlyNorth(Coordinate $point1, Coordinate $point2): bool + { + return !$this->direction->pointIsEastOf($point1, $point2) + && !$this->direction->pointIsSouthOf($point1, $point2) + && !$this->direction->pointIsWestOf($point1, $point2) + && $this->direction->pointIsNorthOf($point1, $point2); + } + + private function isStrictlyEast(Coordinate $point1, Coordinate $point2): bool + { + return $this->direction->pointIsEastOf($point1, $point2) + && !$this->direction->pointIsSouthOf($point1, $point2) + && !$this->direction->pointIsWestOf($point1, $point2) + && !$this->direction->pointIsNorthOf($point1, $point2); + } + + private function isStrictlySouth(Coordinate $point1, Coordinate $point2): bool + { + return !$this->direction->pointIsEastOf($point1, $point2) + && $this->direction->pointIsSouthOf($point1, $point2) + && !$this->direction->pointIsWestOf($point1, $point2) + && !$this->direction->pointIsNorthOf($point1, $point2); + } + + private function isStrictlyWest(Coordinate $point1, Coordinate $point2): bool + { + return !$this->direction->pointIsEastOf($point1, $point2) + && !$this->direction->pointIsSouthOf($point1, $point2) + && $this->direction->pointIsWestOf($point1, $point2) + && !$this->direction->pointIsNorthOf($point1, $point2); + } + + private function isNorthEast(Coordinate $point1, Coordinate $point2): bool + { + return $this->direction->pointIsEastOf($point1, $point2) + && !$this->direction->pointIsSouthOf($point1, $point2) + && !$this->direction->pointIsWestOf($point1, $point2) + && $this->direction->pointIsNorthOf($point1, $point2); + } + + private function isSouthEast(Coordinate $point1, Coordinate $point2): bool + { + return $this->direction->pointIsEastOf($point1, $point2) + && $this->direction->pointIsSouthOf($point1, $point2) + && !$this->direction->pointIsWestOf($point1, $point2) + && !$this->direction->pointIsNorthOf($point1, $point2); + } + + private function isSouthWest(Coordinate $point1, Coordinate $point2): bool + { + return !$this->direction->pointIsEastOf($point1, $point2) + && $this->direction->pointIsSouthOf($point1, $point2) + && $this->direction->pointIsWestOf($point1, $point2) + && !$this->direction->pointIsNorthOf($point1, $point2); + } + + private function isNorthWest(Coordinate $point1, Coordinate $point2): bool + { + return !$this->direction->pointIsEastOf($point1, $point2) + && !$this->direction->pointIsSouthOf($point1, $point2) + && $this->direction->pointIsWestOf($point1, $point2) + && $this->direction->pointIsNorthOf($point1, $point2); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirectionDistances.php b/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirectionDistances.php new file mode 100644 index 000000000..2252870f0 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirectionDistances.php @@ -0,0 +1,133 @@ +north = $north; + $this->east = $east; + $this->south = $south; + $this->west = $west; + } + + /** + * @psalm-pure + * @psalm-mutation-free + */ + public static function create(): self + { + return new self(0, 0, 0, 0); + } + + /** + * @psalm-mutation-free + */ + public function setNorth(float $north): self + { + $this->assertPositiveFloat($north); + + return new self($north, $this->east, $this->south, $this->west); + } + + /** + * @psalm-mutation-free + */ + public function setEast(float $east): self + { + $this->assertPositiveFloat($east); + + return new self($this->north, $east, $this->south, $this->west); + } + + /** + * @psalm-mutation-free + */ + public function setSouth(float $south): self + { + $this->assertPositiveFloat($south); + + return new self($this->north, $this->east, $south, $this->west); + } + + /** + * @psalm-mutation-free + */ + public function setWest(float $west): self + { + $this->assertPositiveFloat($west); + + return new self($this->north, $this->east, $this->south, $west); + } + + /** + * @psalm-mutation-free + */ + public function getNorth(): float + { + return $this->north; + } + + /** + * @psalm-mutation-free + */ + public function getEast(): float + { + return $this->east; + } + + /** + * @psalm-mutation-free + */ + public function getSouth(): float + { + return $this->south; + } + + /** + * @psalm-mutation-free + */ + public function getWest(): float + { + return $this->west; + } + + /** + * @psalm-pure + * @psalm-mutation-free + * + * @throws InvalidDistanceException + */ + private function assertPositiveFloat(float $value): void + { + if ($value < 0) { + throw new InvalidDistanceException('Negative distance is invalid.', 1857757416); + } + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirectionDistancesCalculator.php b/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirectionDistancesCalculator.php new file mode 100644 index 000000000..0c7fb9492 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/CardinalDirection/CardinalDirectionDistancesCalculator.php @@ -0,0 +1,78 @@ +getCardinalDirection($point1, $point2); + $directDistance = $point1->getDistance($point2, $distanceCalculator); + + switch ($cardinalDirection) { + case CardinalDirection::CARDINAL_DIRECTION_NONE: + return CardinalDirectionDistances::create(); + + case CardinalDirection::CARDINAL_DIRECTION_NORTH: + return CardinalDirectionDistances::create()->setSouth($directDistance); + + case CardinalDirection::CARDINAL_DIRECTION_EAST: + return CardinalDirectionDistances::create()->setWest($directDistance); + + case CardinalDirection::CARDINAL_DIRECTION_SOUTH: + return CardinalDirectionDistances::create()->setNorth($directDistance); + + case CardinalDirection::CARDINAL_DIRECTION_WEST: + return CardinalDirectionDistances::create()->setEast($directDistance); + + case CardinalDirection::CARDINAL_DIRECTION_NORTHWEST: + $bounds = new Bounds($point1, $point2); + $point3 = new Coordinate($bounds->getNorth(), $bounds->getEast()); + + return CardinalDirectionDistances::create() + ->setEast($point1->getDistance($point3, $distanceCalculator)) + ->setSouth($point3->getDistance($point2, $distanceCalculator)); + + case CardinalDirection::CARDINAL_DIRECTION_SOUTHWEST: + $bounds = new Bounds( + new Coordinate($point2->getLat(), $point1->getLng()), + new Coordinate($point1->getLat(), $point2->getLng()) + ); + $point3 = new Coordinate($bounds->getSouth(), $bounds->getEast()); + + return CardinalDirectionDistances::create() + ->setNorth($point3->getDistance($point2, $distanceCalculator)) + ->setEast($point1->getDistance($point3, $distanceCalculator)); + + case CardinalDirection::CARDINAL_DIRECTION_NORTHEAST: + $bounds = new Bounds( + new Coordinate($point1->getLat(), $point2->getLng()), + new Coordinate($point2->getLat(), $point1->getLng()) + ); + $point3 = new Coordinate($bounds->getNorth(), $bounds->getWest()); + + return CardinalDirectionDistances::create() + ->setSouth($point3->getDistance($point2, $distanceCalculator)) + ->setWest($point1->getDistance($point3, $distanceCalculator)); + + case CardinalDirection::CARDINAL_DIRECTION_SOUTHEAST: + $bounds = new Bounds($point2, $point1); + $point3 = new Coordinate($bounds->getSouth(), $bounds->getWest()); + + return CardinalDirectionDistances::create() + ->setNorth($point3->getDistance($point2, $distanceCalculator)) + ->setWest($point1->getDistance($point3, $distanceCalculator)); + } + + return CardinalDirectionDistances::create(); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Coordinate.php b/admin/vendor/mjaschen/phpgeo/src/Coordinate.php new file mode 100644 index 000000000..49283b508 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Coordinate.php @@ -0,0 +1,176 @@ + + */ +class Coordinate implements GeometryInterface +{ + /** + * @var float + */ + protected $lat; + + /** + * @var float + */ + protected $lng; + + /** + * @var Ellipsoid + */ + protected $ellipsoid; + + /** + * @param float $lat -90.0 .. +90.0 + * @param float $lng -180.0 .. +180.0 + * @param ?Ellipsoid $ellipsoid if omitted, WGS-84 is used + * + * @throws InvalidArgumentException + */ + public function __construct(float $lat, float $lng, ?Ellipsoid $ellipsoid = null) + { + if (! $this->isValidLatitude($lat)) { + throw new InvalidArgumentException('Latitude value must be numeric -90.0 .. +90.0 (given: ' . $lat . ')'); + } + + if (! $this->isValidLongitude($lng)) { + throw new InvalidArgumentException( + 'Longitude value must be numeric -180.0 .. +180.0 (given: ' . $lng . ')' + ); + } + + $this->lat = $lat; + $this->lng = $lng; + + if ($ellipsoid instanceof Ellipsoid) { + $this->ellipsoid = $ellipsoid; + + return; + } + + $this->ellipsoid = Ellipsoid::createDefault(); + } + + public function getLat(): float + { + return $this->lat; + } + + public function getLng(): float + { + return $this->lng; + } + + /** + * @return array + */ + public function getPoints(): array + { + return [$this]; + } + + public function getEllipsoid(): Ellipsoid + { + return $this->ellipsoid; + } + + /** + * Calculates the distance between the given coordinate + * and this coordinate. + */ + public function getDistance(Coordinate $coordinate, DistanceInterface $calculator): float + { + return $calculator->getDistance($this, $coordinate); + } + + /** + * Calculates the cardinal direction distances from this coordinate + * to given coordinate. + */ + public function getCardinalDirectionDistances( + Coordinate $coordinate, + DistanceInterface $calculator + ): CardinalDirectionDistances { + return (new CardinalDirectionDistancesCalculator()) + ->getCardinalDirectionDistances($this, $coordinate, $calculator); + } + + /** + * Checks if two points describe the same location within an allowed distance. + * + * Uses the Haversine distance calculator for distance calculation as it's + * precise enough for short-distance calculations. + * + * @see Haversine + */ + public function hasSameLocation(Coordinate $coordinate, float $allowedDistance = .001): bool + { + return $this->getDistance($coordinate, new Haversine()) <= $allowedDistance; + } + + /** + * Checks if this point intersects a given geometry. + * + * @throws InvalidGeometryException + */ + public function intersects(GeometryInterface $geometry): bool + { + if ($geometry instanceof self) { + return $this->hasSameLocation($geometry); + } + + if ($geometry instanceof Polygon) { + return $geometry->contains($this); + } + + throw new InvalidGeometryException('Only polygons can contain other geometries', 1655191821); + } + + public function format(FormatterInterface $formatter): string + { + return $formatter->format($this); + } + + protected function isValidLatitude(float $latitude): bool + { + return $this->isNumericInBounds($latitude, -90.0, 90.0); + } + + protected function isValidLongitude(float $longitude): bool + { + return $this->isNumericInBounds($longitude, -180.0, 180.0); + } + + /** + * Checks if the given value is (1) numeric, and (2) between lower + * and upper bounds (including the bounds values). + */ + protected function isNumericInBounds(float $value, float $lower, float $upper): bool + { + return !($value < $lower || $value > $upper); + } + + public function getBounds(): Bounds + { + return new Bounds($this, $this); + } + + public function getSegments(): array + { + throw new \RuntimeException('A single point instance does not contain valid segments', 6029644914); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Direction/Direction.php b/admin/vendor/mjaschen/phpgeo/src/Direction/Direction.php new file mode 100644 index 000000000..00bb7a013 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Direction/Direction.php @@ -0,0 +1,30 @@ +getLat() > $compareAgainst->getLat(); + } + + public function pointIsSouthOf(Coordinate $point, Coordinate $compareAgainst): bool + { + return $point->getLat() < $compareAgainst->getLat(); + } + + public function pointIsEastOf(Coordinate $point, Coordinate $compareAgainst): bool + { + return $point->getLng() > $compareAgainst->getLng(); + } + + public function pointIsWestOf(Coordinate $point, Coordinate $compareAgainst): bool + { + return $point->getLng() < $compareAgainst->getLng(); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Distance/DistanceInterface.php b/admin/vendor/mjaschen/phpgeo/src/Distance/DistanceInterface.php new file mode 100644 index 000000000..4f7683959 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Distance/DistanceInterface.php @@ -0,0 +1,23 @@ + + */ +interface DistanceInterface +{ + /** + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @return float distance between the two coordinates in meters + */ + public function getDistance(Coordinate $point1, Coordinate $point2): float; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Distance/Haversine.php b/admin/vendor/mjaschen/phpgeo/src/Distance/Haversine.php new file mode 100644 index 000000000..b143fc8c7 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Distance/Haversine.php @@ -0,0 +1,53 @@ + + */ +class Haversine implements DistanceInterface +{ + /** + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @throws NotMatchingEllipsoidException + * + * @return float + */ + public function getDistance(Coordinate $point1, Coordinate $point2): float + { + if ($point1->getEllipsoid()->getName() !== $point2->getEllipsoid()->getName()) { + throw new NotMatchingEllipsoidException('The ellipsoids for both coordinates must match'); + } + + $lat1 = deg2rad($point1->getLat()); + $lat2 = deg2rad($point2->getLat()); + $lng1 = deg2rad($point1->getLng()); + $lng2 = deg2rad($point2->getLng()); + + $dLat = $lat2 - $lat1; + $dLng = $lng2 - $lng1; + + $radius = $point1->getEllipsoid()->getArithmeticMeanRadius(); + + $distance = 2 * $radius * asin( + sqrt( + (sin($dLat / 2) ** 2) + + cos($lat1) * cos($lat2) * (sin($dLng / 2) ** 2) + ) + ); + + return round($distance, 3); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Distance/Vincenty.php b/admin/vendor/mjaschen/phpgeo/src/Distance/Vincenty.php new file mode 100644 index 000000000..4e2d480c1 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Distance/Vincenty.php @@ -0,0 +1,111 @@ + + */ +class Vincenty implements DistanceInterface +{ + /** + * @param Coordinate $point1 + * @param Coordinate $point2 + * + * @throws NotMatchingEllipsoidException + * @throws NotConvergingException + * + * @return float + */ + public function getDistance(Coordinate $point1, Coordinate $point2): float + { + if ($point1->getEllipsoid()->getName() !== $point2->getEllipsoid()->getName()) { + throw new NotMatchingEllipsoidException('The ellipsoids for both coordinates must match'); + } + + $lat1 = deg2rad($point1->getLat()); + $lat2 = deg2rad($point2->getLat()); + $lng1 = deg2rad($point1->getLng()); + $lng2 = deg2rad($point2->getLng()); + + $a = $point1->getEllipsoid()->getA(); + $b = $point1->getEllipsoid()->getB(); + $f = 1 / $point1->getEllipsoid()->getF(); + + $L = $lng2 - $lng1; + $U1 = atan((1 - $f) * tan($lat1)); + $U2 = atan((1 - $f) * tan($lat2)); + + $iterationsLeft = 100; + $lambda = $L; + + $sinU1 = sin($U1); + $sinU2 = sin($U2); + $cosU1 = cos($U1); + $cosU2 = cos($U2); + + do { + $sinLambda = sin($lambda); + $cosLambda = cos($lambda); + + $sinSigma = sqrt( + $cosU2 * $sinLambda * $cosU2 * $sinLambda + + ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda) * ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda) + ); + + if (abs($sinSigma) < 1E-12) { + return 0.0; + } + + $cosSigma = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosLambda; + + $sigma = atan2($sinSigma, $cosSigma); + + $sinAlpha = $cosU1 * $cosU2 * $sinLambda / $sinSigma; + + $cosSqAlpha = 1 - $sinAlpha * $sinAlpha; + + $cos2SigmaM = 0; + if (abs($cosSqAlpha) > 1E-12) { + $cos2SigmaM = $cosSigma - 2 * $sinU1 * $sinU2 / $cosSqAlpha; + } + + $C = $f / 16 * $cosSqAlpha * (4 + $f * (4 - 3 * $cosSqAlpha)); + + $lambdaP = $lambda; + + $lambda = $L + + (1 - $C) + * $f + * $sinAlpha + * ($sigma + $C * $sinSigma * ($cos2SigmaM + $C * $cosSigma * (- 1 + 2 * $cos2SigmaM * $cos2SigmaM))); + + $iterationsLeft--; + } while (abs($lambda - $lambdaP) > 1e-12 && $iterationsLeft > 0); + + if ($iterationsLeft === 0) { + throw new NotConvergingException('Vincenty calculation does not converge'); + } + + $uSq = $cosSqAlpha * ($a * $a - $b * $b) / ($b * $b); + $A = 1 + $uSq / 16384 * (4096 + $uSq * (- 768 + $uSq * (320 - 175 * $uSq))); + $B = $uSq / 1024 * (256 + $uSq * (- 128 + $uSq * (74 - 47 * $uSq))); + $deltaSigma = $B * $sinSigma * ( + $cos2SigmaM + + $B / 4 * ($cosSigma * (- 1 + 2 * $cos2SigmaM * $cos2SigmaM) + - $B / 6 * $cos2SigmaM * (- 3 + 4 * $sinSigma * $sinSigma) * (- 3 + 4 * $cos2SigmaM * $cos2SigmaM)) + ); + $s = $b * $A * ($sigma - $deltaSigma); + + return round($s, 3); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Ellipsoid.php b/admin/vendor/mjaschen/phpgeo/src/Ellipsoid.php new file mode 100644 index 000000000..307646ce4 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Ellipsoid.php @@ -0,0 +1,128 @@ + + */ +class Ellipsoid +{ + /** + * @var string + */ + protected $name; + + /** + * The semi-major axis + * + * @var float + */ + protected $a; + + /** + * The Inverse Flattening (1/f) + * + * @var float + */ + protected $f; + + /** + * Some often used ellipsoids + * + * @var array + */ + protected static $configs = [ + 'WGS-84' => [ + 'name' => 'World Geodetic System 1984', + 'a' => 6378137.0, + 'f' => 298.257223563, + ], + 'GRS-80' => [ + 'name' => 'Geodetic Reference System 1980', + 'a' => 6378137.0, + 'f' => 298.257222100, + ], + ]; + + /** + * @param string $name + * @param float $a + * @param float $f + */ + public function __construct(string $name, float $a, float $f) + { + $this->name = $name; + $this->a = $a; + $this->f = $f; + } + + /** + * @param string $name + * + * @return Ellipsoid + */ + public static function createDefault(string $name = 'WGS-84'): Ellipsoid + { + return static::createFromArray(static::$configs[$name]); + } + + /** + * @param array $config + * + * @return Ellipsoid + */ + public static function createFromArray(array $config): Ellipsoid + { + return new self($config['name'], $config['a'], $config['f']); + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return float + */ + public function getA(): float + { + return $this->a; + } + + /** + * Calculation of the semi-minor axis + * + * @return float + */ + public function getB(): float + { + return $this->a * (1 - 1 / $this->f); + } + + /** + * @return float + */ + public function getF(): float + { + return $this->f; + } + + /** + * Calculates the arithmetic mean radius + * + * @see http://home.online.no/~sigurdhu/WGS84_Eng.html + * + * @return float + */ + public function getArithmeticMeanRadius(): float + { + return $this->a * (1 - 1 / $this->f / 3); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Exception/BearingNotAvailableException.php b/admin/vendor/mjaschen/phpgeo/src/Exception/BearingNotAvailableException.php new file mode 100644 index 000000000..40f431b67 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Exception/BearingNotAvailableException.php @@ -0,0 +1,9 @@ +calculateDestination($center, 315, $distance); + $southEast = $bearing->calculateDestination($center, 135, $distance); + + return new Bounds($northWest, $southEast); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Factory/CoordinateFactory.php b/admin/vendor/mjaschen/phpgeo/src/Factory/CoordinateFactory.php new file mode 100644 index 000000000..5f3ca4abe --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Factory/CoordinateFactory.php @@ -0,0 +1,163 @@ + + */ +class CoordinateFactory implements GeometryFactoryInterface +{ + /** + * Creates a Coordinate instance from the given string. + * + * The string is parsed by a regular expression for a known + * format of geographical coordinates. + * + * @param string $string formatted geographical coordinate + * + * @throws InvalidArgumentException + */ + public static function fromString(string $string, ?Ellipsoid $ellipsoid = null): Coordinate + { + $string = self::mergeSecondsToMinutes($string); + + $result = self::parseDecimalMinutesWithoutCardinalLetters($string, $ellipsoid); + + if ($result instanceof Coordinate) { + return $result; + } + + $result = self::parseDecimalMinutesWithCardinalLetters($string, $ellipsoid); + + if ($result instanceof Coordinate) { + return $result; + } + + $result = self::parseDecimalDegreesWithoutCardinalLetters($string, $ellipsoid); + + if ($result instanceof Coordinate) { + return $result; + } + + $result = self::parseDecimalDegreesWithCardinalLetters($string, $ellipsoid); + + if ($result instanceof Coordinate) { + return $result; + } + + throw new InvalidArgumentException('Format of coordinates was not recognized'); + } + + /** + * @return Coordinate|null + * @throws InvalidArgumentException + */ + private static function parseDecimalMinutesWithoutCardinalLetters(string $string, ?Ellipsoid $ellipsoid = null) + { + // Decimal minutes without cardinal letters, e. g. "52 12.345, 13 23.456", + // "52° 12.345, 13° 23.456", "52° 12.345′, 13° 23.456′", "52 12.345 N, 13 23.456 E", + // "N52° 12.345′ E13° 23.456′" + $regexp = '/(-?\d{1,2})°?\s+(\d{1,2}\.?\d*)[\'′]?[, ]\s*(-?\d{1,3})°?\s+(\d{1,2}\.?\d*)[\'′]?/u'; + + if (preg_match($regexp, $string, $match) === 1) { + $latitude = (int)$match[1] >= 0 + ? (int)$match[1] + (float)$match[2] / 60 + : (int)$match[1] - (float)$match[2] / 60; + $longitude = (int)$match[3] >= 0 + ? (int)$match[3] + (float)$match[4] / 60 + : (int)$match[3] - (float)$match[4] / 60; + + return new Coordinate($latitude, $longitude, $ellipsoid); + } + + return null; + } + + /** + * @return ?Coordinate + * @throws InvalidArgumentException + */ + private static function parseDecimalMinutesWithCardinalLetters(string $string, ?Ellipsoid $ellipsoid = null) + { + // Decimal minutes with cardinal letters, e. g. "52 12.345, 13 23.456", + // "52° 12.345, 13° 23.456", "52° 12.345′, 13° 23.456′", "52 12.345 N, 13 23.456 E", + // "N52° 12.345′ E13° 23.456′" + $regexp = '/([NS]?\s*)(\d{1,2})°?\s+(\d{1,2}\.?\d*)[\'′]?(\s*[NS]?)'; + $regexp .= '[, ]\s*([EW]?\s*)(\d{1,3})°?\s+(\d{1,2}\.?\d*)[\'′]?(\s*[EW]?)/ui'; + + if (preg_match($regexp, $string, $match) === 1) { + $latitude = (int)$match[2] + (float)$match[3] / 60; + if (strtoupper(trim($match[1])) === 'S' || strtoupper(trim($match[4])) === 'S') { + $latitude = - $latitude; + } + $longitude = (int)$match[6] + (float)$match[7] / 60; + if (strtoupper(trim($match[5])) === 'W' || strtoupper(trim($match[8])) === 'W') { + $longitude = - $longitude; + } + + return new Coordinate($latitude, $longitude, $ellipsoid); + } + + return null; + } + + /** + * @return Coordinate|null + * @throws InvalidArgumentException + */ + private static function parseDecimalDegreesWithoutCardinalLetters(string $string, ?Ellipsoid $ellipsoid = null) + { + // The most simple format: decimal degrees without cardinal letters, + // e. g. "52.5, 13.5" or "53.25732 14.24984" + if (preg_match('/(-?\d{1,2}\.?\d*)°?[, ]\s*(-?\d{1,3}\.?\d*)°?/u', $string, $match) === 1) { + return new Coordinate((float)$match[1], (float)$match[2], $ellipsoid); + } + + return null; + } + + /** + * @return Coordinate|null + * @throws InvalidArgumentException + */ + private static function parseDecimalDegreesWithCardinalLetters(string $string, ?Ellipsoid $ellipsoid = null) + { + // Decimal degrees with cardinal letters, e. g. "N52.5, E13.5", + // "40.2S, 135.3485W", or "56.234°N, 157.245°W" + $regexp = '/([NS]?\s*)(\d{1,2}\.?\d*)°?(\s*[NS]?)[, ]\s*([EW]?\s*)(\d{1,3}\.?\d*)°?(\s*[EW]?)/ui'; + + if (preg_match($regexp, $string, $match) === 1) { + $latitude = $match[2]; + if (strtoupper(trim($match[1])) === 'S' || strtoupper(trim($match[3])) === 'S') { + $latitude = - $latitude; + } + $longitude = $match[5]; + if (strtoupper(trim($match[4])) === 'W' || strtoupper(trim($match[6])) === 'W') { + $longitude = - $longitude; + } + + return new Coordinate((float)$latitude, (float)$longitude, $ellipsoid); + } + + return null; + } + + private static function mergeSecondsToMinutes(string $string): string + { + return preg_replace_callback( + '/(\d+)(°|\s)\s*(\d+)(\'|′|\s)(\s*([0-9\.]*))("|\'\'|″|′′)?/u', + static function (array $matches): string { + return sprintf('%d %f', $matches[1], (float)$matches[3] + (float)$matches[6] / 60); + }, + $string + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Factory/GeometryFactoryInterface.php b/admin/vendor/mjaschen/phpgeo/src/Factory/GeometryFactoryInterface.php new file mode 100644 index 000000000..7858c615b --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Factory/GeometryFactoryInterface.php @@ -0,0 +1,22 @@ + + */ +interface GeometryFactoryInterface +{ + /** + * @param string $string + * + * @return GeometryInterface + */ + public static function fromString(string $string); +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DMS.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DMS.php new file mode 100644 index 000000000..bd1e7aecd --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DMS.php @@ -0,0 +1,216 @@ + + */ +class DMS implements FormatterInterface +{ + public const UNITS_UTF8 = 'UTF-8'; + public const UNITS_ASCII = 'ASCII'; + + /** + * @var string Separator string between latitude and longitude + */ + protected $separator; + + /** + * Use cardinal letters for N/S and W/E instead of minus sign + * + * @var bool + */ + protected $useCardinalLetters; + + /** + * @var string + * + * @psalm-suppress PropertyNotSetInConstructor + */ + protected $unitType; + + /** + * @var array + */ + protected $units = [ + 'UTF-8' => [ + 'deg' => '°', + 'min' => '′', + 'sec' => '″', + ], + 'ASCII' => [ + 'deg' => '°', + 'min' => '\'', + 'sec' => '"', + ], + ]; + + /** + * @throws InvalidArgumentException + */ + public function __construct( + string $separator = ' ', + bool $useCardinalLetters = false, + string $unitType = self::UNITS_UTF8 + ) { + $this->separator = $separator; + $this->useCardinalLetters = $useCardinalLetters; + $this->unitType = $unitType; + } + + /** + * Sets the separator between latitude and longitude values + * + * @param string $separator + * + * @return DMS + * + * @deprecated + */ + public function setSeparator(string $separator): DMS + { + $this->separator = $separator; + + return $this; + } + + /** + * @param bool $value + * + * @return DMS + * + * @deprecated + */ + public function useCardinalLetters(bool $value): DMS + { + $this->useCardinalLetters = $value; + + return $this; + } + + /** + * @param string $type + * + * @return DMS + * @throws InvalidArgumentException + * + * @deprecated + */ + public function setUnits(string $type): DMS + { + if (!array_key_exists($type, $this->units)) { + throw new InvalidArgumentException('Invalid unit type'); + } + + $this->unitType = $type; + + return $this; + } + + /** + * @return string + */ + public function getUnitType(): string + { + return $this->unitType; + } + + /** + * @param Coordinate $coordinate + * + * @return string + */ + public function format(Coordinate $coordinate): string + { + $lat = $coordinate->getLat(); + $lng = $coordinate->getLng(); + + $latValue = abs($lat); + $latDegrees = (int)$latValue; + + $latMinutesDecimal = $latValue - $latDegrees; + $latMinutes = (int)(60 * $latMinutesDecimal); + + $latSeconds = 60 * (60 * $latMinutesDecimal - $latMinutes); + + $lngValue = abs($lng); + $lngDegrees = (int)$lngValue; + + $lngMinutesDecimal = $lngValue - $lngDegrees; + $lngMinutes = (int)(60 * $lngMinutesDecimal); + + $lngSeconds = 60 * (60 * $lngMinutesDecimal - $lngMinutes); + + return sprintf( + '%s%02d%s %02d%s %02d%s%s%s%s%03d%s %02d%s %02d%s%s', + $this->getLatPrefix($lat), + abs($latDegrees), + $this->units[$this->unitType]['deg'], + $latMinutes, + $this->units[$this->unitType]['min'], + round($latSeconds, 0), + $this->units[$this->unitType]['sec'], + $this->getLatSuffix($lat), + $this->separator, + $this->getLngPrefix($lng), + abs($lngDegrees), + $this->units[$this->unitType]['deg'], + $lngMinutes, + $this->units[$this->unitType]['min'], + round($lngSeconds, 0), + $this->units[$this->unitType]['sec'], + $this->getLngSuffix($lng) + ); + } + + protected function getLatPrefix(float $lat): string + { + if ($this->useCardinalLetters || $lat >= 0) { + return ''; + } + + return '-'; + } + + protected function getLngPrefix(float $lng): string + { + if ($this->useCardinalLetters || $lng >= 0) { + return ''; + } + + return '-'; + } + + protected function getLatSuffix(float $lat): string + { + if (!$this->useCardinalLetters) { + return ''; + } + + if ($lat >= 0) { + return ' N'; + } + + return ' S'; + } + + protected function getLngSuffix(float $lng): string + { + if (!$this->useCardinalLetters) { + return ''; + } + + if ($lng >= 0) { + return ' E'; + } + + return ' W'; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DecimalDegrees.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DecimalDegrees.php new file mode 100644 index 000000000..54454ae96 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DecimalDegrees.php @@ -0,0 +1,64 @@ + + */ +class DecimalDegrees implements FormatterInterface +{ + /** + * @var string Separator string between latitude and longitude + */ + protected $separator; + + /** + * @var int + */ + protected $digits = 5; + + /** + * @param string $separator + * @param int $digits + */ + public function __construct(string $separator = ' ', int $digits = 5) + { + $this->separator = $separator; + $this->digits = $digits; + } + + /** + * @param Coordinate $coordinate + * + * @return string + */ + public function format(Coordinate $coordinate): string + { + return sprintf( + '%.' . $this->digits . 'f%s%.' . $this->digits . 'f', + $coordinate->getLat(), + $this->separator, + $coordinate->getLng() + ); + } + + /** + * Sets the separator between latitude and longitude values + * + * @param string $separator + * + * @return $this + */ + public function setSeparator(string $separator): DecimalDegrees + { + $this->separator = $separator; + + return $this; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DecimalMinutes.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DecimalMinutes.php new file mode 100644 index 000000000..2b9da65b8 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/DecimalMinutes.php @@ -0,0 +1,252 @@ + + */ +class DecimalMinutes implements FormatterInterface +{ + public const UNITS_UTF8 = 'UTF-8'; + public const UNITS_ASCII = 'ASCII'; + + /** + * @var string Separator string between latitude and longitude + */ + protected $separator; + + /** + * Use cardinal letters for N/S and W/E instead of minus sign + * + * @var bool + */ + protected $useCardinalLetters; + + /** + * @var string + * + * @psalm-suppress PropertyNotSetInConstructor + */ + protected $unitType; + + /** + * @var int + */ + protected $digits = 3; + + /** + * @var string + */ + protected $decimalPoint = '.'; + + /** + * @var array + */ + protected $units = [ + 'UTF-8' => [ + 'deg' => '°', + 'min' => '′', + ], + 'ASCII' => [ + 'deg' => '°', + 'min' => '\'', + ], + ]; + + /** + * @param string $separator + */ + public function __construct(string $separator = ' ') + { + $this->separator = $separator; + $this->useCardinalLetters = false; + + $this->setUnits(self::UNITS_UTF8); + } + + /** + * Sets the separator between latitude and longitude values + * + * @param string $separator + * + * @return DecimalMinutes + */ + public function setSeparator(string $separator): DecimalMinutes + { + $this->separator = $separator; + + return $this; + } + + /** + * @param bool $value + * + * @return DecimalMinutes + */ + public function useCardinalLetters(bool $value): DecimalMinutes + { + $this->useCardinalLetters = $value; + + return $this; + } + + /** + * @param string $type + * + * @return DecimalMinutes + * @throws \InvalidArgumentException + */ + public function setUnits(string $type): DecimalMinutes + { + if (! array_key_exists($type, $this->units)) { + throw new InvalidArgumentException('Invalid unit type'); + } + + $this->unitType = $type; + + return $this; + } + + /** + * @return string + */ + public function getUnitType(): string + { + return $this->unitType; + } + + /** + * @param int $digits + * + * @return DecimalMinutes + */ + public function setDigits(int $digits): DecimalMinutes + { + $this->digits = $digits; + + return $this; + } + + /** + * @param string $decimalPoint + * + * @return DecimalMinutes + */ + public function setDecimalPoint(string $decimalPoint): DecimalMinutes + { + $this->decimalPoint = $decimalPoint; + + return $this; + } + + /** + * @param Coordinate $coordinate + * + * @return string + */ + public function format(Coordinate $coordinate): string + { + $lat = $coordinate->getLat(); + $lng = $coordinate->getLng(); + + $latValue = abs($lat); + $latDegrees = (int)$latValue; + + $latMinutesDecimal = $latValue - $latDegrees; + $latMinutes = 60 * $latMinutesDecimal; + + $lngValue = abs($lng); + $lngDegrees = (int)$lngValue; + + $lngMinutesDecimal = $lngValue - $lngDegrees; + $lngMinutes = 60 * $lngMinutesDecimal; + + return sprintf( + '%s%02d%s %s%s%s%s%s%03d%s %s%s%s', + $this->getLatPrefix($lat), + abs($latDegrees), + $this->units[$this->unitType]['deg'], + number_format($latMinutes, $this->digits, $this->decimalPoint, $this->decimalPoint), + $this->units[$this->unitType]['min'], + $this->getLatSuffix($lat), + $this->separator, + $this->getLngPrefix($lng), + abs($lngDegrees), + $this->units[$this->unitType]['deg'], + number_format($lngMinutes, $this->digits, $this->decimalPoint, $this->decimalPoint), + $this->units[$this->unitType]['min'], + $this->getLngSuffix($lng) + ); + } + + /** + * @param float $lat + * + * @return string + */ + protected function getLatPrefix(float $lat): string + { + if ($this->useCardinalLetters || $lat >= 0) { + return ''; + } + + return '-'; + } + + /** + * @param float $lng + * + * @return string + */ + protected function getLngPrefix(float $lng): string + { + if ($this->useCardinalLetters || $lng >= 0) { + return ''; + } + + return '-'; + } + + /** + * @param float $lat + * + * @return string + */ + protected function getLatSuffix(float $lat): string + { + if (! $this->useCardinalLetters) { + return ''; + } + + if ($lat >= 0) { + return ' N'; + } + + return ' S'; + } + + /** + * @param float $lng + * + * @return string + */ + protected function getLngSuffix(float $lng): string + { + if (! $this->useCardinalLetters) { + return ''; + } + + if ($lng >= 0) { + return ' E'; + } + + return ' W'; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/FormatterInterface.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/FormatterInterface.php new file mode 100644 index 000000000..fe35c23b4 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/FormatterInterface.php @@ -0,0 +1,22 @@ + + */ +interface FormatterInterface +{ + /** + * @param Coordinate $coordinate + * + * @return string + */ + public function format(Coordinate $coordinate): string; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/GeoJSON.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/GeoJSON.php new file mode 100644 index 000000000..7d831358d --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Coordinate/GeoJSON.php @@ -0,0 +1,33 @@ + + */ +class GeoJSON implements FormatterInterface +{ + /** + * @param Coordinate $coordinate + * + * @return string + */ + public function format(Coordinate $coordinate): string + { + return json_encode( + [ + 'type' => 'Point', + 'coordinates' => [ + $coordinate->getLng(), + $coordinate->getLat(), + ], + ] + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Polygon/FormatterInterface.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polygon/FormatterInterface.php new file mode 100644 index 000000000..a20981ea0 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polygon/FormatterInterface.php @@ -0,0 +1,23 @@ + + * @author Richard Barnes + */ +interface FormatterInterface +{ + /** + * @param Polygon $polygon + * + * @return string + */ + public function format(Polygon $polygon): string; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Polygon/GeoJSON.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polygon/GeoJSON.php new file mode 100644 index 000000000..bd728f48a --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polygon/GeoJSON.php @@ -0,0 +1,45 @@ + + */ +class GeoJSON implements FormatterInterface +{ + /** + * @param Polygon $polygon + * + * @return string + * + * @throws InvalidPolygonException + */ + public function format(Polygon $polygon): string + { + if ($polygon->getNumberOfPoints() < 3) { + throw new InvalidPolygonException('A polygon must consist of at least three points.'); + } + + $points = []; + + /** @var Coordinate $point */ + foreach ($polygon->getPoints() as $point) { + $points[] = [$point->getLng(), $point->getLat()]; + } + + return json_encode( + [ + 'type' => 'Polygon', + 'coordinates' => [$points], + ] + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Polyline/FormatterInterface.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polyline/FormatterInterface.php new file mode 100644 index 000000000..a29bfaae0 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polyline/FormatterInterface.php @@ -0,0 +1,22 @@ + + */ +interface FormatterInterface +{ + /** + * @param Polyline $polyline + * + * @return string + */ + public function format(Polyline $polyline): string; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Formatter/Polyline/GeoJSON.php b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polyline/GeoJSON.php new file mode 100644 index 000000000..bf7a275fa --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Formatter/Polyline/GeoJSON.php @@ -0,0 +1,36 @@ + + */ +class GeoJSON implements FormatterInterface +{ + /** + * @param Polyline $polyline + * + * @return string + */ + public function format(Polyline $polyline): string + { + $points = []; + + foreach ($polyline->getPoints() as $point) { + $points[] = [$point->getLng(), $point->getLat()]; + } + + return json_encode( + [ + 'type' => 'LineString', + 'coordinates' => $points, + ] + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/GeometryInterface.php b/admin/vendor/mjaschen/phpgeo/src/GeometryInterface.php new file mode 100644 index 000000000..310b13ed7 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/GeometryInterface.php @@ -0,0 +1,15 @@ + + */ + public function getPoints(): array; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/GetBoundsTrait.php b/admin/vendor/mjaschen/phpgeo/src/GetBoundsTrait.php new file mode 100644 index 000000000..2d3e257d6 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/GetBoundsTrait.php @@ -0,0 +1,43 @@ + $points + */ +trait GetBoundsTrait +{ + /** + * @return array + */ + abstract public function getPoints(): array; + + /** + * @return Bounds + */ + public function getBounds(): Bounds + { + $latMin = 90.0; + $latMax = -90.0; + $lngMin = 180.0; + $lngMax = -180.0; + + foreach ($this->getPoints() as $point) { + $latMin = min($point->getLat(), $latMin); + $lngMin = min($point->getLng(), $lngMin); + $latMax = max($point->getLat(), $latMax); + $lngMax = max($point->getLng(), $lngMax); + } + + return new Bounds( + new Coordinate($latMax, $lngMin), + new Coordinate($latMin, $lngMax) + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Intersection/Intersection.php b/admin/vendor/mjaschen/phpgeo/src/Intersection/Intersection.php new file mode 100644 index 000000000..66e77263f --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Intersection/Intersection.php @@ -0,0 +1,90 @@ +contains($geometry2); + } + + if ($geometry1 instanceof Coordinate && $geometry2 instanceof Polygon) { + return $geometry2->contains($geometry1); + } + + if ($precise === true) { + return $this->intersectsGeometry($geometry1, $geometry2); + } + + return $this->intersectsBounds($geometry1, $geometry2); + } + + /** + * Checks if this geometry's bounds and the given bounds intersect. + */ + private function intersectsBounds(GeometryInterface $geometry1, GeometryInterface $geometry2): bool + { + $direction = new Direction(); + /** @var Coordinate|Line|Polyline|Polygon $geometry1 */ + $bounds1 = $geometry1->getBounds(); + /** @var Coordinate|Line|Polyline|Polygon $geometry2 */ + $bounds2 = $geometry2->getBounds(); + + return !( + $direction->pointIsEastOf($bounds1->getSouthWest(), $bounds2->getSouthEast()) + || $direction->pointIsSouthOf($bounds1->getNorthWest(), $bounds2->getSouthWest()) + || $direction->pointIsWestOf($bounds1->getSouthEast(), $bounds2->getSouthWest()) + || $direction->pointIsNorthOf($bounds1->getSouthWest(), $bounds2->getNorthWest()) + ); + } + + /** + * Checks if this geometry and the given geometry intersect by checking + * their segments for intersections. + * + * @throws InvalidGeometryException + */ + private function intersectsGeometry(GeometryInterface $geometry1, GeometryInterface $geometry2): bool + { + if ($geometry1 instanceof Coordinate && $geometry2 instanceof Coordinate) { + return $geometry1->hasSameLocation($geometry2); + } + + if ($geometry1 instanceof Coordinate || $geometry2 instanceof Coordinate) { + throw new InvalidGeometryException('Only can check point intersections for polygons', 7311194789); + } + + if (($geometry1 instanceof Polygon) && $geometry1->containsGeometry($geometry2)) { + return true; + } + + if (($geometry2 instanceof Polygon) && $geometry2->containsGeometry($geometry1)) { + return true; + } + + /** @var Line|Polyline|Polygon $geometry1 */ + foreach ($geometry1->getSegments() as $segment) { + /** @var Line|Polyline|Polygon $geometry2 */ + foreach ($geometry2->getSegments() as $otherSegment) { + if ($segment->intersectsLine($otherSegment)) { + return true; + } + } + } + + return false; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Line.php b/admin/vendor/mjaschen/phpgeo/src/Line.php new file mode 100644 index 000000000..e94bd0fa4 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Line.php @@ -0,0 +1,280 @@ + + */ +class Line implements GeometryInterface +{ + use GetBoundsTrait; + + public const ORIENTATION_COLLINEAR = 0; + public const ORIENTATION_CLOCKWISE = 1; + public const ORIENTATION_ANTI_CLOCKWISE = 2; + + /** + * @var Coordinate + */ + protected $point1; + + /** + * @var Coordinate + */ + protected $point2; + + /** + * @param Coordinate $point1 + * @param Coordinate $point2 + */ + public function __construct(Coordinate $point1, Coordinate $point2) + { + $this->point1 = $point1; + $this->point2 = $point2; + } + + /** + * @param Coordinate $point1 + * + * @return void + * + * @deprecated + */ + public function setPoint1(Coordinate $point1) + { + $this->point1 = $point1; + } + + /** + * @return Coordinate + */ + public function getPoint1(): Coordinate + { + return $this->point1; + } + + /** + * @param Coordinate $point2 + * + * @return void + * + * @deprecated + */ + public function setPoint2(Coordinate $point2) + { + $this->point2 = $point2; + } + + /** + * @return Coordinate + */ + public function getPoint2(): Coordinate + { + return $this->point2; + } + + /** + * Returns an array containing the two points. + * + * @return array + */ + public function getPoints(): array + { + return [$this->point1, $this->point2]; + } + + /** + * Returns an array containing the line segment. + * + * @return array + */ + public function getSegments(): array + { + return [$this]; + } + + /** + * Calculates the length of the line (distance between the two + * coordinates). + * + * @param DistanceInterface $calculator instance of distance calculation class + * + * @return float + */ + public function getLength(DistanceInterface $calculator): float + { + return $calculator->getDistance($this->point1, $this->point2); + } + + /** + * @param BearingInterface $bearingCalculator + * + * @return float + */ + public function getBearing(BearingInterface $bearingCalculator): float + { + return $bearingCalculator->calculateBearing($this->point1, $this->point2); + } + + /** + * @param BearingInterface $bearingCalculator + * + * @return float + */ + public function getFinalBearing(BearingInterface $bearingCalculator): float + { + return $bearingCalculator->calculateFinalBearing($this->point1, $this->point2); + } + + /** + * Create a new instance with reversed point order, i. e. reversed direction. + * + * @return Line + */ + public function getReverse(): Line + { + return new self($this->point2, $this->point1); + } + + /** + * Get the midpoint of a Line segment + * + * @see http://www.movable-type.co.uk/scripts/latlong.html#midpoint + * + * @return Coordinate + */ + public function getMidpoint(): Coordinate + { + $lat1 = deg2rad($this->point1->getLat()); + $lng1 = deg2rad($this->point1->getLng()); + $lat2 = deg2rad($this->point2->getLat()); + $lng2 = deg2rad($this->point2->getLng()); + $deltaLng = $lng2 - $lng1; + + $A = new Cartesian(cos($lat1), 0, sin($lat1)); + $B = new Cartesian(cos($lat2) * cos($deltaLng), cos($lat2) * sin($deltaLng), sin($lat2)); + $C = $A->add($B); + + $latMid = atan2($C->getZ(), sqrt($C->getX() ** 2 + $C->getY() ** 2)); + $lngMid = $lng1 + atan2($C->getY(), $C->getX()); + + return new Coordinate(rad2deg($latMid), rad2deg($lngMid)); + } + + /** + * Returns the point which is located on the line at the + * given fraction (starting at point 1). + * + * @see http://www.movable-type.co.uk/scripts/latlong.html#intermediate-point + * @see http://www.edwilliams.org/avform.htm#Intermediate + * + * @param float $fraction 0.0 ... 1.0 (smaller or larger values work too) + * + * @return Coordinate + * + * @throws RuntimeException + */ + public function getIntermediatePoint(float $fraction): Coordinate + { + $lat1 = deg2rad($this->point1->getLat()); + $lng1 = deg2rad($this->point1->getLng()); + $lat2 = deg2rad($this->point2->getLat()); + $lng2 = deg2rad($this->point2->getLng()); + $deltaLat = $lat2 - $lat1; + $deltaLng = $lng2 - $lng1; + + if ($lat1 + $lat2 == 0.0 && abs($lng1 - $lng2) == M_PI) { + throw new RuntimeException( + 'Start and end points are antipodes, route is therefore undefined.', + 5382449689 + ); + } + + $a = sin($deltaLat / 2) ** 2 + cos($lat1) * cos($lat2) * sin($deltaLng / 2) ** 2; + $delta = 2 * atan2(sqrt($a), sqrt(1 - $a)); + + $A = sin((1 - $fraction) * $delta) / sin($delta); + $B = sin($fraction * $delta) / sin($delta); + + $x = $A * cos($lat1) * cos($lng1) + $B * cos($lat2) * cos($lng2); + $y = $A * cos($lat1) * sin($lng1) + $B * cos($lat2) * sin($lng2); + $z = $A * sin($lat1) + $B * sin($lat2); + + $lat = atan2($z, sqrt($x ** 2 + $y ** 2)); + $lng = atan2($y, $x); + + return new Coordinate(rad2deg($lat), rad2deg($lng)); + } + + /** + * Compares the location of a given coordinate to this line returning + * its orientation as: + * + * - 0 if the coordinate is collinear to this line segment + * - 1 if the coordinate's orientation is clockwise to this line segment + * - 2 if the coordinate's orientation is anti-clockwise to this line segment + */ + public function getOrientation(Coordinate $coordinate): int + { + $crossproduct1 = ($this->point2->getLat() - $this->point1->getLat()) + * ($coordinate->getLng() - $this->point2->getLng()); + $crossproduct2 = ($this->point2->getLng() - $this->point1->getLng()) + * ($coordinate->getLat() - $this->point2->getLat()); + $delta = $crossproduct1 - $crossproduct2; + + if ($delta > 0) { + return self::ORIENTATION_CLOCKWISE; + } + + if ($delta < 0) { + return self::ORIENTATION_ANTI_CLOCKWISE; + } + + return self::ORIENTATION_COLLINEAR; + } + + /** + * Two lines intersect if: + * + * 1. the points of the given line are oriented into opposite directions + * 2. the points of this line are oriented into opposite directions + * 3. the points are collinear and the two line segments are overlapping + */ + public function intersectsLine(Line $line): bool + { + $orientation = []; + $orientation[11] = $this->getOrientation($line->getPoint1()); + $orientation[12] = $this->getOrientation($line->getPoint2()); + $orientation[21] = $line->getOrientation($this->getPoint1()); + $orientation[22] = $line->getOrientation($this->getPoint2()); + + // the lines cross + if ( + $orientation[11] !== $orientation[12] + && $orientation[21] !== $orientation[22] + ) { + return true; + } + + // the lines are collinear or touch + if ( + in_array(self::ORIENTATION_COLLINEAR, $orientation, true) + && (new Intersection())->intersects($this, $line, false) + ) { + return true; + } + + // the lines do not overlap + return false; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Polygon.php b/admin/vendor/mjaschen/phpgeo/src/Polygon.php new file mode 100644 index 000000000..1582366f6 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Polygon.php @@ -0,0 +1,260 @@ + + */ + protected $points = []; + + /** + * @param Coordinate $point + * + * @return void + */ + public function addPoint(Coordinate $point): void + { + $this->points[] = $point; + } + + /** + * @param array $points + */ + public function addPoints(array $points): void + { + foreach ($points as $point) { + $this->addPoint($point); + } + } + + /** + * @return array + */ + public function getPoints(): array + { + return $this->points; + } + + /** + * Return all polygon point's latitudes. + * + * @return array + */ + public function getLats(): array + { + $lats = []; + + foreach ($this->points as $point) { + /** @var Coordinate $point */ + $lats[] = $point->getLat(); + } + + return $lats; + } + + /** + * Return all polygon point's longitudes. + * + * @return array + */ + public function getLngs(): array + { + $lngs = []; + + foreach ($this->points as $point) { + /** @var Coordinate $point */ + $lngs[] = $point->getLng(); + } + + return $lngs; + } + + /** + * @return int + */ + public function getNumberOfPoints(): int + { + return count($this->points); + } + + /** + * @param FormatterInterface $formatter + * + * @return string + */ + public function format(FormatterInterface $formatter): string + { + return $formatter->format($this); + } + + /** + * @return array + */ + public function getSegments(): array + { + $length = count($this->points); + $segments = []; + + if ($length <= 1) { + return $segments; + } + + for ($i = 1; $i < $length; $i++) { + $segments[] = new Line($this->points[$i - 1], $this->points[$i]); + } + + // to close the polygon we have to add the final segment between + // the last point and the first point + $segments[] = new Line($this->points[$i - 1], $this->points[0]); + + return $segments; + } + + /** + * Determine if given geometry is contained inside the polygon. This is + * assumed to be true, if each point of the geometry is inside the polygon. + * + * Edge cases: + * + * - it's not detected when a line between two points is outside the polygon + * - @see contains() for more restrictions + * + * @param GeometryInterface $geometry + * + * @return bool + */ + public function containsGeometry(GeometryInterface $geometry): bool + { + $geometryInPolygon = true; + + foreach ($geometry->getPoints() as $point) { + $geometryInPolygon = $geometryInPolygon && $this->contains($point); + } + + return $geometryInPolygon; + } + + /** + * Determine if given point is contained inside the polygon. Uses the PNPOLY + * algorithm by W. Randolph Franklin. Therfore some edge cases may not give the + * expected results, e.g. if the point resides on the polygon boundary. + * + * @see https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html + * + * For special cases this calculation leads to wrong results: + * + * - if the polygons spans over the longitude boundaries at 180/-180 degrees + * + * @param Coordinate $point + * + * @return bool + */ + public function contains(Coordinate $point): bool + { + $numberOfPoints = $this->getNumberOfPoints(); + $polygonLats = $this->getLats(); + $polygonLngs = $this->getLngs(); + + $polygonContainsPoint = false; + + for ($node = 0, $altNode = $numberOfPoints - 1; $node < $numberOfPoints; $altNode = $node++) { + $condition = ($polygonLngs[$node] > $point->getLng()) !== ($polygonLngs[$altNode] > $point->getLng()) + && ($point->getLat() < ($polygonLats[$altNode] - $polygonLats[$node]) + * ($point->getLng() - $polygonLngs[$node]) + / ($polygonLngs[$altNode] - $polygonLngs[$node]) + $polygonLats[$node]); + + if ($condition) { + $polygonContainsPoint = !$polygonContainsPoint; + } + } + + return $polygonContainsPoint; + } + + /** + * Calculates the polygon perimeter. + * + * @param DistanceInterface $calculator instance of distance calculation class + * + * @return float + */ + public function getPerimeter(DistanceInterface $calculator): float + { + $perimeter = 0.0; + + if (count($this->points) < 2) { + return $perimeter; + } + + foreach ($this->getSegments() as $segment) { + $perimeter += $segment->getLength($calculator); + } + + return $perimeter; + } + + /** + * Calculates the polygon area. + * + * This algorithm gives inaccurate results as it ignores + * ellipsoid parameters other than to arithmetic mean radius. + * The error should be < 1 % for small areas. + * + * @return float + */ + public function getArea(): float + { + $area = 0; + + if ($this->getNumberOfPoints() <= 2) { + return $area; + } + + $referencePoint = $this->points[0]; + $radius = $referencePoint->getEllipsoid()->getArithmeticMeanRadius(); + $segments = $this->getSegments(); + + foreach ($segments as $segment) { + $point1 = $segment->getPoint1(); + $point2 = $segment->getPoint2(); + + $x1 = deg2rad($point1->getLng() - $referencePoint->getLng()) * cos(deg2rad($point1->getLat())); + $y1 = deg2rad($point1->getLat() - $referencePoint->getLat()); + + $x2 = deg2rad($point2->getLng() - $referencePoint->getLng()) * cos(deg2rad($point2->getLat())); + $y2 = deg2rad($point2->getLat() - $referencePoint->getLat()); + + $area += ($x2 * $y1 - $x1 * $y2); + } + + $area *= 0.5 * $radius ** 2; + + return abs($area); + } + + /** + * Create a new polygon with reversed order of points, i. e. reversed + * polygon direction. + * + * @return Polygon + */ + public function getReverse(): Polygon + { + $reversed = new self(); + + foreach (array_reverse($this->points) as $point) { + $reversed->addPoint($point); + } + + return $reversed; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Polyline.php b/admin/vendor/mjaschen/phpgeo/src/Polyline.php new file mode 100644 index 000000000..e703d95e3 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Polyline.php @@ -0,0 +1,197 @@ + + */ +class Polyline implements GeometryInterface +{ + use GetBoundsTrait; + + /** + * @var array + */ + protected $points = []; + + /** + * @param Coordinate $point + * + * @return void + */ + public function addPoint(Coordinate $point): void + { + $this->points[] = $point; + } + + /** + * @param array $points + */ + public function addPoints(array $points): void + { + foreach ($points as $point) { + $this->addPoint($point); + } + } + + /** + * Adds an unique point to the polyline. A maximum allowed distance for + * same point comparison can be provided. Default allowed distance + * deviation is 0.001 meters (1 millimeter). + * + * @param Coordinate $point + * @param float $allowedDistance + * + * @return void + */ + public function addUniquePoint(Coordinate $point, float $allowedDistance = .001): void + { + if ($this->containsPoint($point, $allowedDistance)) { + return; + } + + $this->addPoint($point); + } + + /** + * @return array + */ + public function getPoints(): array + { + return $this->points; + } + + /** + * @return int + */ + public function getNumberOfPoints(): int + { + return count($this->points); + } + + /** + * @param Coordinate $point + * @param float $allowedDistance + * + * @return bool + */ + public function containsPoint(Coordinate $point, float $allowedDistance = .001): bool + { + foreach ($this->points as $existingPoint) { + if ($existingPoint->hasSameLocation($point, $allowedDistance)) { + return true; + } + } + + return false; + } + + /** + * @param FormatterInterface $formatter + * + * @return string + */ + public function format(FormatterInterface $formatter): string + { + return $formatter->format($this); + } + + /** + * @return array + */ + public function getSegments(): array + { + $length = count($this->points); + $segments = []; + + if ($length <= 1) { + return $segments; + } + + for ($i = 1; $i < $length; $i++) { + $segments[] = new Line($this->points[$i - 1], $this->points[$i]); + } + + return $segments; + } + + /** + * Calculates the length of the polyline. + * + * @param DistanceInterface $calculator instance of distance calculation class + * + * @return float + */ + public function getLength(DistanceInterface $calculator): float + { + $distance = 0.0; + + if (count($this->points) <= 1) { + return $distance; + } + + foreach ($this->getSegments() as $segment) { + $distance += $segment->getLength($calculator); + } + + return $distance; + } + + /** + * Create a new polyline with reversed order of points, i. e. reversed + * polyline direction. + * + * @return Polyline + */ + public function getReverse(): Polyline + { + $reversed = new self(); + + foreach (array_reverse($this->points) as $point) { + $reversed->addPoint($point); + } + + return $reversed; + } + + /** + * Returns the point which is defined by the avarages of all + * latitude/longitude values. + * + * This currently only works for polylines which don't cross the dateline at + * 180/-180 degrees longitude. + * + * @return Coordinate + * + * @throws InvalidGeometryException when the polyline doesn't contain any points. + */ + public function getAveragePoint(): Coordinate + { + $latitude = 0.0; + $longitude = 0.0; + $numberOfPoints = count($this->points); + + if ($this->getNumberOfPoints() === 0) { + throw new InvalidGeometryException('Polyline doesn\'t contain points', 9464188927); + } + + foreach ($this->points as $point) { + // @var Coordinate $point + $latitude += $point->getLat(); + $longitude += $point->getLng(); + } + + $latitude /= $numberOfPoints; + $longitude /= $numberOfPoints; + + return new Coordinate($latitude, $longitude); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyBearing.php b/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyBearing.php new file mode 100644 index 000000000..4e970c8a0 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyBearing.php @@ -0,0 +1,120 @@ + + */ +class SimplifyBearing implements SimplifyInterface +{ + /** + * @var float + */ + private $bearingAngle; + + /** + * SimplifyBearing constructor. + * + * @param float $bearingAngle + */ + public function __construct(float $bearingAngle) + { + $this->bearingAngle = $bearingAngle; + } + + /** + * @param Polyline $polyline + * + * @return Polyline + * @throws RuntimeException + */ + public function simplify(Polyline $polyline): Polyline + { + $result = $this->simplifyGeometry($polyline); + + if (!($result instanceof Polyline)) { + throw new RuntimeException('Result is no Polyline', 4231694400); + } + + return $result; + } + + /** + * Simplifies the given polyline + * + * 1. calculate the bearing angle between the first two points p1 and p2: b1 + * 2. calculate the bearing angle between the next two points p2 and p3: b2 + * 3. calculate the difference between b1 and b2: deltaB; if deltaB is + * smaller than the threshold angle, remove the middle point p2 + * 4. start again at (1.) as long as the polyline contains more points + * + * This method will be merged with `simplify()` in the next major release. + * + * @param GeometryInterface $geometry + * + * @return GeometryInterface + */ + public function simplifyGeometry(GeometryInterface $geometry): GeometryInterface + { + if (!($geometry instanceof Polyline) && !($geometry instanceof Polygon)) { + return $geometry; + } + + $counterPoints = $geometry->getNumberOfPoints(); + + if ($geometry instanceof Polygon) { + if ($counterPoints <= 3) { + return clone $geometry; + } + $result = new Polygon(); + } else { + if ($counterPoints < 3) { + return clone $geometry; + } + $result = new Polyline(); + } + + $bearingCalc = new BearingEllipsoidal(); + + $points = $geometry->getPoints(); + + $index = 0; + + // add the first point to the resulting polyline + $result->addPoint($points[$index]); + + do { + $index++; + + // preserve the last point of the original polyline + if ($index === $counterPoints - 1) { + $result->addPoint($points[$index]); + break; + } + + $bearing1 = $bearingCalc->calculateBearing($points[$index - 1], $points[$index]); + $bearing2 = $bearingCalc->calculateBearing($points[$index], $points[$index + 1]); + + $bearingDifference = min( + fmod($bearing1 - $bearing2 + 360, 360), + fmod($bearing2 - $bearing1 + 360, 360) + ); + + if ($bearingDifference > $this->bearingAngle) { + $result->addPoint($points[$index]); + } + } while ($index < $counterPoints); + + return $result; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyDouglasPeucker.php b/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyDouglasPeucker.php new file mode 100644 index 000000000..40331e252 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyDouglasPeucker.php @@ -0,0 +1,135 @@ + + */ +class SimplifyDouglasPeucker implements SimplifyInterface +{ + /** + * @var float + */ + protected $tolerance; + + /** + * @param float $tolerance the perpendicular distance threshold in meters + */ + public function __construct(float $tolerance) + { + $this->tolerance = $tolerance; + } + + /** + * @param Polyline $polyline + * + * @return Polyline + * @throws RuntimeException + */ + public function simplify(Polyline $polyline): Polyline + { + $result = $this->simplifyGeometry($polyline); + + if (!($result instanceof Polyline)) { + throw new RuntimeException('Result is no Polyline', 9737647468); + } + + return $result; + } + + /** + * This method is a workaround to allow simplifying polygons too. It'll be + * merged with `simplify()` in the next major release. + * + * @param GeometryInterface $geometry + * + * @return GeometryInterface + */ + public function simplifyGeometry(GeometryInterface $geometry): GeometryInterface + { + if (!($geometry instanceof Polyline) && !($geometry instanceof Polygon)) { + return $geometry; + } + + $counterPoints = $geometry->getNumberOfPoints(); + + if ($geometry instanceof Polygon) { + if ($counterPoints <= 3) { + return clone $geometry; + } + $result = new Polygon(); + } else { + if ($counterPoints < 3) { + return clone $geometry; + } + $result = new Polyline(); + } + + $simplifiedLine = $this->douglasPeucker($geometry->getPoints()); + + $result->addPoints($simplifiedLine); + + return $result; + } + + /** + * @param array $line + * + * @return array + */ + protected function douglasPeucker(array $line): array + { + $distanceMax = 0; + $index = 0; + + $lineSize = count($line); + + $pdCalc = new PerpendicularDistance(); + + for ($i = 1; $i <= $lineSize - 2; $i++) { + $distance = $pdCalc->getPerpendicularDistance($line[$i], new Line($line[0], $line[$lineSize - 1])); + + if ($distance > $distanceMax) { + $index = $i; + $distanceMax = $distance; + } + } + + if ($distanceMax > $this->tolerance) { + $lineSplitFirst = array_slice($line, 0, $index + 1); + $lineSplitSecond = array_slice($line, $index, $lineSize - $index); + + $resultsSplit1 = count($lineSplitFirst) > 2 + ? $this->douglasPeucker($lineSplitFirst) + : $lineSplitFirst; + + $resultsSplit2 = count($lineSplitSecond) > 2 + ? $this->douglasPeucker($lineSplitSecond) + : $lineSplitSecond; + + array_pop($resultsSplit1); + + return array_merge($resultsSplit1, $resultsSplit2); + } + + return [$line[0], $line[$lineSize - 1]]; + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyInterface.php b/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyInterface.php new file mode 100644 index 000000000..6c3a1fb3e --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Processor/Polyline/SimplifyInterface.php @@ -0,0 +1,24 @@ + + */ +interface SimplifyInterface +{ + /** + * Simplifies the given polyline + * + * @param Polyline $polyline + * + * @return Polyline + */ + public function simplify(Polyline $polyline): Polyline; +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Utility/Cartesian.php b/admin/vendor/mjaschen/phpgeo/src/Utility/Cartesian.php new file mode 100644 index 000000000..9ab2dcb12 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Utility/Cartesian.php @@ -0,0 +1,73 @@ +x = $x; + $this->y = $y; + $this->z = $z; + } + + /** + * @return float + */ + public function getX(): float + { + return $this->x; + } + + /** + * @return float + */ + public function getY(): float + { + return $this->y; + } + + /** + * @return float + */ + public function getZ(): float + { + return $this->z; + } + + /** + * @param Cartesian $other + * + * @return Cartesian + */ + public function add(Cartesian $other): Cartesian + { + return new self( + $this->x + $other->x, + $this->y + $other->y, + $this->z + $other->z + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Utility/PerpendicularDistance.php b/admin/vendor/mjaschen/phpgeo/src/Utility/PerpendicularDistance.php new file mode 100644 index 000000000..735553b32 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Utility/PerpendicularDistance.php @@ -0,0 +1,82 @@ + + */ +class PerpendicularDistance +{ + public function getPerpendicularDistance(Coordinate $point, Line $line): float + { + $ellipsoid = $point->getEllipsoid(); + + $ellipsoidRadius = $ellipsoid->getArithmeticMeanRadius(); + + $firstLinePointLat = $this->deg2radLatitude($line->getPoint1()->getLat()); + $firstLinePointLng = $this->deg2radLongitude($line->getPoint1()->getLng()); + + $firstLinePointX = $ellipsoidRadius * cos($firstLinePointLng) * sin($firstLinePointLat); + $firstLinePointY = $ellipsoidRadius * sin($firstLinePointLng) * sin($firstLinePointLat); + $firstLinePointZ = $ellipsoidRadius * cos($firstLinePointLat); + + $secondLinePointLat = $this->deg2radLatitude($line->getPoint2()->getLat()); + $secondLinePointLng = $this->deg2radLongitude($line->getPoint2()->getLng()); + + $secondLinePointX = $ellipsoidRadius * cos($secondLinePointLng) * sin($secondLinePointLat); + $secondLinePointY = $ellipsoidRadius * sin($secondLinePointLng) * sin($secondLinePointLat); + $secondLinePointZ = $ellipsoidRadius * cos($secondLinePointLat); + + $pointLat = $this->deg2radLatitude($point->getLat()); + $pointLng = $this->deg2radLongitude($point->getLng()); + + $pointX = $ellipsoidRadius * cos($pointLng) * sin($pointLat); + $pointY = $ellipsoidRadius * sin($pointLng) * sin($pointLat); + $pointZ = $ellipsoidRadius * cos($pointLat); + + $normalizedX = $firstLinePointY * $secondLinePointZ - $firstLinePointZ * $secondLinePointY; + $normalizedY = $firstLinePointZ * $secondLinePointX - $firstLinePointX * $secondLinePointZ; + $normalizedZ = $firstLinePointX * $secondLinePointY - $firstLinePointY * $secondLinePointX; + + $length = sqrt($normalizedX * $normalizedX + $normalizedY * $normalizedY + $normalizedZ * $normalizedZ); + + if ($length == 0.0) { + return 0; + } + + $normalizedX /= $length; + $normalizedY /= $length; + $normalizedZ /= $length; + + $thetaPoint = $normalizedX * $pointX + $normalizedY * $pointY + $normalizedZ * $pointZ; + + $length = sqrt($pointX * $pointX + $pointY * $pointY + $pointZ * $pointZ); + + $thetaPoint /= $length; + + $distance = abs((M_PI / 2) - acos($thetaPoint)); + + return $distance * $ellipsoidRadius; + } + + protected function deg2radLatitude(float $latitude): float + { + return deg2rad(90 - $latitude); + } + + protected function deg2radLongitude(float $longitude): float + { + if ($longitude > 0) { + return deg2rad($longitude); + } + + return deg2rad($longitude + 360); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/src/Utility/PointToLineDistance.php b/admin/vendor/mjaschen/phpgeo/src/Utility/PointToLineDistance.php new file mode 100644 index 000000000..77746a040 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/src/Utility/PointToLineDistance.php @@ -0,0 +1,88 @@ + + */ +class PointToLineDistance +{ + /** + * @var DistanceInterface + */ + private $distanceCalculator; + + /** + * @var float + */ + private $epsilon; + + public function __construct(DistanceInterface $distanceCalculator, float $epsilon = 0.001) + { + $this->distanceCalculator = $distanceCalculator; + $this->epsilon = $epsilon; + } + + /** + * @psalm-suppress InvalidReturnType + * @throws NotConvergingException + */ + public function getDistance(Coordinate $point, Line $line): float + { + if ($line->getPoint1()->hasSameLocation($line->getPoint2(), $this->epsilon)) { + return $this->distanceCalculator->getDistance($point, $line->getPoint1()); + } + if ($point->hasSameLocation($line->getPoint1(), $this->epsilon)) { + return 0.0; + } + if ($point->hasSameLocation($line->getPoint2(), $this->epsilon)) { + return 0.0; + } + if ($point->hasSameLocation($line->getMidpoint(), $this->epsilon)) { + return 0.0; + } + + $iterationsCounter = 0; + $iterationLine = clone $line; + + do { + $linePoint1 = $iterationLine->getPoint1(); + $linePoint2 = $iterationLine->getPoint2(); + $lineMidPoint = $iterationLine->getMidpoint(); + + $distancePointToLinePoint1 = $point->getDistance($linePoint1, $this->distanceCalculator); + $distancePointToLinePoint2 = $point->getDistance($linePoint2, $this->distanceCalculator); + + if ($distancePointToLinePoint1 <= $distancePointToLinePoint2) { + $iterationLine = new Line($linePoint1, $lineMidPoint); + } else { + $iterationLine = new Line($lineMidPoint, $linePoint2); + } + + if (abs($distancePointToLinePoint1 - $distancePointToLinePoint2) < $this->epsilon) { + return $point->getDistance($iterationLine->getMidpoint(), $this->distanceCalculator); + } + + $iterationsCounter++; + if ($iterationsCounter > 100) { + throw new NotConvergingException( + 'Calculation of Point to Minor Arc did not converge after 100 iterations.', + 6391878367 + ); + } + } while (true); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Bearing/BearingEllipsoidalTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Bearing/BearingEllipsoidalTest.php new file mode 100644 index 000000000..e00ae4109 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Bearing/BearingEllipsoidalTest.php @@ -0,0 +1,212 @@ +assertEquals(0.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingSouthernWorksAsExpected(): void + { + $point1 = new Coordinate(10, 0); + $point2 = new Coordinate(0, 0); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(180.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(90.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, - 10); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(270.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingNorthEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0.1, 0.1); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEqualsWithDelta(45.0, $bearingCalculator->calculateBearing($point1, $point2), 0.2, ''); + } + + public function testIfCalculateBearingNorthWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0.1, -0.1); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEqualsWithDelta(315.0, $bearingCalculator->calculateBearing($point1, $point2), 0.2, ''); + } + + public function testIfCalculateBearingSouthEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(- 0.1, 0.1); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEqualsWithDelta(135.0, $bearingCalculator->calculateBearing($point1, $point2), 0.2, ''); + } + + public function testIfCalculateBearingSouthWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(- 0.1, - 0.1); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEqualsWithDelta(225.0, $bearingCalculator->calculateBearing($point1, $point2), 0.2, ''); + } + + public function testIfCalculateFinalBearingNorthernWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(10, 0); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(0.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateFinalBearingSouthernWorksAsExpected(): void + { + $point1 = new Coordinate(10, 0); + $point2 = new Coordinate(0, 0); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(180.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateFinalBearingEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(90.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateFinalBearingWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, - 10); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(270.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateDestinationEasternWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 90, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + // so we expect a latitude of 0 degrees and a longitude + // of 1 degree: + + $this->assertEqualsWithDelta(0.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(1.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationWesternWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 270, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(0.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(-1.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationNorthernWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 0, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(1.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(0.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationNorthern360WorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 360, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(1.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(0.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationSouthernWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 180, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(-1.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(0.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfBearingForTheSamePointIsZero(): void + { + $bearingCalculator = new BearingEllipsoidal(); + $point1 = new Coordinate(50.12345, 10.23456); + $point2 = new Coordinate(50.12345, 10.23456); + + $this->assertEquals(0.0, $bearingCalculator->calculateBearing($point1, $point2)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Bearing/BearingSphericalTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Bearing/BearingSphericalTest.php new file mode 100644 index 000000000..e27c77dc8 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Bearing/BearingSphericalTest.php @@ -0,0 +1,203 @@ +assertEquals(0.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingSouthernWorksAsExpected(): void + { + $point1 = new Coordinate(10, 0); + $point2 = new Coordinate(0, 0); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(180.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(90.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, - 10); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(270.0, $bearingCalculator->calculateBearing($point1, $point2)); + } + + public function testIfCalculateBearingNorthEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0.1, 0.1); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEqualsWithDelta(45.0, $bearingCalculator->calculateBearing($point1, $point2), 0.1, ''); + } + + public function testIfCalculateBearingNorthWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0.1, - 0.1); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEqualsWithDelta(315.0, $bearingCalculator->calculateBearing($point1, $point2), 0.1, ''); + } + + public function testIfCalculateBearingSouthEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(- 0.1, 0.1); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEqualsWithDelta(135.0, $bearingCalculator->calculateBearing($point1, $point2), 0.1, ''); + } + + public function testIfCalculateBearingSouthWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(- 0.1, - 0.1); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEqualsWithDelta(225.0, $bearingCalculator->calculateBearing($point1, $point2), 0.1, ''); + } + + public function testIfCalculateFinalBearingNorthernWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(10, 0); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(0.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateFinalBearingSouthernWorksAsExpected(): void + { + $point1 = new Coordinate(10, 0); + $point2 = new Coordinate(0, 0); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(180.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateFinalBearingEasternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(90.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateFinalBearingWesternWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, - 10); + + $bearingCalculator = new BearingSpherical(); + + $this->assertEquals(270.0, $bearingCalculator->calculateFinalBearing($point1, $point2)); + } + + public function testIfCalculateDestinationEasternWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 90, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + // so we expect a latitude of 0 degrees and a longitude + // of 1 degree: + + $this->assertEqualsWithDelta(0.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(1.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationWesternWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 270, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(0.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(-1.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationNorthernWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 0, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(1.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(0.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationNorthern360WorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 360, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(1.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(0.0, $destination->getLng(), 0.0001, ''); + } + + public function testIfCalculateDestinationSouthernWorksAsExpected(): void + { + $bearingCalculator = new BearingSpherical(); + + $point = new Coordinate(0, 0); + $destination = $bearingCalculator->calculateDestination($point, 180, 111195.0837); + + // 1 degree in longitude at the equator: + // 2πr/360 = 40030230.1407 meters/360 = 111195.0837 meters + + $this->assertEqualsWithDelta(-1.0, $destination->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta(0.0, $destination->getLng(), 0.0001, ''); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/BoundsTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/BoundsTest.php new file mode 100644 index 000000000..3758c0f7e --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/BoundsTest.php @@ -0,0 +1,88 @@ +object = new Bounds( + new Coordinate(50, 10), + new Coordinate(30, 30) + ); + } + + protected function tearDown(): void + { + unset($this->object); + } + + public function testGetNortWest(): void + { + $c = new Coordinate(50, 10); + + $this->assertEquals($c, $this->object->getNorthWest()); + } + + public function testGetSouthEast(): void + { + $c = new Coordinate(30, 30); + + $this->assertEquals($c, $this->object->getSouthEast()); + } + + public function testGetNorth(): void + { + $this->assertEquals(50, $this->object->getNorth()); + } + + public function testGetSouth(): void + { + $this->assertEquals(30, $this->object->getSouth()); + } + + public function testGetWest(): void + { + $this->assertEquals(10, $this->object->getWest()); + } + + public function testGetEast(): void + { + $this->assertEquals(30, $this->object->getEast()); + } + + public function testGetCenter(): void + { + $testBounds = [ + ['nw' => new Coordinate(50, 10), 'se' => new Coordinate(30, 30), 'c' => new Coordinate(40, 20)], + ['nw' => new Coordinate(50, - 130), 'se' => new Coordinate(30, - 110), 'c' => new Coordinate(40, - 120)], + ['nw' => new Coordinate(10, - 10), 'se' => new Coordinate(- 10, 10), 'c' => new Coordinate(0, 0)], + [ + 'nw' => new Coordinate(- 80, - 130), + 'se' => new Coordinate(- 90, - 110), + 'c' => new Coordinate(- 85, - 120) + ], + ['nw' => new Coordinate(80, - 130), 'se' => new Coordinate(90, - 110), 'c' => new Coordinate(85, - 120)], + ['nw' => new Coordinate(80, 110), 'se' => new Coordinate(90, 130), 'c' => new Coordinate(85, 120)], + ['nw' => new Coordinate(50, 170), 'se' => new Coordinate(30, - 160), 'c' => new Coordinate(40, - 175)], + ['nw' => new Coordinate(- 50, 150), 'se' => new Coordinate(- 70, - 170), 'c' => new Coordinate(- 60, 170)], + ]; + + foreach ($testBounds as $bounds) { + $b = new Bounds($bounds['nw'], $bounds['se']); + + $this->assertEquals($bounds['c'], $b->getCenter()); + } + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionDistancesCalculatorTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionDistancesCalculatorTest.php new file mode 100644 index 000000000..0b8f7b7e9 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionDistancesCalculatorTest.php @@ -0,0 +1,120 @@ +assertEquals( + $expected, + $cardinalDirectionDistancesCalculator->getCardinalDirectionDistances($point1, $point2, new Vincenty()) + ); + } + + public function getCardinalDirectionDistancesProvider(): Generator + { + $point2 = new Coordinate(51, 13); + + $directDistanceWestEast = 70197.14; + + yield 'point1 equals point2' => [ + 'point1' => $point2, + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create(), + ]; + yield 'point1 north from point2' => [ + 'point1' => $this->moveToNorth($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setSouth(111257.827), + ]; + yield 'point1 east from point2' => [ + 'point1' => $this->moveToEast($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setWest($directDistanceWestEast), + ]; + yield 'point1 south from point2' => [ + 'point1' => $this->moveToSouth($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setNorth(111238.681), + ]; + yield 'point1 west from point2' => [ + 'point1' => $this->moveToWest($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setEast($directDistanceWestEast), + ]; + yield 'point1 north west from point2' => [ + 'point1' => $this->moveToNorthWest($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setEast(68677.475)->setSouth(111257.827), + ]; + yield 'point1 north east from point2' => [ + 'point1' => $this->moveToNorthEast($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setSouth(111257.827)->setWest(68677.475), + ]; + yield 'point1 south east from point2' => [ + 'point1' => $this->moveToSouthEast($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setNorth(111238.681)->setWest(71695.22), + ]; + yield 'point1 south west from point2' => [ + 'point1' => $this->moveToSouthWest($point2), + 'point2' => $point2, + 'expected' => CardinalDirectionDistances::create()->setNorth(111238.681)->setEast(71695.22), + ]; + } + + private function moveToNorth(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat() + 1, $coordinate->getLng()); + } + + private function moveToEast(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat(), $coordinate->getLng() + 1); + } + + private function moveToSouth(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat() - 1, $coordinate->getLng()); + } + + private function moveToWest(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat(), $coordinate->getLng() - 1); + } + + private function moveToNorthEast(Coordinate $coordinate): Coordinate + { + return self::moveToNorth(self::moveToEast($coordinate)); + } + + private function moveToSouthEast(Coordinate $coordinate): Coordinate + { + return self::moveToSouth(self::moveToEast($coordinate)); + } + + private function moveToSouthWest(Coordinate $coordinate): Coordinate + { + return self::moveToSouth(self::moveToWest($coordinate)); + } + + private function moveToNorthWest(Coordinate $coordinate): Coordinate + { + return self::moveToNorth(self::moveToWest($coordinate)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionDistancesTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionDistancesTest.php new file mode 100644 index 000000000..9fa180882 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionDistancesTest.php @@ -0,0 +1,77 @@ +assertSame($north, CardinalDirectionDistances::create()->setNorth($north)->getNorth()); + } + + public function testSetNorthThrows(): void + { + $this->expectException(InvalidDistanceException::class); + CardinalDirectionDistances::create()->setNorth(-1); + } + + public function testSetEast(): void + { + $east = 2500.0; + $this->assertSame($east, CardinalDirectionDistances::create()->setEast($east)->getEast()); + } + + public function testSetEastThrows(): void + { + $this->expectException(InvalidDistanceException::class); + CardinalDirectionDistances::create()->setEast(-1); + } + + public function testSetSouth(): void + { + $south = 2500.0; + $this->assertSame($south, CardinalDirectionDistances::create()->setSouth($south)->getSouth()); + } + + public function testSetSouthThrows(): void + { + $this->expectException(InvalidDistanceException::class); + CardinalDirectionDistances::create()->setSouth(-1); + } + + public function testSetWest(): void + { + $west = 2500.0; + $this->assertSame($west, CardinalDirectionDistances::create()->setWest($west)->getWest()); + } + + public function testSetWestThrows(): void + { + $this->expectException(InvalidDistanceException::class); + CardinalDirectionDistances::create()->setWest(-1); + } + + public function testSetMultiple(): void + { + $north = 500.0; + $east = 1000.0; + $south = 1500.0; + $west = 2000.0; + $cardinalDirectionDistances = CardinalDirectionDistances::create() + ->setNorth($north) + ->setEast($east) + ->setSouth($south) + ->setWest($west); + + $this->assertSame($north, $cardinalDirectionDistances->getNorth()); + $this->assertSame($east, $cardinalDirectionDistances->getEast()); + $this->assertSame($south, $cardinalDirectionDistances->getSouth()); + $this->assertSame($west, $cardinalDirectionDistances->getWest()); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionTest.php new file mode 100644 index 000000000..dfe83c2ea --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/CardinalDirection/CardinalDirectionTest.php @@ -0,0 +1,111 @@ +assertSame( + $expected, + (new CardinalDirection())->getCardinalDirection($point1, $point2) + ); + } + + public function getCardinalDirectionProvider(): Generator + { + $point2 = new Coordinate(51, 13); + yield 'point1 equals point2' => [ + 'point1' => $point2, + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_NONE, + ]; + yield 'point1 north from point2' => [ + 'point1' => $this->moveToNorth($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_NORTH, + ]; + yield 'point1 east from point2' => [ + 'point1' => $this->moveToEast($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_EAST, + ]; + yield 'point1 south from point2' => [ + 'point1' => $this->moveToSouth($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_SOUTH, + ]; + yield 'point1 west from point2' => [ + 'point1' => $this->moveToWest($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_WEST, + ]; + yield 'point1 north west from point2' => [ + 'point1' => $this->moveToNorthWest($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_NORTHWEST, + ]; + yield 'point1 north east from point2' => [ + 'point1' => $this->moveToNorthEast($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_NORTHEAST, + ]; + yield 'point1 south east from point2' => [ + 'point1' => $this->moveToSouthEast($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_SOUTHEAST, + ]; + yield 'point1 south west from point2' => [ + 'point1' => $this->moveToSouthWest($point2), + 'point2' => $point2, + 'expected' => CardinalDirection::CARDINAL_DIRECTION_SOUTHWEST, + ]; + } + + private function moveToNorth(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat() + 1, $coordinate->getLng()); + } + + private function moveToEast(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat(), $coordinate->getLng() + 1); + } + + private function moveToSouth(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat() - 1, $coordinate->getLng()); + } + + private function moveToWest(Coordinate $coordinate): Coordinate + { + return new Coordinate($coordinate->getLat(), $coordinate->getLng() - 1); + } + + private function moveToNorthEast(Coordinate $coordinate): Coordinate + { + return self::moveToNorth(self::moveToEast($coordinate)); + } + + private function moveToSouthEast(Coordinate $coordinate): Coordinate + { + return self::moveToSouth(self::moveToEast($coordinate)); + } + + private function moveToSouthWest(Coordinate $coordinate): Coordinate + { + return self::moveToSouth(self::moveToWest($coordinate)); + } + + private function moveToNorthWest(Coordinate $coordinate): Coordinate + { + return self::moveToNorth(self::moveToWest($coordinate)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/CoordinateTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/CoordinateTest.php new file mode 100644 index 000000000..0421df9f3 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/CoordinateTest.php @@ -0,0 +1,134 @@ + 'WGS-84', + 'a' => 6378137.0, + 'f' => 298.257223563, + ]; + + $this->ellipsoid = Ellipsoid::createFromArray($ellipsoidConfig); + + $this->coordinate = new Coordinate(52.5, 13.5, $this->ellipsoid); + } + + public function testConstructorInvalidLatitudeOutOfBoundsWorksAsExpected(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Latitude value must be numeric -90.0 .. +90.0 (given: 91)'); + + $c = new Coordinate(91.0, 13.5, $this->ellipsoid); + } + + public function testConstructorInvalidLongitudeOutOfBoundsWorksAsExpected(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Longitude value must be numeric -180.0 .. +180.0 (given: 190)'); + + $c = new Coordinate(52.2, 190.0, $this->ellipsoid); + } + + public function testConstructorBoundChecksWorkAsExpected(): void + { + $c = new Coordinate(90.0, 180.0, $this->ellipsoid); + + $this->assertEquals(90.0, $c->getLat()); + $this->assertEquals(180.0, $c->getLng()); + + $c = new Coordinate(-90.0, -180.0, $this->ellipsoid); + + $this->assertEquals(-90.0, $c->getLat()); + $this->assertEquals(-180.0, $c->getLng()); + + $c = new Coordinate(-90, 180, $this->ellipsoid); + + $this->assertEquals(-90.0, $c->getLat()); + $this->assertEquals(180.0, $c->getLng()); + + $c = new Coordinate(90, -180, $this->ellipsoid); + + $this->assertEquals(90.0, $c->getLat()); + $this->assertEquals(-180.0, $c->getLng()); + } + + public function testConstructorDefaultEllipsoid(): void + { + $c = new Coordinate(52.5, 13.5); + + $this->assertInstanceOf(Ellipsoid::class, $c->getEllipsoid()); + } + + public function testGetLat(): void + { + $this->assertEquals(52.5, $this->coordinate->getLat()); + } + + public function testGetLng(): void + { + $this->assertEquals(13.5, $this->coordinate->getLng()); + } + + public function testGetEllipsoid(): void + { + $this->assertEquals($this->ellipsoid, $this->coordinate->getEllipsoid()); + } + + public function testGetdistance(): void + { + $coordinate1 = new Coordinate(19.820664, -155.468066, $this->ellipsoid); + $coordinate2 = new Coordinate(20.709722, -156.253333, $this->ellipsoid); + + $this->assertEquals(128130.850, $coordinate1->getDistance($coordinate2, new Vincenty())); + } + + public function testFormat(): void + { + $this->assertEquals('52.50000 13.50000', $this->coordinate->format(new DecimalDegrees())); + } + + public function testHasSameLocation(): void + { + $point1 = new Coordinate(0.0, 0.0); + $point2 = new Coordinate(0.0, 0.0); + + $this->assertTrue($point1->hasSameLocation($point1, 0.0)); + $this->assertTrue($point1->hasSameLocation($point1, 0.1)); + + $this->assertTrue($point1->hasSameLocation($point2, 0.0)); + $this->assertTrue($point1->hasSameLocation($point2, 0.1)); + + $this->assertTrue($point2->hasSameLocation($point1, 0.0)); + $this->assertTrue($point2->hasSameLocation($point1, 0.1)); + + // distance: 1 arc second + $point2 = new Coordinate(0, 0.0002777778); + + $this->assertFalse($point1->hasSameLocation($point2, 0.0)); + + // a longitude difference of 1 arc second is about ~30.9 meters on the equator line + $this->assertFalse($point1->hasSameLocation($point2, 30.85)); + $this->assertTrue($point1->hasSameLocation($point2, 30.95)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Direction/DirectionTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Direction/DirectionTest.php new file mode 100644 index 000000000..d9651c46a --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Direction/DirectionTest.php @@ -0,0 +1,41 @@ +assertTrue((new Direction())->pointIsNorthOf(new Coordinate(50, 13), new Coordinate(40, 10))); + $this->assertTrue((new Direction())->pointIsNorthOf(new Coordinate(-50, 13), new Coordinate(-60, 10))); + $this->assertTrue((new Direction())->pointIsNorthOf(new Coordinate(10, 13), new Coordinate(-40, 10))); + } + + public function testIsSouthOf(): void + { + $this->assertTrue((new Direction())->pointIsSouthOf(new Coordinate(40, 10), new Coordinate(50, 13))); + $this->assertTrue((new Direction())->pointIsSouthOf(new Coordinate(-60, 10), new Coordinate(-50, 13))); + $this->assertTrue((new Direction())->pointIsSouthOf(new Coordinate(-40, 10), new Coordinate(10, 13))); + } + + public function testIsWestOf(): void + { + $this->assertTrue((new Direction())->pointIsWestOf(new Coordinate(40, 10), new Coordinate(50, 13))); + $this->assertTrue((new Direction())->pointIsWestOf(new Coordinate(-60, -10), new Coordinate(-50, -3))); + $this->assertTrue((new Direction())->pointIsWestOf(new Coordinate(-40, -100), new Coordinate(10, 130))); + $this->assertTrue((new Direction())->pointIsWestOf(new Coordinate(-40, -179), new Coordinate(10, 179))); + } + + public function testIsEastOf(): void + { + $this->assertTrue((new Direction())->pointIsEastOf(new Coordinate(50, 13), new Coordinate(40, 10))); + $this->assertTrue((new Direction())->pointIsEastOf(new Coordinate(-50, -3), new Coordinate(-60, -10))); + $this->assertTrue((new Direction())->pointIsEastOf(new Coordinate(10, 130), new Coordinate(-40, -100))); + $this->assertTrue((new Direction())->pointIsEastOf(new Coordinate(10, 179), new Coordinate(-40, -179))); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Distance/HaversineTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Distance/HaversineTest.php new file mode 100644 index 000000000..e19500192 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Distance/HaversineTest.php @@ -0,0 +1,89 @@ + 'WGS-84', + 'a' => 6378137.0, + 'f' => 298.257223563, + ]; + + $this->ellipsoid = Ellipsoid::createFromArray($ellipsoidConfig); + + $this->calculator = new Haversine(); + } + + public function testGetDistanceZero(): void + { + $coordinate1 = new Coordinate(52.5, 13.5, $this->ellipsoid); + $coordinate2 = new Coordinate(52.5, 13.5, $this->ellipsoid); + + $distance = $this->calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(0.0, $distance); + } + + public function testGetDistanceSameLatitude(): void + { + $coordinate1 = new Coordinate(52.5, 13.5, $this->ellipsoid); + $coordinate2 = new Coordinate(52.5, 13.1, $this->ellipsoid); + + $distance = $this->calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(27076.476, $distance); + } + + public function testGetDistanceSameLongitude(): void + { + $coordinate1 = new Coordinate(52.5, 13.5, $this->ellipsoid); + $coordinate2 = new Coordinate(52.1, 13.5, $this->ellipsoid); + + $distance = $this->calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(44478.032, $distance); + } + + public function testGetDistance(): void + { + $coordinate1 = new Coordinate(19.820664, - 155.468066, $this->ellipsoid); + $coordinate2 = new Coordinate(20.709722, - 156.253333, $this->ellipsoid); + + $distance = $this->calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(128384.515, $distance); + } + + public function testGetDistanceInternationalDateLine(): void + { + $coordinate1 = new Coordinate(20.0, 170.0, $this->ellipsoid); + $coordinate2 = new Coordinate(- 20.0, - 170.0, $this->ellipsoid); + + $distance = $this->calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(4952349.639, $distance); + } + + public function testNotMatchingEllipsoids(): void + { + $this->expectException(NotMatchingEllipsoidException::class); + + $coordinate1 = new Coordinate(19.820664, - 155.468066, $this->ellipsoid); + $coordinate2 = new Coordinate(20.709722, - 156.253333, new Ellipsoid('AnotherEllipsoid', 6378140.0, 299.2)); + + $this->calculator->getDistance($coordinate1, $coordinate2); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Distance/VincentyTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Distance/VincentyTest.php new file mode 100644 index 000000000..8d6a6dd39 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Distance/VincentyTest.php @@ -0,0 +1,92 @@ + 'WGS-84', + 'a' => 6378137.0, + 'f' => 298.257223563, + ]; + + $this->ellipsoid = Ellipsoid::createFromArray($ellipsoidConfig); + } + + public function testGetDistanceZero(): void + { + $coordinate1 = new Coordinate(52.5, 13.5, $this->ellipsoid); + $coordinate2 = new Coordinate(52.5, 13.5, $this->ellipsoid); + + $calculator = new Vincenty(); + $distance = $calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(0.0, $distance); + } + + public function testGetDistanceSameLatitude(): void + { + $coordinate1 = new Coordinate(52.5, 13.5, $this->ellipsoid); + $coordinate2 = new Coordinate(52.5, 13.1, $this->ellipsoid); + + $calculator = new Vincenty(); + $distance = $calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(27164.059, $distance); + } + + public function testGetDistanceSameLongitude(): void + { + $coordinate1 = new Coordinate(52.5, 13.5, $this->ellipsoid); + $coordinate2 = new Coordinate(52.1, 13.5, $this->ellipsoid); + + $calculator = new Vincenty(); + $distance = $calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(44509.218, $distance); + } + + public function testGetDistance(): void + { + $coordinate1 = new Coordinate(19.820664, - 155.468066, $this->ellipsoid); + $coordinate2 = new Coordinate(20.709722, - 156.253333, $this->ellipsoid); + + $calculator = new Vincenty(); + $distance = $calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(128130.850, $distance); + } + + public function testGetDistanceInternationalDateLine(): void + { + $coordinate1 = new Coordinate(20.0, 170.0, $this->ellipsoid); + $coordinate2 = new Coordinate(- 20.0, - 170.0, $this->ellipsoid); + + $calculator = new Vincenty(); + $distance = $calculator->getDistance($coordinate1, $coordinate2); + + $this->assertEquals(4932842.135, $distance); + } + + public function testNotMatchingEllispoids(): void + { + $this->expectException(NotMatchingEllipsoidException::class); + + $coordinate1 = new Coordinate(19.820664, - 155.468066, $this->ellipsoid); + $coordinate2 = new Coordinate(20.709722, - 156.253333, new Ellipsoid('AnotherEllipsoid', 6378140.0, 299.2)); + + $calculator = new Vincenty(); + $distance = $calculator->getDistance($coordinate1, $coordinate2); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Factory/BoundsFactoryTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Factory/BoundsFactoryTest.php new file mode 100644 index 000000000..eed7041ed --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Factory/BoundsFactoryTest.php @@ -0,0 +1,95 @@ +assertEquals( + new Bounds( + new Coordinate(52.00063591099075, 12.998967101997957), + new Coordinate(51.999364079975535, 13.001032898002041) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, 100, new BearingSpherical()) + ); + $this->assertEquals( + new Bounds( + new Coordinate(52.00063549793861, 12.998970388437384), + new Coordinate(51.99936449299343, 13.001029582403508) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, 100, new BearingEllipsoidal()) + ); + + $startCenter = new Coordinate(-52, -13); + $this->assertEquals( + new Bounds( + new Coordinate(-51.999364079975535, -13.001032898002041), + new Coordinate(-52.00063591099075, -12.998967101997957) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, 100, new BearingSpherical()) + ); + $this->assertEquals( + new Bounds( + new Coordinate(-51.99936449299343, -13.001029582403508), + new Coordinate(-52.00063549793861, -12.998970388437384) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, 100, new BearingEllipsoidal()) + ); + } + + public function testIfExpandFromCenterCoordinateWorksWithNegativeDistance() + { + $startCenter = new Coordinate(52, 13); + $this->assertEquals( + new Bounds( + new Coordinate(51.999364079975535, 13.001032898002041), + new Coordinate(52.00063591099075, 12.998967101997957) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, -100, new BearingSpherical()) + ); + $this->assertEquals( + new Bounds( + new Coordinate(51.99936449299343, 13.001029582403508), + new Coordinate(52.00063549793861, 12.998970388437384) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, -100, new BearingEllipsoidal()) + ); + } + + public function testIfExpandFromCenterCoordinateThrowsExceptionOn180meridianWithBearingSpherical() + { + $this->expectException(InvalidArgumentException::class); + + $startCenter = new Coordinate(52, 179.999); + $this->assertEquals( + new Bounds( + new Coordinate(52.00063591099075, 12.998967101997957), + new Coordinate(51.999364079975535, 13.001032898002041) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, 1000, new BearingSpherical()) + ); + } + + public function testIfExpandFromCenterCoordinateWorksOn180meridianWithBearingEllipsoidal() + { + $startCenter = new Coordinate(52, 179.999); + $this->assertEquals( + new Bounds( + new Coordinate(52.00635457125255, 179.98870257203671), + new Coordinate(51.993644521951445, -179.99070548794623) + ), + BoundsFactory::expandFromCenterCoordinate($startCenter, 1000, new BearingEllipsoidal()) + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Factory/CoordinateFactoryTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Factory/CoordinateFactoryTest.php new file mode 100644 index 000000000..c26db7cc1 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Factory/CoordinateFactoryTest.php @@ -0,0 +1,411 @@ +assertEquals(new Coordinate(52, 13), CoordinateFactory::fromString('52, 13')); + $this->assertEquals(new Coordinate(52, 13), CoordinateFactory::fromString('52 13')); + $this->assertEquals(new Coordinate(52, 13), CoordinateFactory::fromString('52 013')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5, 13.5')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5 13.5')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5°, 13.5°')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5° 13.5°')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5° 013.5°')); + $this->assertEquals(new Coordinate(-52.5, 13.5), CoordinateFactory::fromString('-52.5, 13.5')); + $this->assertEquals(new Coordinate(-52.5, 13.5), CoordinateFactory::fromString('-52.5 13.5')); + $this->assertEquals(new Coordinate(-52.5, 13.5), CoordinateFactory::fromString('-52.5 013.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('-52.5, -13.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('-52.5 -13.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('-52.5 -013.5')); + $this->assertEquals(new Coordinate(52.5, -13.5), CoordinateFactory::fromString('52.5, -13.5')); + $this->assertEquals(new Coordinate(52.5, -13.5), CoordinateFactory::fromString('52.5 -13.5')); + } + + public function testIfFromStringForDecimalDegreesWithCardinalLettersWorksAsExpected(): void + { + $this->assertEquals(new Coordinate(52, 13), CoordinateFactory::fromString('N52, E13')); + $this->assertEquals(new Coordinate(52, 13), CoordinateFactory::fromString('N52 E13')); + $this->assertEquals(new Coordinate(52, 13), CoordinateFactory::fromString('N52 E013')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('N52.5, E13.5')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('N52.5 E13.5')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('N52.5°, E13.5°')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('N52.5° E13.5°')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('N52.5° E013.5°')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5N, 13.5E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5N 13.5E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5N 013.5E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5°N, 13.5°E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5°N 13.5°E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5°N 013.5°E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5° N, 13.5° E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5° N 13.5° E')); + $this->assertEquals(new Coordinate(52.5, 13.5), CoordinateFactory::fromString('52.5° N 013.5° E')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('S52.5, W13.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('S52.5 W13.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('52.5S, 13.5W')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('52.5S 13.5W')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('52.5S 013.5W')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('S 52.5, W 13.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('S 52.5 W 13.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('S 52.5 W 013.5')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('52.5 S, 13.5 W')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('52.5 S 13.5 W')); + $this->assertEquals(new Coordinate(-52.5, -13.5), CoordinateFactory::fromString('52.5 S 013.5 W')); + } + + public function testIfFromStringWithDecimalMinutesWorksAsExpected(): void + { + $expected = new Coordinate(52.20575, 13.576116667); + $expectedLat = $expected->getLat(); + $expectedLng = $expected->getLng(); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52 12.345, 13 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52 12.345, 13 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + -$expectedLat, + CoordinateFactory::fromString('-52 12.345, 13 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('-52 12.345, 13 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + -$expectedLat, + CoordinateFactory::fromString('-52 12.345, -13 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + -$expectedLng, + CoordinateFactory::fromString('-52 12.345, -13 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52 12.345, -13 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + -$expectedLng, + CoordinateFactory::fromString('52 12.345, -13 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52° 12.345, 13° 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52° 12.345, 13° 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + -$expectedLat, + CoordinateFactory::fromString('-52° 12.345, 13° 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('-52° 12.345, 13° 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + -$expectedLat, + CoordinateFactory::fromString('-52° 12.345, -13° 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + -$expectedLng, + CoordinateFactory::fromString('-52° 12.345, -13° 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52° 12.345, -13° 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + -$expectedLng, + CoordinateFactory::fromString('52° 12.345, -13° 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('N52 12.345, E13 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('N52 12.345, E13 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('N 52 12.345, E 13 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('N 52 12.345, E 13 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52 12.345N, E13 34.567E')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52 12.345N, E13 34.567E')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52 12.345 N, E13 34.567 E')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52 12.345 N, E13 34.567 E')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('N52° 12.345, E13° 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('N52° 12.345, E13° 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('N 52° 12.345, E 13° 34.567')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('N 52° 12.345, E 13° 34.567')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52° 12.345N, E13° 34.567E')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52° 12.345N, E13° 34.567E')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52° 12.345 N, E13° 34.567 E')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52° 12.345 N, E13° 34.567 E')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString("N52° 12.345', E13° 34.567'")->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString("N52° 12.345', E13° 34.567'")->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString("N 52° 12.345', E 13° 34.567'")->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString("N 52° 12.345', E 13° 34.567'")->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString("52° 12.345' N, E13° 34.567' E")->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString("52° 12.345' N, E13° 34.567' E")->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('N52° 12.345′, E13° 34.567′')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('N52° 12.345′, E13° 34.567′')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('N 52° 12.345′, E 13° 34.567′')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('N 52° 12.345′, E 13° 34.567′')->getLng(), + 0.0001, + '' + ); + + $this->assertEqualsWithDelta( + $expectedLat, + CoordinateFactory::fromString('52° 12.345′ N, E13° 34.567′ E')->getLat(), + 0.0001, + '' + ); + $this->assertEqualsWithDelta( + $expectedLng, + CoordinateFactory::fromString('52° 12.345′ N, E13° 34.567′ E')->getLng(), + 0.0001, + '' + ); + + $this->assertEquals( + new Coordinate(52.2333, 20.9756), + CoordinateFactory::fromString('52° 13.998′ 020° 58.536′') + ); + } + + /** + * @dataProvider dataIfFromStringWithIntegerMinutesAndDecimalSecondsWorksAsExpected + * + * @param float $expectedLat + * @param float $expectedLng + * @param string $string + */ + public function testIfFromStringWithIntegerMinutesAndDecimalSecondsWorksAsExpected( + $expectedLat, + $expectedLng, + $string + ): void { + $coordinate = CoordinateFactory::fromString($string); + $this->assertEqualsWithDelta($expectedLat, $coordinate->getLat(), 0.0001, ''); + $this->assertEqualsWithDelta($expectedLng, $coordinate->getLng(), 0.0001, ''); + } + + /** + * Data provider for decimal seconds parser test. + */ + public function dataIfFromStringWithIntegerMinutesAndDecimalSecondsWorksAsExpected(): ?Generator + { + $expected = new Coordinate(52.20575, 13.576116667); + $expectedLat = $expected->getLat(); + $expectedLng = $expected->getLng(); + + $testData = [ + '52 12 20.7, 13 34 34.02', + '52 12 20.7N, 13 34 34.02E', + '52 12 20.7 N, E13 34 34.02 E', + '52° 12\' 20.7" N, E13° 34\' 34.02" E', + '52° 12\' 20.7\'\' N, E13° 34\' 34.02\'\' E', + '52° 12′ 20.7″ N, E13° 34′ 34.02″ E', + '52° 12′ 20.7′′ N, E13° 34′ 34.02′′ E', + ]; + + foreach ($testData as $string) { + yield $string => [$expectedLat, $expectedLng, $string]; + } + } + + public function testIfInvalidFormatThrowsException(): void + { + $this->expectException(InvalidArgumentException::class); + + CoordinateFactory::fromString('Lorem ipsum dolor sit amet'); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DMSTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DMSTest.php new file mode 100644 index 000000000..893355137 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DMSTest.php @@ -0,0 +1,96 @@ +formatter = new DMS(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown(): void + { + } + + public function testSetUnitsUTF8(): void + { + $this->formatter->setUnits(DMS::UNITS_UTF8); + + $this->assertEquals(DMS::UNITS_UTF8, $this->formatter->getUnitType()); + } + + public function testSetUnitsASCII(): void + { + $this->formatter->setUnits(DMS::UNITS_ASCII); + + $this->assertEquals(DMS::UNITS_ASCII, $this->formatter->getUnitType()); + } + + public function testSetUnitsInvalidType(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid unit type'); + + + $this->formatter->setUnits('invalid'); + } + + public function testFormatDefaultSeparator(): void + { + $coordinate = new Coordinate(52.5, 13.5); + + $this->assertEquals('52° 30′ 00″ 013° 30′ 00″', $this->formatter->format($coordinate)); + } + + public function testFormatCustomSeparator(): void + { + $coordinate = new Coordinate(18.911306, - 155.678268); + + $this->formatter->setSeparator(', '); + + $this->assertEquals('18° 54′ 41″, -155° 40′ 42″', $this->formatter->format($coordinate)); + } + + public function testFormatCardinalLetters(): void + { + $coordinate = new Coordinate(18.911306, - 155.678268); + + $this->formatter->setSeparator(', ')->useCardinalLetters(true); + + $this->assertEquals('18° 54′ 41″ N, 155° 40′ 42″ W', $this->formatter->format($coordinate)); + } + + public function testFormatBothNegative(): void + { + $coordinate = new Coordinate(- 18.911306, - 155.678268); + + $this->formatter->setSeparator(', '); + + $this->assertEquals('-18° 54′ 41″, -155° 40′ 42″', $this->formatter->format($coordinate)); + } + + public function testFormatASCIIUnits(): void + { + $coordinate = new Coordinate(- 18.911306, - 155.678268); + + $this->formatter->setSeparator(', ')->setUnits(DMS::UNITS_ASCII); + + $this->assertEquals("-18° 54' 41\", -155° 40' 42\"", $this->formatter->format($coordinate)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DecimalDegreesTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DecimalDegreesTest.php new file mode 100644 index 000000000..a1127a0b3 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DecimalDegreesTest.php @@ -0,0 +1,57 @@ +object = new DecimalDegrees(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown(): void + { + } + + public function testFormatDefaultSeparator(): void + { + $coordinate = new Coordinate(52.5, 13.5); + + $formatter = new DecimalDegrees(); + + $this->assertEquals('52.50000 13.50000', $formatter->format($coordinate)); + } + + public function testFormatCustomSeparator(): void + { + $coordinate = new Coordinate(52.5, 13.5); + + $formatter = new DecimalDegrees(', '); + + $this->assertEquals('52.50000, 13.50000', $formatter->format($coordinate)); + } + + public function testIfSetSeparatorWorksAsExpected(): void + { + $coordinate = new Coordinate(52.5, 13.5); + + $formatter = new DecimalDegrees(); + $formatter->setSeparator('/'); + + $this->assertEquals('52.50000/13.50000', $formatter->format($coordinate)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DecimalMinutesTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DecimalMinutesTest.php new file mode 100644 index 000000000..8a0e9efa5 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/DecimalMinutesTest.php @@ -0,0 +1,113 @@ +formatter = new DecimalMinutes(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown(): void + { + } + + public function testSetUnitsUTF8(): void + { + $this->formatter->setUnits(DMS::UNITS_UTF8); + + $this->assertEquals(DMS::UNITS_UTF8, $this->formatter->getUnitType()); + } + + public function testSetUnitsASCII(): void + { + $this->formatter->setUnits(DMS::UNITS_ASCII); + + $this->assertEquals(DMS::UNITS_ASCII, $this->formatter->getUnitType()); + } + + public function testSetUnitsInvalidType(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid unit type'); + + $this->formatter->setUnits('invalid'); + } + + public function testFormatDefaultSeparator(): void + { + $coordinate = new Coordinate(52.5, 13.5); + + $this->assertEquals('52° 30.000′ 013° 30.000′', $this->formatter->format($coordinate)); + } + + public function testFormatCustomSeparator(): void + { + $coordinate = new Coordinate(18.911306, - 155.678268); + + $this->formatter->setSeparator(', '); + + $this->assertEquals('18° 54.678′, -155° 40.696′', $this->formatter->format($coordinate)); + } + + public function testFormatCardinalLetters(): void + { + $coordinate = new Coordinate(18.911306, - 155.678268); + + $this->formatter->setSeparator(', ')->useCardinalLetters(true); + + $this->assertEquals('18° 54.678′ N, 155° 40.696′ W', $this->formatter->format($coordinate)); + } + + public function testFormatBothNegative(): void + { + $coordinate = new Coordinate(- 18.911306, - 155.678268); + + $this->formatter->setSeparator(', '); + + $this->assertEquals('-18° 54.678′, -155° 40.696′', $this->formatter->format($coordinate)); + } + + public function testFormatASCIIUnits(): void + { + $coordinate = new Coordinate(- 18.911306, - 155.678268); + + $this->formatter->setSeparator(', ')->setUnits(DMS::UNITS_ASCII); + + $this->assertEquals("-18° 54.678', -155° 40.696'", $this->formatter->format($coordinate)); + } + + public function testSetDigits(): void + { + $coordinate = new Coordinate(- 18.911306, - 155.678268); + + $this->formatter->setDigits(2); + + $this->assertEquals('-18° 54.68′ -155° 40.70′', $this->formatter->format($coordinate)); + } + + public function testSetDecimalPoint(): void + { + $coordinate = new Coordinate(- 18.911306, - 155.678268); + + $this->formatter->setDecimalPoint(','); + + $this->assertEquals('-18° 54,678′ -155° 40,696′', $this->formatter->format($coordinate)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/GeoJSONTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/GeoJSONTest.php new file mode 100644 index 000000000..ef899d4d1 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Coordinate/GeoJSONTest.php @@ -0,0 +1,52 @@ +formatter = new GeoJSON(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown(): void + { + unset($this->formatter); + } + + public function testFormatDefault(): void + { + $coordinate = new Coordinate(52.5, 13.5); + + $json = '{ "type" : "Point" , "coordinates" : [ 13.5, 52.5 ] }'; + + $this->assertJsonStringEqualsJsonString($json, $this->formatter->format($coordinate)); + } + + public function testFormatPrecision(): void + { + $coordinate = new Coordinate(52.123456789012345, 13.123456789012345); + + $json = '{ "type" : "Point" , "coordinates" : [ 13.123456789012345, 52.123456789012345 ] }'; + + $this->assertJsonStringEqualsJsonString($json, $this->formatter->format($coordinate)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Polygon/GeoJSONTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Polygon/GeoJSONTest.php new file mode 100644 index 000000000..c3e8a1d91 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Polygon/GeoJSONTest.php @@ -0,0 +1,60 @@ +formatter = new GeoJSON(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown(): void + { + unset($this->formatter); + } + + public function testFormatDefault(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 20)); + $polygon->addPoint(new Coordinate(20, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, 20)); + + $json = '{ "type" : "Polygon" , "coordinates" : [ [ [ 20, 10 ], [ 40, 20 ], [ 40, 30 ], [ 20, 30] ] ] }'; + + $this->assertJsonStringEqualsJsonString($json, $this->formatter->format($polygon)); + } + + public function testPolygonGeoJSONWithLessThanThreePointsThrowsInvalidPolygonException(): void + { + $this->expectException(InvalidPolygonException::class); + + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(0, 0)); + $polygon->addPoint(new Coordinate(10, 10)); + + $this->formatter->format($polygon); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Polyline/GeoJSONTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Polyline/GeoJSONTest.php new file mode 100644 index 000000000..f6c491562 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Formatter/Polyline/GeoJSONTest.php @@ -0,0 +1,46 @@ +formatter = new GeoJSON(); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + protected function tearDown(): void + { + unset($this->formatter); + } + + public function testFormatDefault(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(52.5, 13.5)); + $polyline->addPoint(new Coordinate(62.5, 14.5)); + + $json = '{ "type" : "LineString" , "coordinates" : [ [ 13.5, 52.5 ], [ 14.5, 62.5 ] ] }'; + + $this->assertJsonStringEqualsJsonString($json, $this->formatter->format($polyline)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Intersection/IntersectionTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Intersection/IntersectionTest.php new file mode 100644 index 000000000..4f930a3a6 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Intersection/IntersectionTest.php @@ -0,0 +1,210 @@ +polygon = new Polygon(); + foreach ($coordinates as $coordinate) { + $this->polygon->addPoint(new Coordinate($coordinate[0], $coordinate[1])); + } + } + + public function testLineIntersections(): void + { + // Lines + $lineCenterCrossing = new Line( + new Coordinate(52.237594, 9.287635), + new Coordinate(52.258154, 11.010313) + ); + $lineTop = new Line( + new Coordinate(52.62456, 9.455537), + new Coordinate(52.608249, 10.734953) + ); + $lineBottom = new Line( + new Coordinate(51.880405, 9.613366), + new Coordinate(51.907345, 10.724879) + ); + $lineRight = new Line( + new Coordinate(52.720262, 10.627496), + new Coordinate(51.859671, 10.812188) + ); + + $intersection = new Intersection(); + + // By bounds + $this->assertTrue( + $intersection->intersects($lineCenterCrossing, $this->polygon, false) + ); + $this->assertFalse($intersection->intersects($lineTop, $this->polygon, false)); + $this->assertFalse($intersection->intersects($lineBottom, $this->polygon, false)); + $this->assertTrue($intersection->intersects($lineRight, $this->polygon, false)); + + // By shape + $this->assertTrue( + $intersection->intersects($lineCenterCrossing, $this->polygon, true) + ); + $this->assertFalse($intersection->intersects($lineTop, $this->polygon, true)); + $this->assertFalse($intersection->intersects($lineBottom, $this->polygon, true)); + $this->assertFalse($intersection->intersects($lineRight, $this->polygon, true)); + } + + public function testCoordinateIntersections(): void + { + $intersection = new Intersection(); + + // Coordinates + $pointContained = new Coordinate(52.328745, 10.151638); + $pointOutside = new Coordinate(52.549057, 10.475242); + $pointOutsideLine = new Coordinate(52.252717, 10.728334); + + // By bounds + $this->assertTrue($intersection->intersects($pointContained, $this->polygon, false)); + $this->assertFalse($intersection->intersects($pointOutside, $this->polygon, false)); + $this->assertFalse( + $intersection->intersects($pointOutsideLine, $this->polygon, false) + ); + + // By shape + $this->assertTrue($intersection->intersects($pointContained, $this->polygon, true)); + $this->assertFalse($intersection->intersects($pointOutside, $this->polygon, true)); + $this->assertFalse($intersection->intersects($pointOutsideLine, $this->polygon, true)); + } + + public function testPolygonIntersections(): void + { + $intersection = new Intersection(); + + // Polygons + $polygonLeftIntersecting = new Polygon(); + $coordinates = [ + [51.990136, 9.438747], + [52.493904, 9.408525], + [52.518432, 9.77791], + [51.807794, 9.871935], + [51.809766, 9.886408], + [51.990136, 9.438747], + ]; + foreach ($coordinates as $coordinate) { + $polygonLeftIntersecting->addPoint( + new Coordinate($coordinate[0], $coordinate[1]) + ); + } + + $polygonRightOutside = new Polygon(); + $coordinates = [ + [52.533043, 10.747941], + [52.326314, 10.787294], + [52.317063, 11.117259], + [52.317063, 11.117259], + [52.533043, 10.747941], + ]; + foreach ($coordinates as $coordinate) { + $polygonRightOutside->addPoint( + new Coordinate($coordinate[0], $coordinate[1]) + ); + } + + // By bounds + $this->assertTrue( + $intersection->intersects($polygonLeftIntersecting, $this->polygon, false) + ); + $this->assertFalse( + $intersection->intersects($polygonRightOutside, $this->polygon, false) + ); + + // By shape + $this->assertTrue( + $intersection->intersects($polygonLeftIntersecting, $this->polygon, true) + ); + $this->assertFalse( + $intersection->intersects($polygonRightOutside, $this->polygon, true) + ); + } + + public function testPolylineIntersections(): void + { + $intersection = new Intersection(); + + $polyline1 = new Polyline(); + $polyline1->addPoint(new Coordinate(-4, -2)); + $polyline1->addPoint(new Coordinate(5, 2)); + $polyline1->addPoint(new Coordinate(-1, 7)); + $polyline1->addPoint(new Coordinate(-3, 4)); + + $polyline2 = new Polyline(); + $polyline2->addPoint(new Coordinate(-8, 3)); + $polyline2->addPoint(new Coordinate(-5, -5)); + $polyline2->addPoint(new Coordinate(4, -3)); + + $polyline4 = new Polyline(); + $polyline4->addPoint(new Coordinate(1, 10)); + $polyline4->addPoint(new Coordinate(-1, 5)); + $polyline4->addPoint(new Coordinate(-6, 9)); + + $polyline3 = new Polyline(); + $polyline3->addPoint(new Coordinate(11, 13)); + $polyline3->addPoint(new Coordinate(21, 14)); + $polyline3->addPoint(new Coordinate(15, 18)); + + $polyline5 = new Polyline(); + $polyline5->addPoint(new Coordinate(9, 22)); + $polyline5->addPoint(new Coordinate(13, 24)); + $polyline5->addPoint(new Coordinate(14, 20)); + $polyline5->addPoint(new Coordinate(8, 15)); + + // By bounds + $this->assertTrue($intersection->intersects($polyline3, $polyline5, false)); + $this->assertTrue($intersection->intersects($polyline5, $polyline3, false)); + + $this->assertFalse($intersection->intersects($polyline2, $polyline3, false)); + $this->assertFalse($intersection->intersects($polyline3, $polyline2, false)); + + $this->assertTrue($intersection->intersects($polyline1, $polyline2, false)); + $this->assertTrue($intersection->intersects($polyline2, $polyline1, false)); + + $this->assertTrue($intersection->intersects($polyline1, $polyline4, false)); + $this->assertTrue($intersection->intersects($polyline4, $polyline1, false)); + + // By shape + $this->assertTrue($intersection->intersects($polyline1, $polyline4, true)); + $this->assertTrue($intersection->intersects($polyline4, $polyline1, true)); + + $this->assertFalse($intersection->intersects($polyline1, $polyline3, true)); + $this->assertFalse($intersection->intersects($polyline3, $polyline1, true)); + + $this->assertFalse($intersection->intersects($polyline1, $polyline5, true)); + $this->assertFalse($intersection->intersects($polyline5, $polyline1, true)); + + $this->assertFalse($intersection->intersects($polyline2, $polyline3, true)); + $this->assertFalse($intersection->intersects($polyline3, $polyline2, true)); + + $this->assertFalse($intersection->intersects($polyline2, $polyline4, true)); + $this->assertFalse($intersection->intersects($polyline4, $polyline2, true)); + + $this->assertFalse($intersection->intersects($polyline2, $polyline5, true)); + $this->assertFalse($intersection->intersects($polyline5, $polyline2, true)); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/LineTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/LineTest.php new file mode 100644 index 000000000..9872a39f8 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/LineTest.php @@ -0,0 +1,152 @@ +assertEquals($point1, $line->getPoint1()); + $this->assertEquals($point2, $line->getPoint2()); + } + + public function testCalculateLength(): void + { + $point1 = new Coordinate(52.5, 13.5); + $point2 = new Coordinate(64.1, -21.9); + + $line = new Line($point1, $point2); + + $this->assertEqualsWithDelta(2397867.8, $line->getLength(new Vincenty()), 0.01, ''); + } + + public function testGetReverseWorksAsExpected(): void + { + $point1 = new Coordinate(52.5, 13.5); + $point2 = new Coordinate(64.1, -21.9); + + $line = new Line($point1, $point2); + $reversedLine = $line->getReverse(); + + $expected = new Line($point2, $point1); + + $this->assertEquals($expected, $reversedLine); + } + + public function testIfGetBearingWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $line = new Line($point1, $point2); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(90.0, $line->getBearing($bearingCalculator)); + } + + public function testIfGetFinalBearingWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $line = new Line($point1, $point2); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(90.0, $line->getFinalBearing($bearingCalculator)); + } + + public function testIfGetBearingReversedWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $line = new Line($point2, $point1); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(270.0, $line->getBearing($bearingCalculator)); + } + + public function testIfGetFinalBearingReversedWorksAsExpected(): void + { + $point1 = new Coordinate(0, 0); + $point2 = new Coordinate(0, 10); + + $line = new Line($point2, $point1); + + $bearingCalculator = new BearingEllipsoidal(); + + $this->assertEquals(270.0, $line->getFinalBearing($bearingCalculator)); + } + + public function testIfGetBoundsWorksAsExpected(): void + { + $point1 = new Coordinate(-10.0, 20.0); + $point2 = new Coordinate(3.0, 10.0); + + $line = new Line($point2, $point1); + + $expected = new Bounds(new Coordinate(3.0, 10.0), new Coordinate(-10.0, 20.0)); + + $this->assertEquals($expected, $line->getBounds()); + } + + public function testIfGetMidpointWorksAsExpected() + { + $line = new Line(new Coordinate(0, 0), new Coordinate(10, 20)); + + $this->assertEqualsWithDelta(5.07672, $line->getMidpoint()->getLat(), 0.0001); + $this->assertEqualsWithDelta(9.92267, $line->getMidpoint()->getLng(), 0.0001); + + $line = new Line(new Coordinate(1, 1), new Coordinate(-2, -2)); + + $this->assertEqualsWithDelta(-0.5, $line->getMidpoint()->getLat(), 0.001); + $this->assertEqualsWithDelta(-0.5, $line->getMidpoint()->getLng(), 0.001); + + $line = new Line(new Coordinate(35, -90), new Coordinate(35.2, -90.4)); + + $this->assertEqualsWithDelta(35.1, $line->getMidpoint()->getLat(), 0.001); + $this->assertEqualsWithDelta(-90.2, $line->getMidpoint()->getLng(), 0.001); + } + + public function testIfGetMidpointAcrossLongitudeBorderWorksAsExpected() + { + $line = new Line(new Coordinate(0.0, -179.0), new Coordinate(0.0, 179.0)); + $this->assertEquals(new Coordinate(0.0, -180.0), $line->getMidpoint()); + + $line = new Line(new Coordinate(0.0, -178.0), new Coordinate(0.0, 179.0)); + $this->assertEquals(new Coordinate(0.0, -179.5), $line->getMidpoint()); + } + + public function testIfGetIntermediatePointWorksAsExpected() + { + $line = new Line(new Coordinate(0, 0), new Coordinate(0, 1)); + $this->assertEquals(new Coordinate(0, 0), $line->getIntermediatePoint(0.)); + $line = new Line(new Coordinate(0, 0), new Coordinate(0, 1)); + $this->assertEquals(new Coordinate(0, .5), $line->getIntermediatePoint(.5)); + $line = new Line(new Coordinate(0, 0), new Coordinate(0, 1)); + $this->assertEquals(new Coordinate(0, 1), $line->getIntermediatePoint(1.)); + } + + public function testIfGetIntermediatePointThrowsExceptionForAntipodes() + { + $this->expectException(\RuntimeException::class); + $this->expectExceptionCode(5382449689); + + $line = new Line(new Coordinate(45, -45), new Coordinate(-45, 135)); + $line->getIntermediatePoint(.5); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/PolygonTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/PolygonTest.php new file mode 100644 index 000000000..920d0bfb5 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/PolygonTest.php @@ -0,0 +1,569 @@ +assertEquals([], $polygon->getPoints()); + + $point1 = new Coordinate(10, 10); + $polygon->addPoint($point1); + + $this->assertEquals([$point1], $polygon->getPoints()); + + $point2 = new Coordinate(10, 20); + $polygon->addPoint($point2); + + $this->assertEquals([$point1, $point2], $polygon->getPoints()); + } + + public function testIfGetNumberOfPointsWorksAsExpected(): void + { + $polygon = new Polygon(); + + $this->assertEquals(0, $polygon->getNumberOfPoints()); + + $polygon->addPoint(new Coordinate(10, 10)); + + $this->assertEquals(1, $polygon->getNumberOfPoints()); + + $polygon->addPoint(new Coordinate(10, 20)); + + $this->assertEquals(2, $polygon->getNumberOfPoints()); + } + + public function testIfGetSegmentsWorksAsExpected(): void + { + $polygon = new Polygon(); + + $point1 = new Coordinate(10, 20); + $point2 = new Coordinate(10, 40); + $point3 = new Coordinate(30, 40); + $point4 = new Coordinate(30, 20); + $polygon->addPoint($point1); + $polygon->addPoint($point2); + $polygon->addPoint($point3); + $polygon->addPoint($point4); + + $expected = [ + new Line($point1, $point2), + new Line($point2, $point3), + new Line($point3, $point4), + new Line($point4, $point1), + ]; + + $this->assertEquals($expected, $polygon->getSegments()); + } + + public function testIfGetLatsWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 20)); + $polygon->addPoint(new Coordinate(10, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, 20)); + + $expected = [10, 10, 30, 30]; + + $this->assertEquals($expected, $polygon->getLats()); + } + + public function testIfGetLngsWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 20)); + $polygon->addPoint(new Coordinate(10, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, 20)); + + $expected = [20, 40, 40, 20]; + + $this->assertEquals($expected, $polygon->getLngs()); + } + + public function testIfContainsPointCheckWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 20)); + $polygon->addPoint(new Coordinate(10, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, 20)); + + $point = new Coordinate(20, 30); + + $this->assertTrue($polygon->contains($point)); + } + + public function testIfContainsPointCheckWithLatitudeSignSwitchWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(- 30, 20)); + $polygon->addPoint(new Coordinate(- 30, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, 20)); + + $point = new Coordinate(0, 30); + $this->assertTrue($polygon->contains($point)); + + $point = new Coordinate(- 10, 30); + $this->assertTrue($polygon->contains($point)); + + $point = new Coordinate(10, 30); + $this->assertTrue($polygon->contains($point)); + } + + public function testIfContainsPointCheckWithLongitudeSignSwitchWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, - 20)); + $polygon->addPoint(new Coordinate(10, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, - 20)); + + $point = new Coordinate(20, 0); + $this->assertTrue($polygon->contains($point)); + + $point = new Coordinate(20, - 10); + $this->assertTrue($polygon->contains($point)); + + $point = new Coordinate(20, 10); + $this->assertTrue($polygon->contains($point)); + } + + public function testIfNotContainsPointCheckWithWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 20)); + $polygon->addPoint(new Coordinate(10, 40)); + $polygon->addPoint(new Coordinate(30, 40)); + $polygon->addPoint(new Coordinate(30, 20)); + + $point = new Coordinate(20, 10); + $this->assertFalse($polygon->contains($point)); + + $point = new Coordinate(20, 50); + $this->assertFalse($polygon->contains($point)); + + $point = new Coordinate(0, 30); + $this->assertFalse($polygon->contains($point)); + + $point = new Coordinate(40, 30); + $this->assertFalse($polygon->contains($point)); + } + + /* + public function testIfContainsPointCheckWithLongitudesCrossingThe180thMeridianWorksAsExpected() + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 150)); + $polygon->addPoint(new Coordinate(10, -150)); + $polygon->addPoint(new Coordinate(30, -150)); + $polygon->addPoint(new Coordinate(30, 150)); + + $point = new Coordinate(20, 160); + $this->assertTrue($polygon->contains($point)); + + $point = new Coordinate(20, -160); + $this->assertTrue($polygon->contains($point)); + } + */ + + public function testIfPerimeterCalculationWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(10, 10)); + $polygon->addPoint(new Coordinate(10, 20)); + $polygon->addPoint(new Coordinate(20, 20)); + $polygon->addPoint(new Coordinate(20, 10)); + + // http://geographiclib.sourceforge.net/cgi-bin/Planimeter?type=polygon&rhumb=geodesic&input=10+10%0D%0A10+20%0D%0A20+20%0D%0A20+10&norm=decdegrees&option=Submit + $this->assertEqualsWithDelta(4355689.472548, $polygon->getPerimeter(new Vincenty()), 0.01, ''); + + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52, 13)); + $polygon->addPoint(new Coordinate(53, 13)); + $polygon->addPoint(new Coordinate(53, 12)); + $polygon->addPoint(new Coordinate(52, 12)); + + // http://geographiclib.sourceforge.net/cgi-bin/Planimeter?type=polygon&rhumb=geodesic&input=52+13%0D%0A53+13%0D%0A53+12%0D%0A52+12&norm=decdegrees&option=Submit + $this->assertEqualsWithDelta(358367.809428, $polygon->getPerimeter(new Vincenty()), 0.01, ''); + } + + public function testIfAreaCalculationWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(0.0000000000, 0.0000000000)); + $polygon->addPoint(new Coordinate(0.0000000000, 0.0008983153)); + $polygon->addPoint(new Coordinate(0.0009043695, 0.0008983153)); + $polygon->addPoint(new Coordinate(0.0009043695, 0.0000000000)); + + // https://geographiclib.sourceforge.io/cgi-bin/Planimeter?type=polygon&rhumb=geodesic&input=0.0000000000+0.0000000000%0D%0A0.0000000000+0.0008983153%0D%0A0.0009043695+0.0008983153%0D%0A0.0009043695+0.0000000000&norm=decdegrees&option=Submit + //$this->assertEquals(10000.0, $polygon->getArea(), '', 1.0); + } + + public function testIfPolygonContainsGeometryWithPolygonInsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $insidePolygon = new Polygon(); + $insidePolygon->addPoint(new Coordinate(52.206110581755638, 13.674710914492607)); + $insidePolygon->addPoint(new Coordinate(52.202216433361173, 13.673997698351741)); + $insidePolygon->addPoint(new Coordinate(52.20279042609036, 13.666518358513713)); + $insidePolygon->addPoint(new Coordinate(52.209159163758159, 13.667042898014188)); + $insidePolygon->addPoint(new Coordinate(52.215381134301424, 13.664670567959547)); + $insidePolygon->addPoint(new Coordinate(52.209875900298357, 13.672981224954128)); + + $this->assertTrue($polygon->containsGeometry($insidePolygon)); + } + + public function testIfPolygonContainsGeometryWithPolygonInsideAndOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $inAndOutSidePolygon = new Polygon(); + $inAndOutSidePolygon->addPoint(new Coordinate(52.206110581755638, 13.674710914492607)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.202216433361173, 13.673997698351741)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.20279042609036, 13.666518358513713)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.209159163758159, 13.667042898014188)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.215381134301424, 13.664670567959547)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.209875900298357, 13.672981224954128)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.211303086951375, 13.676270367577672)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.20556978136301, 13.688599476590753)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.205583276227117, 13.688599476590753)); + $inAndOutSidePolygon->addPoint(new Coordinate(52.204232113435864, 13.683774350211024)); + + $this->assertFalse($polygon->containsGeometry($inAndOutSidePolygon)); + } + + public function testIfPolygonContainsGeometryWithPolygonOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $outsidePolygon = new Polygon(); + $outsidePolygon->addPoint(new Coordinate(52.2123983502388, 13.677485324442387)); + $outsidePolygon->addPoint(new Coordinate(52.215186841785908, 13.683912232518196)); + $outsidePolygon->addPoint(new Coordinate(52.207024795934558, 13.685344364494085)); + + $this->assertFalse($polygon->containsGeometry($outsidePolygon)); + } + + public function testIfPolygonContainsGeometryWithPolylineInsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $insidePolyline = new Polyline(); + $insidePolyline->addPoint(new Coordinate(52.206110581755638, 13.674710914492607)); + $insidePolyline->addPoint(new Coordinate(52.202216433361173, 13.673997698351741)); + $insidePolyline->addPoint(new Coordinate(52.20279042609036, 13.666518358513713)); + $insidePolyline->addPoint(new Coordinate(52.209159163758159, 13.667042898014188)); + $insidePolyline->addPoint(new Coordinate(52.215381134301424, 13.664670567959547)); + $insidePolyline->addPoint(new Coordinate(52.209875900298357, 13.672981224954128)); + + $this->assertTrue($polygon->containsGeometry($insidePolyline)); + } + + public function testIfPolygonContainsGeometryWithPolylineInsideAndOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $inAndOutSidePolyline = new Polyline(); + $inAndOutSidePolyline->addPoint(new Coordinate(52.206110581755638, 13.674710914492607)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.202216433361173, 13.673997698351741)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.20279042609036, 13.666518358513713)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.209159163758159, 13.667042898014188)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.215381134301424, 13.664670567959547)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.209875900298357, 13.672981224954128)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.211303086951375, 13.676270367577672)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.20556978136301, 13.688599476590753)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.205583276227117, 13.688599476590753)); + $inAndOutSidePolyline->addPoint(new Coordinate(52.204232113435864, 13.683774350211024)); + + $this->assertFalse($polygon->containsGeometry($inAndOutSidePolyline)); + } + + public function testIfPolygonContainsGeometryWithPolylineOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $outsidePolyline = new Polyline(); + $outsidePolyline->addPoint(new Coordinate(52.2123983502388, 13.677485324442387)); + $outsidePolyline->addPoint(new Coordinate(52.215186841785908, 13.683912232518196)); + $outsidePolyline->addPoint(new Coordinate(52.207024795934558, 13.685344364494085)); + + $this->assertFalse($polygon->containsGeometry($outsidePolyline)); + } + + public function testIfPolygonContainsGeometryWithLineInsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $insideLine = new Line( + new Coordinate(52.206110581755638, 13.674710914492607), + new Coordinate(52.202216433361173, 13.673997698351741) + ); + + $this->assertTrue($polygon->containsGeometry($insideLine)); + } + + public function testIfPolygonContainsGeometryWithLineInsideAndOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $inAndOutSidePolyline = new Line( + new Coordinate(52.207389576360583, 13.670525830239058), + new Coordinate(52.210680730640888, 13.687128368765116) + ); + + $this->assertFalse($polygon->containsGeometry($inAndOutSidePolyline)); + } + + public function testIfPolygonContainsGeometryWithLineOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $outsidePolyline = new Line( + new Coordinate(52.215186841785908, 13.683912232518196), + new Coordinate(52.207024795934558, 13.685344364494085) + ); + + $this->assertFalse($polygon->containsGeometry($outsidePolyline)); + } + + public function testIfPolygonContainsGeometryWithPointInsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $this->assertTrue($polygon->containsGeometry(new Coordinate(52.206110581755638, 13.674710914492607))); + } + + public function testIfPolygonContainsGeometryWithPointOutsideWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.221651719883084, 13.661613101139665)); + $polygon->addPoint(new Coordinate(52.215716242790222, 13.662988655269146)); + $polygon->addPoint(new Coordinate(52.211922844871879, 13.662990247830749)); + $polygon->addPoint(new Coordinate(52.208002796396613, 13.664533020928502)); + $polygon->addPoint(new Coordinate(52.203469779342413, 13.664621533825994)); + $polygon->addPoint(new Coordinate(52.199896154925227, 13.665583860129118)); + $polygon->addPoint(new Coordinate(52.199177406728268, 13.665664242580533)); + $polygon->addPoint(new Coordinate(52.197426510974765, 13.664221465587616)); + $polygon->addPoint(new Coordinate(52.196468207985163, 13.674150248989463)); + $polygon->addPoint(new Coordinate(52.200047867372632, 13.674412602558732)); + $polygon->addPoint(new Coordinate(52.203508755192161, 13.676183195784688)); + $polygon->addPoint(new Coordinate(52.206863863393664, 13.678688379004598)); + $polygon->addPoint(new Coordinate(52.213457236066461, 13.67043505422771)); + $polygon->addPoint(new Coordinate(52.217430174350739, 13.66775787435472)); + $polygon->addPoint(new Coordinate(52.221683654934168, 13.661622740328312)); + + $this->assertFalse($polygon->containsGeometry(new Coordinate(52.2123983502388, 13.677485324442387))); + } + + public function testGetReverseWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.5, 13.5)); + $polygon->addPoint(new Coordinate(64.1, - 21.9)); + $polygon->addPoint(new Coordinate(40.7, - 74.0)); + $polygon->addPoint(new Coordinate(33.9, - 118.4)); + + $reversed = $polygon->getReverse(); + + $expected = new Polygon(); + $expected->addPoint(new Coordinate(33.9, - 118.4)); + $expected->addPoint(new Coordinate(40.7, - 74.0)); + $expected->addPoint(new Coordinate(64.1, - 21.9)); + $expected->addPoint(new Coordinate(52.5, 13.5)); + + $this->assertEquals($expected, $reversed); + } + + public function testReverseTwiceWorksAsExpected(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.5, 13.5)); + $polygon->addPoint(new Coordinate(64.1, - 21.9)); + $polygon->addPoint(new Coordinate(40.7, - 74.0)); + $polygon->addPoint(new Coordinate(33.9, - 118.4)); + + $doubleReversed = $polygon->getReverse()->getReverse(); + + $this->assertEquals($polygon, $doubleReversed); + } + + public function testIfGetBoundsWorksAsExpected(): void + { + $polygon = new Polygon(); + + $point1 = new Coordinate(10.0, -20.0); + $point2 = new Coordinate(-10.0, 40.0); + $point3 = new Coordinate(30.0, 50.0); + $point4 = new Coordinate(40.0, 20.0); + $polygon->addPoint($point1); + $polygon->addPoint($point2); + $polygon->addPoint($point3); + $polygon->addPoint($point4); + + $expected = new Bounds(new Coordinate(40.0, -20.0), new Coordinate(-10.0, 50.0)); + + $this->assertEquals($expected, $polygon->getBounds()); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/PolylineTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/PolylineTest.php new file mode 100644 index 000000000..3ae46938d --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/PolylineTest.php @@ -0,0 +1,159 @@ +polyline = new Polyline(); + $this->polyline->addPoint(new Coordinate(52.5, 13.5)); + $this->polyline->addPoint(new Coordinate(64.1, -21.9)); + $this->polyline->addPoint(new Coordinate(40.7, -74.0)); + $this->polyline->addPoint(new Coordinate(33.9, -118.4)); + } + + public function testCreatePolyline(): void + { + static::assertCount(4, $this->polyline->getPoints()); + } + + public function testGetSegments(): void + { + $segments = $this->polyline->getSegments(); + + static::assertEquals(new Line(new Coordinate(52.5, 13.5), new Coordinate(64.1, -21.9)), $segments[0]); + static::assertEquals(new Line(new Coordinate(64.1, -21.9), new Coordinate(40.7, -74.0)), $segments[1]); + static::assertEquals(new Line(new Coordinate(40.7, -74.0), new Coordinate(33.9, -118.4)), $segments[2]); + } + + public function testGetSegmentsForOnlyOnePointInLineWorksAsExpected(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(52.5, 13.5)); + + static::assertEquals([], $polyline->getSegments()); + } + + public function testGetLength(): void + { + static::assertEqualsWithDelta(10576798.9, $this->polyline->getLength(new Vincenty()), 0.1, ''); + } + + public function testGetReverseWorksAsExpected(): void + { + $reversed = $this->polyline->getReverse(); + + $expected = new Polyline(); + $expected->addPoint(new Coordinate(33.9, -118.4)); + $expected->addPoint(new Coordinate(40.7, -74.0)); + $expected->addPoint(new Coordinate(64.1, -21.9)); + $expected->addPoint(new Coordinate(52.5, 13.5)); + + static::assertEquals($expected, $reversed); + } + + public function testReverseTwiceWorksAsExpected(): void + { + $doubleReversed = $this->polyline->getReverse()->getReverse(); + + static::assertEquals($this->polyline, $doubleReversed); + } + + public function testGetBoundsWorksAsExpected(): void + { + $expected = new Bounds(new Coordinate(64.1, -118.4), new Coordinate(33.9, 13.5)); + + static::assertEquals($expected, $this->polyline->getBounds()); + } + + public function testAddUniquePointWorksAsExpeted(): void + { + $expected = $this->polyline; + $unique = new Polyline(); + + // Pass 1 + $unique->addUniquePoint(new Coordinate(52.5, 13.5)); + $unique->addUniquePoint(new Coordinate(64.1, -21.9)); + $unique->addUniquePoint(new Coordinate(40.7, -74.0)); + $unique->addUniquePoint(new Coordinate(33.9, -118.4)); + + // Pass 2 + $unique->addUniquePoint(new Coordinate(52.5, 13.5)); + $unique->addUniquePoint(new Coordinate(64.1, -21.9)); + $unique->addUniquePoint(new Coordinate(40.7, -74.0)); + $unique->addUniquePoint(new Coordinate(33.9, -118.4)); + + static::assertEquals($unique, $expected); + } + + public function testAddUniquePointWithAllowedDistanceZero(): void + { + $expected = $this->polyline; + $actual = clone $expected; + + $actual->addUniquePoint(new Coordinate(33.9, -118.4), .0); + + static::assertEquals($expected, $actual); + + $expected->addPoint(new Coordinate(33.90001, -118.40001)); + $actual->addUniquePoint(new Coordinate(33.90001, -118.40001), .0); + + static::assertEquals($expected, $actual); + } + + public function testAddUniquePointWithAllowedDistance(): void + { + $expected = $this->polyline; + $actual = clone $expected; + + $actual->addUniquePoint(new Coordinate(33.90000001, -118.40000001), .001); + + static::assertEquals($expected, $actual); + + $expected = $this->polyline; + $actual = clone $expected; + + $actual->addUniquePoint(new Coordinate(33.900001, -118.400001), 1); + + static::assertEquals($expected, $actual); + } + + public function testGetAveragePointWorksAsExpected(): void + { + $middle = $this->polyline->getAveragePoint(); + + $this->assertEquals($middle, new Coordinate(47.8, -50.2)); + } + + public function testGetAveragePointCrossingDateLine(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(80.0, 179.0)); + $polyline->addPoint(new Coordinate(80.0, -179.0)); + + static::markTestSkipped('Polyline crossing dateline'); + } + + public function testGetAveragePointWithNoPoints(): void + { + $polyline = new Polyline(); + + $this->expectException(InvalidGeometryException::class); + $this->expectExceptionMessage('Polyline doesn\'t contain points'); + $this->expectExceptionCode(9464188927); + + $middle = $polyline->getAveragePoint(); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Processor/Polyline/SimplifyBearingTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Processor/Polyline/SimplifyBearingTest.php new file mode 100644 index 000000000..140a6b940 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Processor/Polyline/SimplifyBearingTest.php @@ -0,0 +1,93 @@ +addPoint(new Coordinate(10.0, 10.0)); + $polyline->addPoint(new Coordinate(20.0, 20.0)); + $polyline->addPoint(new Coordinate(30.0, 10.0)); + + $processor = new SimplifyBearing(85); + + // actual bearing difference between the both segments is + // 83.3 degrees, therefore the middle point gets removed + $simplified = $processor->simplify($polyline); + + $segments = $simplified->getSegments(); + + $this->assertEquals(1, count($segments)); + $this->assertEquals(new Line(new Coordinate(10.0, 10.0), new Coordinate(30.0, 10.0)), $segments[0]); + } + + public function testSimplifyTwoPointsImpossible(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(10.0, 10.0)); + $polyline->addPoint(new Coordinate(20.0, 20.0)); + + $processor = new SimplifyBearing(10); + + $simplified = $processor->simplify($polyline); + + $this->assertEquals($polyline, $simplified); + } + + public function testSimplifyPolygon(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.22756274954098, 13.642145602718902)); + $polygon->addPoint(new Coordinate(52.239006313247366, 13.707722618459625)); + $polygon->addPoint(new Coordinate(52.24786291062496, 13.690119804191333)); + $polygon->addPoint(new Coordinate(52.25589445256298, 13.6807244463633)); + $polygon->addPoint(new Coordinate(52.259384204167624, 13.670769072927543)); + $polygon->addPoint(new Coordinate(52.263977114630265, 13.664195445135501)); + $polygon->addPoint(new Coordinate(52.2677055, 13.6518132)); + $polygon->addPoint(new Coordinate(52.2732257, 13.6453916)); + $polygon->addPoint(new Coordinate(52.27315767127478, 13.632664578662904)); + + $processor = new SimplifyBearing(45); + + $simplified = $processor->simplifyGeometry($polygon); + + $segments = $simplified->getSegments(); + + $this->assertCount(4, $segments); + $this->assertEquals( + new Line( + new Coordinate(52.22756274954098, 13.642145602718902), + new Coordinate(52.239006313247366, 13.707722618459625) + ), + $segments[0] + ); + $this->assertEquals( + new Line( + new Coordinate(52.239006313247366, 13.707722618459625), + new Coordinate(52.2732257, 13.6453916) + ), + $segments[1] + ); + $this->assertEquals( + new Line( + new Coordinate(52.2732257, 13.6453916), + new Coordinate(52.27315767127478, 13.632664578662904) + ), + $segments[2] + ); + $this->assertEquals( + new Line( + new Coordinate(52.27315767127478, 13.632664578662904), + new Coordinate(52.22756274954098, 13.642145602718902) + ), + $segments[3] + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Processor/Polyline/SimplifyDouglasPeuckerTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Processor/Polyline/SimplifyDouglasPeuckerTest.php new file mode 100644 index 000000000..1c9e3604a --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Processor/Polyline/SimplifyDouglasPeuckerTest.php @@ -0,0 +1,143 @@ +addPoint(new Coordinate(10.0, 10.0)); + $polyline->addPoint(new Coordinate(20.0, 20.0)); + $polyline->addPoint(new Coordinate(30.0, 10.0)); + + $processor = new SimplifyDouglasPeucker(1500000); + + // actual deviation is 1046 km, so 1500 km is enough of tolerance to strip the 2nd coordinate + $simplified = $processor->simplify($polyline); + + $segments = $simplified->getSegments(); + + $this->assertCount(1, $segments); + $this->assertEquals(new Line(new Coordinate(10.0, 10.0), new Coordinate(30.0, 10.0)), $segments[0]); + } + + public function testSimplifyFourPointsToTwoPoints(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(50.0, 10.0)); + $polyline->addPoint(new Coordinate(40.0, 20.0)); + $polyline->addPoint(new Coordinate(30.0, 10.0)); + $polyline->addPoint(new Coordinate(20.0, 30.0)); + + $processor = new SimplifyDouglasPeucker(1500000); + + $simplified = $processor->simplify($polyline); + + $segments = $simplified->getSegments(); + + $this->assertCount(1, $segments); + $this->assertEquals(new Line(new Coordinate(50.0, 10.0), new Coordinate(20.0, 30.0)), $segments[0]); + } + + public function testSimplifyFourPointsToThreePoints(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(50.0, 10.0)); + $polyline->addPoint(new Coordinate(40.0, 20.0)); + $polyline->addPoint(new Coordinate(30.0, 10.0)); + $polyline->addPoint(new Coordinate(20.0, 30.0)); + + $processor = new SimplifyDouglasPeucker(1200000); + + $simplified = $processor->simplify($polyline); + + $segments = $simplified->getSegments(); + + $this->assertCount(2, $segments); + $this->assertEquals(new Line(new Coordinate(50.0, 10.0), new Coordinate(30.0, 10.0)), $segments[0]); + $this->assertEquals(new Line(new Coordinate(30.0, 10.0), new Coordinate(20.0, 30.0)), $segments[1]); + } + + public function testSimplifyThreePointsImpossible(): void + { + $polyline = new Polyline(); + $polyline->addPoint(new Coordinate(10.0, 10.0)); + $polyline->addPoint(new Coordinate(20.0, 20.0)); + $polyline->addPoint(new Coordinate(30.0, 10.0)); + + $processor = new SimplifyDouglasPeucker(1000); + + $simplified = $processor->simplify($polyline); + + $this->assertEquals($polyline, $simplified); + } + + public function testSimplifyPolygonFourPointsToThreePoints(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(50.0, 10.0)); + $polygon->addPoint(new Coordinate(40.0, 20.0)); + $polygon->addPoint(new Coordinate(30.0, 10.0)); + $polygon->addPoint(new Coordinate(20.0, 30.0)); + + $processor = new SimplifyDouglasPeucker(1200000); + + $simplified = $processor->simplifyGeometry($polygon); + + $segments = $simplified->getSegments(); + + $this->assertCount(3, $segments); + $this->assertEquals(new Line(new Coordinate(50.0, 10.0), new Coordinate(30.0, 10.0)), $segments[0]); + $this->assertEquals(new Line(new Coordinate(30.0, 10.0), new Coordinate(20.0, 30.0)), $segments[1]); + $this->assertEquals(new Line(new Coordinate(20.0, 30.0), new Coordinate(50.0, 10.0)), $segments[2]); + } + + public function testSimplifyPolygon(): void + { + $polygon = new Polygon(); + $polygon->addPoint(new Coordinate(52.22756274954098, 13.642145602718902)); + $polygon->addPoint(new Coordinate(52.239006313247366, 13.707722618459625)); + $polygon->addPoint(new Coordinate(52.24786291062496, 13.690119804191333)); + $polygon->addPoint(new Coordinate(52.25589445256298, 13.6807244463633)); + $polygon->addPoint(new Coordinate(52.259384204167624, 13.670769072927543)); + $polygon->addPoint(new Coordinate(52.263977114630265, 13.664195445135501)); + $polygon->addPoint(new Coordinate(52.2677055, 13.6518132)); + $polygon->addPoint(new Coordinate(52.2732257, 13.6453916)); + $polygon->addPoint(new Coordinate(52.27315767127478, 13.632664578662904)); + + $processor = new SimplifyDouglasPeucker(1000); + + $simplified = $processor->simplifyGeometry($polygon); + + $segments = $simplified->getSegments(); + + $this->assertCount(3, $segments); + $this->assertEquals( + new Line( + new Coordinate(52.22756274954098, 13.642145602718902), + new Coordinate(52.239006313247366, 13.707722618459625) + ), + $segments[0] + ); + $this->assertEquals( + new Line( + new Coordinate(52.239006313247366, 13.707722618459625), + new Coordinate(52.27315767127478, 13.632664578662904) + ), + $segments[1] + ); + $this->assertEquals( + new Line( + new Coordinate(52.27315767127478, 13.632664578662904), + new Coordinate(52.22756274954098, 13.642145602718902) + ), + $segments[2] + ); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/CartesianTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/CartesianTest.php new file mode 100644 index 000000000..5a4a2d91c --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/CartesianTest.php @@ -0,0 +1,39 @@ +point = new Cartesian(1.0, 2.0, 3.0); + } + + public function testGetX(): void + { + $this->assertEquals(1.0, $this->point->getX()); + } + + public function testGetZ(): void + { + $this->assertEquals(3.0, $this->point->getZ()); + } + + public function testGetY(): void + { + $this->assertEquals(2.0, $this->point->getY()); + } + + public function testAdd(): void + { + $expected = new Cartesian(4.0, 5.0, 6.0); + + $this->assertEquals($expected, $this->point->add(new Cartesian(3.0, 3.0, 3.0))); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/PointToLineDistanceTestHaversineTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/PointToLineDistanceTestHaversineTest.php new file mode 100644 index 000000000..56c604028 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/PointToLineDistanceTestHaversineTest.php @@ -0,0 +1,157 @@ +haversine = new Haversine(); + $this->pointToLineDistance = new PointToLineDistance($this->haversine); + } + + public function testLineHasTheSameStartAndEndPoint(): void + { + $point = new Coordinate(52.5, 13.5); + + $line = new Line(new Coordinate(52.5, 13.1), new Coordinate(52.5, 13.1)); + + $this->assertEqualsWithDelta(27076, $this->pointToLineDistance->getDistance($point, $line), 1); + } + + public function testLinePoint1IsNearer(): void + { + $point = new Coordinate(52.45, 13.05); + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEquals( + $point->getDistance($linePoint1, $this->haversine), + $this->pointToLineDistance->getDistance($point, $line) + ); + } + + public function testPointIsSameLocationAsLinePoint1(): void + { + $point = new Coordinate(52.45, 13.05); + + $linePoint1 = new Coordinate(52.45, 13.05); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEquals(0, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testLinePoint2IsNearer(): void + { + $point = new Coordinate(52.6001, 13.1201); + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEqualsWithDelta( + $point->getDistance($linePoint2, $this->haversine), + $this->pointToLineDistance->getDistance($point, $line), + 0.001 + ); + } + + public function testPointIsSameLocationAsLinePoint2(): void + { + $point = new Coordinate(52.45, 13.05); + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.45, 13.05); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEquals(0, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testPointIsSameLocationAsLineMidPoint(): void + { + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $point = $line->getMidpoint(); + + $this->assertEquals(0, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testDistanceIsCalculatedToSomewhereOnLine(): void + { + $point = new Coordinate(52.04, 13.01); + + $linePoint1 = new Coordinate(52.0, 13.0); + $linePoint2 = new Coordinate(52.07, 13.02); + $line = new Line($linePoint1, $linePoint2); + + $pl1Distance = $point->getDistance($linePoint1, $this->haversine); + $pl2Distance = $point->getDistance($linePoint2, $this->haversine); + $plDistance = $this->pointToLineDistance->getDistance($point, $line); + + $this->assertLessThan($pl1Distance, $plDistance); + $this->assertLessThan($pl2Distance, $plDistance); + } + + public function testDistanceMatchesPerpendicularDistance(): void + { + $point = new Coordinate(52.04, 13.01); + + $linePoint1 = new Coordinate(52.0, 13.0); + $linePoint2 = new Coordinate(52.07, 13.02); + $line = new Line($linePoint1, $linePoint2); + + $pdCalculator = new PerpendicularDistance(); + + $perpendicularDistance = $pdCalculator->getPerpendicularDistance($point, $line); + $pointToLineDistance = $this->pointToLineDistance->getDistance($point, $line); + + // allowed delta is relatively large because the perpdendicular distance + // is calculated with a simple spherical model + $this->assertEqualsWithDelta($pointToLineDistance, $perpendicularDistance, 0.3); + } + + public function testPointBetweenMidpointAndPoint2(): void + { + $point = new Coordinate(52.0419763, 13.3061232); + + $linePoint1 = new Coordinate(52.0, 13.0); + $linePoint2 = new Coordinate(52.1, 13.5); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEqualsWithDelta(2068, $this->pointToLineDistance->getDistance($point, $line), 1); + } + + public function testPointToLineDistanceCaseA() + { + $line = new Line(new Coordinate(55.9857757, 13.5475307), new Coordinate(55.9869533, 13.5509295)); + $point0a = new Coordinate(55.9839105, 13.5465958); + + $this->assertEqualsWithDelta(215, $point0a->getDistance($line->getPoint1(), $this->haversine), 1); + + $this->assertEqualsWithDelta(215, $this->pointToLineDistance->getDistance($point0a, $line), 1); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/PointToLineDistanceTestVincentyTest.php b/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/PointToLineDistanceTestVincentyTest.php new file mode 100644 index 000000000..9c9833e37 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Location/Utility/PointToLineDistanceTestVincentyTest.php @@ -0,0 +1,158 @@ +vincenty = new Vincenty(); + $this->pointToLineDistance = new PointToLineDistance($this->vincenty); + } + + public function testLineHasTheSameStartAndEndPoint(): void + { + $point = new Coordinate(52.5, 13.5); + + $line = new Line(new Coordinate(52.5, 13.1), new Coordinate(52.5, 13.1)); + + $this->assertEquals(27164.059, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testLinePoint1IsNearer(): void + { + $point = new Coordinate(52.45, 13.05); + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEquals( + $point->getDistance($linePoint1, $this->vincenty), + $this->pointToLineDistance->getDistance($point, $line) + ); + } + + public function testPointIsSameLocationAsLinePoint1(): void + { + $point = new Coordinate(52.45, 13.05); + + $linePoint1 = new Coordinate(52.45, 13.05); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEquals(0, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testLinePoint2IsNearer(): void + { + $point = new Coordinate(52.6001, 13.1201); + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEqualsWithDelta( + $point->getDistance($linePoint2, $this->vincenty), + $this->pointToLineDistance->getDistance($point, $line), + 0.001 + ); + } + + public function testPointIsSameLocationAsLinePoint2(): void + { + $point = new Coordinate(52.45, 13.05); + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.45, 13.05); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEquals(0, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testPointIsSameLocationAsLineMidPoint(): void + { + + $linePoint1 = new Coordinate(52.5, 13.1); + $linePoint2 = new Coordinate(52.6, 13.12); + $line = new Line($linePoint1, $linePoint2); + + $point = $line->getMidpoint(); + + $this->assertEquals(0, $this->pointToLineDistance->getDistance($point, $line)); + } + + public function testDistanceIsCalculatedToSomewhereOnLine(): void + { + $point = new Coordinate(52.04, 13.01); + + $linePoint1 = new Coordinate(52.0, 13.0); + $linePoint2 = new Coordinate(52.07, 13.02); + $line = new Line($linePoint1, $linePoint2); + + $pl1Distance = $point->getDistance($linePoint1, $this->vincenty); + $pl2Distance = $point->getDistance($linePoint2, $this->vincenty); + $plDistance = $this->pointToLineDistance->getDistance($point, $line); + + $this->assertLessThan($pl1Distance, $plDistance); + $this->assertLessThan($pl2Distance, $plDistance); + } + + public function testDistanceMatchesPerpendicularDistance(): void + { + $point = new Coordinate(52.04, 13.01); + + $linePoint1 = new Coordinate(52.0, 13.0); + $linePoint2 = new Coordinate(52.07, 13.02); + $line = new Line($linePoint1, $linePoint2); + + $pdCalculator = new PerpendicularDistance(); + + $perpendicularDistance = $pdCalculator->getPerpendicularDistance($point, $line); + $pointToLineDistance = $this->pointToLineDistance->getDistance($point, $line); + + // allowed delta is relatively large because the perpdendicular distance + // is calculated with a simple spherical model + $this->assertEqualsWithDelta($pointToLineDistance, $perpendicularDistance, 0.3); + } + + public function testPointBetweenMidpointAndPoint2(): void + { + $point = new Coordinate(52.0419763, 13.3061232); + + $linePoint1 = new Coordinate(52.0, 13.0); + $linePoint2 = new Coordinate(52.1, 13.5); + $line = new Line($linePoint1, $linePoint2); + + $this->assertEqualsWithDelta(2069.9, $this->pointToLineDistance->getDistance($point, $line), 0.1); + } + + public function testPointToLineDistanceCaseA() + { + $line = new Line(new Coordinate(55.9857757, 13.5475307), new Coordinate(55.9869533, 13.5509295)); + $point0a = new Coordinate(55.9839105, 13.5465958); + + $this->assertEqualsWithDelta(215.636, $point0a->getDistance($line->getPoint1(), $this->vincenty), 0.1); + + $this->assertEqualsWithDelta(215.636, $this->pointToLineDistance->getDistance($point0a, $line), 0.1); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/15/Issue15Test.php b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/15/Issue15Test.php new file mode 100644 index 000000000..4c00a4510 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/15/Issue15Test.php @@ -0,0 +1,94 @@ +addPoint(new Coordinate($point[0], $point[1])); + } + + $processor = new SimplifyDouglasPeucker(2); + $simplified = $processor->simplify($polyline); + + $firstPoint = new Coordinate(20.6579781231, -103.422906054); + $lastPoint = new Coordinate(20.6610790881, -103.421889792); + + $this->assertEquals($firstPoint, $simplified->getPoints()[0]); + $this->assertEquals($lastPoint, $simplified->getPoints()[$simplified->getNumberOfPoints() - 1]); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/18/Issue18Test.php b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/18/Issue18Test.php new file mode 100644 index 000000000..c8634e893 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/18/Issue18Test.php @@ -0,0 +1,23 @@ +getDistance( + new Coordinate(0, 0), + new Coordinate(0, 0.1) + ); + + $this->assertIsFloat($distance); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/42/Issue42Test.php b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/42/Issue42Test.php new file mode 100644 index 000000000..3bb845ac8 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/42/Issue42Test.php @@ -0,0 +1,23 @@ +getDistance( + new Coordinate(45.306833, 5.887717), + new Coordinate(45.306833, 5.887733) + ); + + $this->assertEquals(1.255, $distance); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/68/Issue68Test.php b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/68/Issue68Test.php new file mode 100644 index 000000000..e2d1b3361 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/68/Issue68Test.php @@ -0,0 +1,22 @@ +assertEqualsWithDelta($expectedLatitude, $coordinates->getLat(), 0.00001); + $this->assertEqualsWithDelta($expectedLongitude, $coordinates->getLng(), 0.00001); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/92/Issue92Test.php b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/92/Issue92Test.php new file mode 100644 index 000000000..6fed9cc14 --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/Regression/Github/92/Issue92Test.php @@ -0,0 +1,68 @@ + 55.98467000751469413444283418357372283935546875, + 'lon' => 13.544430000324179985682349069975316524505615234375, + ]; + $ll2 = [ + 'lat' => 55.98461833972562118333371472544968128204345703125, + 'lon' => 13.54429500218709137016048771329224109649658203125, + ]; + $p = [ + 'lat' => 55.97609299999999876717993174679577350616455078125, + 'lon' => 13.5475989999999999469082467840053141117095947265625, + ]; + + $pointToLineDistanceCalculator = new PointToLineDistance(new Vincenty()); + + $dist = $pointToLineDistanceCalculator->getDistance( + new Coordinate($p['lat'], $p['lon']), + new Line( + new Coordinate($ll1['lat'], $ll1['lon']), + new Coordinate($ll2['lat'], $ll2['lon']) + ) + ); + + $this->assertEqualsWithDelta(971.37, $dist, 0.01); + } + + public function testForIssue92RoundedValues(): void + { + $ll1 = [ + 'lat' => 55.98467, + 'lon' => 13.54443, + ]; + $ll2 = [ + 'lat' => 55.98461, + 'lon' => 13.54429, + ]; + $p = [ + 'lat' => 55.97609, + 'lon' => 13.54759, + ]; + + $pointToLineDistanceCalculator = new PointToLineDistance(new Vincenty()); + + $dist = $pointToLineDistanceCalculator->getDistance( + new Coordinate($p['lat'], $p['lon']), + new Line( + new Coordinate($ll1['lat'], $ll1['lon']), + new Coordinate($ll2['lat'], $ll2['lon']) + ) + ); + + $this->assertEqualsWithDelta(970.74, $dist, 0.01); + } +} diff --git a/admin/vendor/mjaschen/phpgeo/tests/bootstrap.php b/admin/vendor/mjaschen/phpgeo/tests/bootstrap.php new file mode 100644 index 000000000..cf564ec7d --- /dev/null +++ b/admin/vendor/mjaschen/phpgeo/tests/bootstrap.php @@ -0,0 +1,3 @@ +