Adding elevation difference to the GPX simplification

This commit is contained in:
2019-11-24 13:26:23 +01:00
parent 5afb60da5d
commit 2a4fa8b2d0
2 changed files with 32 additions and 14 deletions

View File

@@ -108,7 +108,8 @@ class GeoJson extends Geo {
const EXT = '.geojson'; const EXT = '.geojson';
const MAX_FILESIZE = 2; //MB const MAX_FILESIZE = 2; //MB
const MAX_DEVIATION = 0.1; //10% const MAX_DEVIATION_FLAT = 0.1; //10%
const MAX_DEVIATION_ELEV = 0.1; //20%
public function __construct($sFileName) { public function __construct($sFileName) {
parent::__construct($sFileName); parent::__construct($sFileName);
@@ -136,6 +137,9 @@ class GeoJson extends Geo {
public function buildTracks($asTracks, $bSimplify=false) { public function buildTracks($asTracks, $bSimplify=false) {
$this->addNotice('Creating '.($bSimplify?'Simplified ':'').'GeoJson Tracks'); $this->addNotice('Creating '.($bSimplify?'Simplified ':'').'GeoJson Tracks');
$iGlobalInvalidPointCount = 0;
$iGlobalPointCount = 0;
$this->asTracks = array(); $this->asTracks = array();
foreach($asTracks as $asTrackProps) { foreach($asTracks as $asTrackProps) {
@@ -178,40 +182,55 @@ class GeoJson extends Geo {
$asTrackPoints = $asTrackProps['points']; $asTrackPoints = $asTrackProps['points'];
$iPointCount = count($asTrackPoints); $iPointCount = count($asTrackPoints);
$iInvalidPointCount = 0; $iInvalidPointCount = 0;
$asPrevPoint = array();
foreach($asTrackPoints as $iIndex=>$asPoint) { foreach($asTrackPoints as $iIndex=>$asPoint) {
if($bSimplify && $iIndex > 0 && $iIndex < ($iPointCount - 1)) { $asNextPoint = ($iIndex < ($iPointCount - 1))?$asTrackPoints[$iIndex + 1]:array();
if(!$this->isPointValid($asTrackPoints[$iIndex - 1], $asPoint, $asTrackPoints[$iIndex + 1])) { if($bSimplify && !empty($asPrevPoint) && !empty($asNextPoint)) {
if(!$this->isPointValid($asPrevPoint, $asPoint, $asNextPoint)) {
$iInvalidPointCount++; $iInvalidPointCount++;
continue; continue;
} }
} }
$asTrack['geometry']['coordinates'][] = array_values($asPoint); $asTrack['geometry']['coordinates'][] = array_values($asPoint);
$asPrevPoint = $asPoint;
} }
$this->asTracks[] = $asTrack; $this->asTracks[] = $asTrack;
$iGlobalInvalidPointCount += $iInvalidPointCount;
$iGlobalPointCount += $iPointCount;
if($iInvalidPointCount > 0) $this->addNotice('Removing '.$iInvalidPointCount.'/'.$iPointCount.' points ('.round($iInvalidPointCount / $iPointCount * 100, 1).'%) from '.$asTrackProps['name']); if($iInvalidPointCount > 0) $this->addNotice('Removing '.$iInvalidPointCount.'/'.$iPointCount.' points ('.round($iInvalidPointCount / $iPointCount * 100, 1).'%) from '.$asTrackProps['name']);
} }
if($bSimplify) $this->addNotice('Total: '.$iGlobalInvalidPointCount.'/'.$iGlobalPointCount.' points removed ('.round($iGlobalInvalidPointCount / $iGlobalPointCount * 100, 1).'%)');
} }
private function isPointValid($asPointA, $asPointO, $asPointB) { private function isPointValid($asPointA, $asPointO, $asPointB) {
/* A----O Calculate angle AO^OB /* A----O Calculate angle AO^OB
\ If angle is within [Pi - 10%; Pi + 10%], O can be discarded * \ If angle is within [Pi - 10%; Pi + 10%], O can be discarded
\ O is valid otherwise * \ O is valid otherwise
B * B
-> -> -> ->
Law of Cosines: angle = arccos(OA.OB / ||OA||.||OB||)
*/ */
//Path Turn Check -> -> -> ->
//Law of Cosines (vector): angle = arccos(OA.OB / ||OA||.||OB||)
$fVectorOA = array('lon'=>($asPointA['lon'] - $asPointO['lon']), 'lat'=> ($asPointA['lat'] - $asPointO['lat'])); $fVectorOA = array('lon'=>($asPointA['lon'] - $asPointO['lon']), 'lat'=> ($asPointA['lat'] - $asPointO['lat']));
$fVectorOB = array('lon'=>($asPointB['lon'] - $asPointO['lon']), 'lat'=> ($asPointB['lat'] - $asPointO['lat'])); $fVectorOB = array('lon'=>($asPointB['lon'] - $asPointO['lon']), 'lat'=> ($asPointB['lat'] - $asPointO['lat']));
$fVectorOAxOB = $fVectorOA['lon'] * $fVectorOB['lon'] + $fVectorOA['lat'] * $fVectorOB['lat'];
$fLengthOA = sqrt(pow($asPointA['lon'] - $asPointO['lon'], 2) + pow($asPointA['lat'] - $asPointO['lat'], 2)); $fLengthOA = sqrt(pow($asPointA['lon'] - $asPointO['lon'], 2) + pow($asPointA['lat'] - $asPointO['lat'], 2));
$fLengthOB = sqrt(pow($asPointO['lon'] - $asPointB['lon'], 2) + pow($asPointO['lat'] - $asPointB['lat'], 2)); $fLengthOB = sqrt(pow($asPointO['lon'] - $asPointB['lon'], 2) + pow($asPointO['lat'] - $asPointB['lat'], 2));
$fVectorOAxOB = $fVectorOA['lon'] * $fVectorOB['lon'] + $fVectorOA['lat'] * $fVectorOB['lat'];
$fAngleAOB = acos($fVectorOAxOB/($fLengthOA * $fLengthOB)); $fAngleAOB = acos($fVectorOAxOB/($fLengthOA * $fLengthOB));
return ($fAngleAOB <= (1 - self::MAX_DEVIATION) * M_PI || $fAngleAOB >= (1 + self::MAX_DEVIATION) * M_PI); //Elevation Check
//Law of Cosines: angle = arccos((OB² + AO² - AB²) / (2*OB*AO))
$fLengthAB = sqrt(pow($asPointB['ele'] - $asPointA['ele'], 2) + pow($fLengthOA + $fLengthOB, 2));
$fLengthAO = sqrt(pow($asPointO['ele'] - $asPointA['ele'], 2) + pow($fLengthOA, 2));
$fLengthOB = sqrt(pow($asPointB['ele'] - $asPointO['ele'], 2) + pow($fLengthOB, 2));
$fAngleAOBElev = acos((pow($fLengthOB, 2) + pow($fLengthAO, 2) - pow($fLengthAB, 2)) / (2 * $fLengthOB * $fLengthAO));
return ($fAngleAOB <= (1 - self::MAX_DEVIATION_FLAT) * M_PI || $fAngleAOB >= (1 + self::MAX_DEVIATION_FLAT) * M_PI ||
$fAngleAOBElev <= (1 - self::MAX_DEVIATION_ELEV) * M_PI || $fAngleAOBElev >= (1 + self::MAX_DEVIATION_ELEV) * M_PI);
} }
private function buildGeoJson() { private function buildGeoJson() {

View File

@@ -9,4 +9,3 @@
* Reset zoom on image closing (lightbox) * Reset zoom on image closing (lightbox)
* Fix fullscreen button on ios * Fix fullscreen button on ios
* Fix lightbox portrait mode: push text under * Fix lightbox portrait mode: push text under
* Simplify track when converting gpx to geojson