diff --git a/inc/converter.php b/inc/converter.php index 9530ba9..fd3f356 100644 --- a/inc/converter.php +++ b/inc/converter.php @@ -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() { diff --git a/readme.md b/readme.md index 567f8aa..1ad6fd0 100644 --- a/readme.md +++ b/readme.md @@ -8,5 +8,4 @@ * import/export * Reset zoom on image closing (lightbox) * Fix fullscreen button on ios -* Fix lightbox portrait mode: push text under -* Simplify track when converting gpx to geojson \ No newline at end of file +* Fix lightbox portrait mode: push text under \ No newline at end of file