Skip to content

Commit

Permalink
Merge pull request #61 πŸ‘©πŸ»β€πŸ¦°
Browse files Browse the repository at this point in the history
* Real distance calculator

* Fixed real distance tests

* Merge branch 'master' into feature/real-distance

* Few text changes, year updates
  • Loading branch information
Sibyx authored Jul 30, 2022
1 parent b17febf commit aac01e5
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.2.0 : 2022-07-30

- **Feature**: [Real distance calculation #37](https://github.com/Sibyx/phpGPX/issues/37) (DistanceCalculator refactor)

## 1.1.3 : 2021-07-29

- **Fix**: [Fix negative duration #58](https://github.com/Sibyx/phpGPX/pull/58) by [@neronmoon](https://github.com/neronmoon)
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017 Jakub Dubec
Copyright (c) 2017-2022 Jakub Dubec

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ You can easily install phpGPX library with [composer](https://getcomposer.org/).
please use release candidates.

```
composer require sibyx/phpgpx:1.1.3
composer require sibyx/phpgpx:1.2.0
```

## Examples
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "sibyx/phpgpx",
"type": "library",
"version": "1.1.3",
"version": "1.2.0",
"description": "A simple PHP library for GPX import/export",
"minimum-stability": "stable",
"license": "MIT",
Expand Down
37 changes: 31 additions & 6 deletions src/phpGPX/Helpers/DistanceCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,56 @@
* DistanceCalculator.php
*
* @author Jens Hassler
* @author Jakub Dubec
* @since 07/2018
* @version 2.0
*/

namespace phpGPX\Helpers;

use phpGPX\Helpers\GeoHelper;
use phpGPX\Models\Point;
use phpGPX\phpGPX;

class DistanceCalculator
{
/**
* @var Point[]
*/
private $points;

/**
* DistanceCalculator constructor.
* @param Point[] $points
*/
public function __construct(array $points)
{
$this->points = $points;
}

public function getRawDistance()
{
return $this->calculate([GeoHelper::class, 'getRawDistance']);
}

public function getRealDistance()
{
return $this->calculate([GeoHelper::class, 'getRealDistance']);
}

/**
* @param Point[]|array $points
* @return float
*/
public static function calculate(array $points)
private function calculate($strategy)
{
$distance = 0;

$pointCount = count($points);
$pointCount = count($this->points);

$lastConsideredPoint = null;

for ($p = 0; $p < $pointCount; $p++) {
$curPoint = $points[$p];
$curPoint = $this->points[$p];

// skip the first point
if ($p === 0) {
Expand All @@ -36,11 +61,11 @@ public static function calculate(array $points)
}

// calculate the delta from current point to last considered point
$curPoint->difference = GeoHelper::getDistance($lastConsideredPoint, $curPoint);
$curPoint->difference = call_user_func($strategy, $lastConsideredPoint, $curPoint);

// if smoothing is applied we only consider points with a delta above the threshold (e.g. 2 meters)
if (phpGPX::$APPLY_DISTANCE_SMOOTHING) {
$differenceFromLastConsideredPoint = GeoHelper::getDistance($curPoint, $lastConsideredPoint);
$differenceFromLastConsideredPoint = call_user_func($strategy, $curPoint, $lastConsideredPoint);

if ($differenceFromLastConsideredPoint > phpGPX::$DISTANCE_SMOOTHING_THRESHOLD) {
$distance += $differenceFromLastConsideredPoint;
Expand Down
19 changes: 18 additions & 1 deletion src/phpGPX/Helpers/GeoHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ abstract class GeoHelper
* @param Point $point2
* @return float
*/
public static function getDistance(Point $point1, Point $point2)
public static function getRawDistance(Point $point1, Point $point2)
{
$latFrom = deg2rad($point1->latitude);
$lonFrom = deg2rad($point1->longitude);
Expand All @@ -38,4 +38,21 @@ public static function getDistance(Point $point1, Point $point2)

return $angle * self::EARTH_RADIUS;
}

/**
* Returns distance between two points including elevation gain/loss
* @param Point $point1
* @param Point $point2
* @return float
*/
public static function getRealDistance(Point $point1, Point $point2)
{
$distance = self::getRawDistance($point1, $point2);

$elevation1 = $point1->elevation != null ? $point1->elevation : 0;
$elevation2 = $point2->elevation != null ? $point2->elevation : 0;
$elevDiff = abs($elevation1 - $elevation2);

return sqrt(pow($distance, 2) + pow($elevDiff, 2));
}
}
4 changes: 3 additions & 1 deletion src/phpGPX/Models/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ public function recalculateStats()
list($this->stats->cumulativeElevationGain, $this->stats->cumulativeElevationLoss) =
ElevationGainLossCalculator::calculate($this->getPoints());

$this->stats->distance = DistanceCalculator::calculate($this->getPoints());
$calculator = new DistanceCalculator($this->getPoints());
$this->stats->distance = $calculator->getRawDistance();
$this->stats->realDistance = $calculator->getRealDistance();

for ($p = 0; $p < $pointCount; $p++) {
if ((phpGPX::$IGNORE_ELEVATION_0 === false || $this->points[$p]->elevation > 0) && $this->stats->minAltitude > $this->points[$p]->elevation) {
Expand Down
4 changes: 3 additions & 1 deletion src/phpGPX/Models/Segment.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ public function recalculateStats()
list($this->stats->cumulativeElevationGain, $this->stats->cumulativeElevationLoss) =
ElevationGainLossCalculator::calculate($this->getPoints());

$this->stats->distance = DistanceCalculator::calculate($this->getPoints());
$calculator = new DistanceCalculator($this->getPoints());
$this->stats->distance = $calculator->getRawDistance();
$this->stats->realDistance = $calculator->getRealDistance();

for ($i = 0; $i < $count; $i++) {
if ($this->stats->maxAltitude < $this->points[$i]->elevation) {
Expand Down
8 changes: 8 additions & 0 deletions src/phpGPX/Models/Stats.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class Stats implements Summarizable
*/
public $distance = 0;

/**
* Distance in meters (m) including elevation loss/gain
* @var float
*/
public $realDistance = 0;

/**
* Average speed in meters per second (m/s)
* @var float
Expand Down Expand Up @@ -82,6 +88,7 @@ class Stats implements Summarizable
public function reset()
{
$this->distance = null;
$this->realDistance = null;
$this->averageSpeed = null;
$this->averagePace = null;
$this->minAltitude = null;
Expand All @@ -100,6 +107,7 @@ public function toArray()
{
return [
'distance' => (float)$this->distance,
'realDistance' => (float)$this->realDistance,
'avgSpeed' => (float)$this->averageSpeed,
'avgPace' => (float)$this->averagePace,
'minAltitude' => (float)$this->minAltitude,
Expand Down
1 change: 1 addition & 0 deletions src/phpGPX/Models/Track.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ public function recalculateStats()
$this->stats->cumulativeElevationLoss += $this->segments[$s]->stats->cumulativeElevationLoss;

$this->stats->distance += $this->segments[$s]->stats->distance;
$this->stats->realDistance += $this->segments[$s]->stats->realDistance;

if ($this->stats->minAltitude === null) {
$this->stats->minAltitude = $this->segments[$s]->stats->minAltitude;
Expand Down
4 changes: 4 additions & 0 deletions tests/LoadFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ private function createExpectedArray()
],
'stats' => [
'distance' => 2.314424561683643,
'realDistance' => 2.314424561683643,
'avgSpeed' => 0.2571582846315159,
'avgPace' => 3888.6555859279733,
'minAltitude' => 0.0,
Expand All @@ -98,6 +99,7 @@ private function createExpectedArray()
],
'stats' => [
'distance' => 2.314424561683643,
'realDistance' => 2.314424561683643,
'avgSpeed' => 0.2571582846315159,
'avgPace' => 3888.6555859279733,
'minAltitude' => 0.0,
Expand Down Expand Up @@ -141,6 +143,7 @@ private function createExpectedArray()
],
'stats' => [
'distance' => 7.062730302497254,
'realDistance' => 7.062730302497254,
'avgSpeed' => 2.354243434165751,
'avgPace' => 424.7649098167112,
'minAltitude' => 0.0,
Expand All @@ -155,6 +158,7 @@ private function createExpectedArray()
],
'stats' => [
'distance' => 7.062730302497254,
'realDistance' => 7.062730302497254,
'avgSpeed' => 2.354243434165751,
'avgPace' => 424.7649098167112,
'minAltitude' => 0.0,
Expand Down
2 changes: 2 additions & 0 deletions tests/LoadRouteFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ private function createExpectedArray()
],
'stats' => [
'distance' => 132.0785853,
'realDistance' => 132.0785853,
'avgSpeed' => 0.0,
'avgPace' => 0.0,
'minAltitude' => 0.0,
Expand Down Expand Up @@ -133,6 +134,7 @@ private function createExpectedArray()
],
'stats' => [
'distance' => 132.0785853,
'realDistance' => 132.0785853,
'avgSpeed' => 0.0,
'avgPace' => 0.0,
'minAltitude' => 0.0,
Expand Down
32 changes: 31 additions & 1 deletion tests/UnitTests/phpGPX/Helpers/GeoHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,39 @@ public function testGetDistance()

$this->assertEquals(
856.97,
GeoHelper::getDistance($point1, $point2),
GeoHelper::getRawDistance($point1, $point2),
"Invalid distance between two points!",
1
);
}

/**
* @link http://cosinekitty.com/compass.html
*/
public function testRealDistance()
{
$point1 = new Point(Point::WAYPOINT);
$point1->latitude = 48.1573923225717;
$point1->longitude = 17.0547121910204;
$point1->elevation = 100;

$point2 = new Point(Point::WAYPOINT);
$point2->latitude = 48.1644916381763;
$point2->longitude = 17.0591753907502;
$point2->elevation = 200;

$this->assertEquals(
856.97,
GeoHelper::getRawDistance($point1, $point2),
"Invalid distance between two points!",
1
);

$this->assertEquals(
862,
GeoHelper::getRealDistance($point1, $point2),
"Invalid real distance between two points!",
1
);
}
}

0 comments on commit aac01e5

Please sign in to comment.