Adding elevation difference to the GPX simplification
This commit is contained in:
@@ -108,7 +108,8 @@ class GeoJson extends Geo {
|
||||
|
||||
const EXT = '.geojson';
|
||||
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) {
|
||||
parent::__construct($sFileName);
|
||||
@@ -136,6 +137,9 @@ class GeoJson extends Geo {
|
||||
public function buildTracks($asTracks, $bSimplify=false) {
|
||||
$this->addNotice('Creating '.($bSimplify?'Simplified ':'').'GeoJson Tracks');
|
||||
|
||||
$iGlobalInvalidPointCount = 0;
|
||||
$iGlobalPointCount = 0;
|
||||
|
||||
$this->asTracks = array();
|
||||
foreach($asTracks as $asTrackProps) {
|
||||
|
||||
@@ -178,40 +182,55 @@ class GeoJson extends Geo {
|
||||
$asTrackPoints = $asTrackProps['points'];
|
||||
$iPointCount = count($asTrackPoints);
|
||||
$iInvalidPointCount = 0;
|
||||
$asPrevPoint = array();
|
||||
foreach($asTrackPoints as $iIndex=>$asPoint) {
|
||||
if($bSimplify && $iIndex > 0 && $iIndex < ($iPointCount - 1)) {
|
||||
if(!$this->isPointValid($asTrackPoints[$iIndex - 1], $asPoint, $asTrackPoints[$iIndex + 1])) {
|
||||
$asNextPoint = ($iIndex < ($iPointCount - 1))?$asTrackPoints[$iIndex + 1]:array();
|
||||
if($bSimplify && !empty($asPrevPoint) && !empty($asNextPoint)) {
|
||||
if(!$this->isPointValid($asPrevPoint, $asPoint, $asNextPoint)) {
|
||||
$iInvalidPointCount++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$asTrack['geometry']['coordinates'][] = array_values($asPoint);
|
||||
$asPrevPoint = $asPoint;
|
||||
}
|
||||
$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($bSimplify) $this->addNotice('Total: '.$iGlobalInvalidPointCount.'/'.$iGlobalPointCount.' points removed ('.round($iGlobalInvalidPointCount / $iGlobalPointCount * 100, 1).'%)');
|
||||
}
|
||||
|
||||
private function isPointValid($asPointA, $asPointO, $asPointB) {
|
||||
/* A----O Calculate angle AO^OB
|
||||
\ If angle is within [Pi - 10%; Pi + 10%], O can be discarded
|
||||
\ O is valid otherwise
|
||||
B
|
||||
-> -> -> ->
|
||||
Law of Cosines: angle = arccos(OA.OB / ||OA||.||OB||)
|
||||
* \ If angle is within [Pi - 10%; Pi + 10%], O can be discarded
|
||||
* \ O is valid otherwise
|
||||
* B
|
||||
*/
|
||||
|
||||
//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']));
|
||||
$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));
|
||||
$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));
|
||||
|
||||
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() {
|
||||
|
||||
Reference in New Issue
Block a user