Adding elevation difference to the GPX simplification
This commit is contained in:
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user