diff --git a/.gitignore b/.gitignore index 4968059..a592d4b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,9 @@ public/photos/big/*.jpeg public/photos/big/*.png public/photos/big/*.gif +tracks/*.gpx +tracks/*.kml +tracks/*.kmz + logs/* .idea diff --git a/classes/Geo.php b/classes/Geo.php new file mode 100644 index 0000000..7967b98 --- /dev/null +++ b/classes/Geo.php @@ -0,0 +1,26 @@ + 1000 ? round($distance/1000, 2).'км' : round($distance).'м'; + } +} diff --git a/classes/Kml.php b/classes/Kml.php new file mode 100644 index 0000000..83171e2 --- /dev/null +++ b/classes/Kml.php @@ -0,0 +1,171 @@ +getKmzContent($path) : file_get_contents($path); + $xml = str_replace(array('kml = new DOMDocument; + $this->kml->loadXML($xml); + + foreach ($this->get($this->kml, 'Placemark') as $placemark) { + if ($this->has($placemark, 'Point')) { + $this->waypoints[] = array( + 'name' => trim($this->getValue($placemark, 'name')), + 'description' => trim($this->getValue($placemark, 'description')), + 'when' => date('c', strtotime($this->getValue($placemark, 'when'))), + 'latlng' => $this->getCoords($placemark)[0], + ); + } + + if ($this->has($placemark, 'LineString')) { + $this->tracks[] = array( + 'name' => trim($this->getValue($placemark, 'name')), + 'description' => trim($this->getValue($placemark, 'description')), + 'latlng' => $this->getCoords($placemark), + ); + } + + if ($this->has($placemark, 'gxMultiTrack')) { + $this->tracks = $this->getTracksGX($placemark); + } + }; + } + + public function getName() + { + return $this->getValue($this->kml, 'name') ? strval($this->getValue($this->kml, 'name')) : 'Track KML'; + } + + public function getDescription() + { + return $this->getValue($this->kml, 'description') ? strval($this->getValue($this->kml, 'description')) : ''; + } + + public function getTime() + { + return $this->getValue($this->kml, 'when') ? date('c', strtotime($this->getValue($this->kml, 'when'))) : date('c'); + } + + public function getWaypoints() + { + return $this->waypoints; + } + + public function getTracks() + { + return $this->tracks; + } + + private function has($src, $tagName) + { + return $this->get($src, $tagName)->length > 0; + } + + private function get($src, $tagName) + { + return $src->getElementsByTagName($tagName); + } + + private function getValue($src, $tagName) + { + foreach ($src->getElementsByTagName($tagName) AS $value) { + return $value->nodeValue; + } + } + + private function getCoords($src) + { + foreach ($src->getElementsByTagName('coordinates') AS $value) { + $result = array(); + $coords = $value->nodeValue; + $coords = str_replace(array(" ", "\n", "\r", "\t"), ' ', $coords); + + // multi-space + $pr = '(\s{2,})'; + $rep = ' '; + $coords = preg_replace($pr, $rep, $coords); + + $coords = explode(' ', trim($coords)); + + foreach ($coords as $coord) { + $tmp = explode(',', $coord); + $result[] = array( + 'lat' => $tmp[1], + 'lng' => $tmp[0], + 'alt' => $tmp[2], + ); + } + + return $result; + } + + return array(); + } + + private function getTracksGX($placemark) + { + $result = array(); + foreach ($placemark->getElementsByTagName('gxTrack') AS $gxTrack) { + $track = array(); + foreach ($gxTrack->getElementsByTagName('gxcoord') AS $value) { + $coords = $value->nodeValue; + $coords = str_replace(array(" ", "\n", "\r", "\t"), ' ', $coords); + + // multi-space + $pr = '(\s{2,})'; + $rep = ' '; + $coords = preg_replace($pr, $rep, $coords); + + $tmp = explode(' ', trim($coords)); + + $track[] = array( + 'lat' => $tmp[1], + 'lng' => $tmp[0], + 'alt' => $tmp[2], + ); + } + + $result[] = array( + 'name' => '', + 'description' => '', + 'latlng' => $track, + ); + } + + return $result; + } + + private function getKmzContent($path) + { + $zip = zip_open($path); + if (!$zip) { + App::error404(); + } + + $zip_entry = zip_read($zip); + + if (zip_entry_name($zip_entry) != 'doc.kml') { + App::error404(); + } + + + if (zip_entry_open($zip, $zip_entry, "r")) { + $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); + zip_entry_close($zip_entry); + zip_close($zip); + + return $buf; + } + + App::error404(); + } + +} diff --git a/classes/Model.php b/classes/Model.php index 8796920..83250b3 100644 --- a/classes/Model.php +++ b/classes/Model.php @@ -204,30 +204,9 @@ abstract class Model * @param array $values - ассоциативный массив соо значениями. * @return object - id добавленной записи или false. */ - function add2($values) - { - $values = $this->_vals_; - unset($values[$this->_primaryKey_]); - - $q = array(); - foreach ($values as $val) { - $q[] = '?'; - } - - var_dump('INSERT INTO `' . $this->_tableName_ . '` (`' . implode('`, `', array_keys($values)) . '`) VALUES (' . implode(', ', array_values($q)) . ') '); - die; - $res = App::DB()->prepare_query('INSERT INTO `' . $this->_tableName_ . '` (`' . implode('`, `', array_keys($values)) . '`) VALUES (' . implode(', ', array_values($q)) . ') ', self::arrayWithTypes($values)); - - if ($res) { - throw new Exception('MySQL error #' . $res->errno . ' - ' . $res->error); - } - - return $this->getByPK(App::DB()->insert_id); - } - function add($values) { - $request = App::DB()->prepare('INSERT INTO ' . $this->_tableName_ . ' (' . implode(',', array_keys($values)) . ') values (:' . implode(', :', array_keys($values)) . ')'); + $request = App::DB()->prepare('INSERT INTO `' . $this->_tableName_ . '` (`' . implode('`, `', array_keys($values)) . '`) values (:' . implode(', :', array_keys($values)) . ')'); if ($request->execute((array) $values)) { return $this->getByPK(App::DB()->lastInsertId()); } else { diff --git a/controllers/EdittrackController.php b/controllers/EdittrackController.php new file mode 100644 index 0000000..145af46 --- /dev/null +++ b/controllers/EdittrackController.php @@ -0,0 +1,113 @@ +id) { + App::redirect('/'); + } + } + + function actionTrip() + { + $id = intval(App::getParam('id')); + $trip = Trips::model()->getByPK($id); + + if (empty($_POST['name']) || $trip->isEmpty() || $trip->owner != App::$user->id) { + App::error404(); + } + + $trip->name = trim($_POST['name']); + $trip->description = trim($_POST['description']); + $trip->status = ($_POST['isPublic'] == 'true') ? Trips::STATUS_PUBLIC : Trips::STATUS_PRIVATE; + $trip->json = ''; + $trip->save(); + } + + function actionTrack() + { + $id = intval(App::getParam('id')); + + $track = Tracks::model()->getByPK($id); + if (empty($_POST['name']) || $track->isEmpty()) { + App::error404(); + } + + $trip = Trips::model()->getByPK($track->tripId); + if ($trip->isEmpty() || $trip->owner != App::$user->id) { + App::error404(); + } + + $track->name = trim($_POST['name']); + $track->description = trim($_POST['description']); + $track->save(); + + $trip->json = ''; + $trip->save(); + } + + function actionDeletetrack() + { + $id = intval(App::getParam('id')); + + $track = Tracks::model()->getByPK($id); + if ($track->isEmpty()) { + App::error404(); + } + + $trip = Trips::model()->getByPK($track->tripId); + if ($trip->isEmpty() || $trip->owner != App::$user->id) { + App::error404(); + } + + $track->delete($id); + + $trip->json = ''; + $trip->save(); + + App::redirect('/tracks/edit/id/'.$trip->id); + } + + function actionWaypoint() + { + $id = intval(App::getParam('id')); + + $waypoint = WayPoints::model()->getByPK($id); + if (empty($_POST['name']) || $waypoint->isEmpty()) { + App::error404(); + } + + $trip = Trips::model()->getByPK($waypoint->tripId); + if ($trip->isEmpty() || $trip->owner != App::$user->id) { + App::error404(); + } + + $waypoint->name = trim($_POST['name']); + $waypoint->description = trim($_POST['description']); + $waypoint->save(); + } + + function actionDeletewaypoint() + { + $id = intval(App::getParam('id')); + + $waypoint = WayPoints::model()->getByPK($id); + if ($waypoint->isEmpty()) { + App::error404(); + } + + $trip = Trips::model()->getByPK($waypoint->tripId); + if ($trip->isEmpty() || $trip->owner != App::$user->id) { + App::error404(); + } + + $waypoint->delete($id); + + $trip->json = ''; + $trip->save(); + + App::redirect('/tracks/edit/id/'.$trip->id); + } +} \ No newline at end of file diff --git a/controllers/IndexController.php b/controllers/IndexController.php index 01d5b24..6e19e0e 100644 --- a/controllers/IndexController.php +++ b/controllers/IndexController.php @@ -28,6 +28,7 @@ class IndexController extends Controller self::addScript('/js/navigation.js?ver=' . App::getConfig('version')); self::addScript('/js/map.js?ver=' . App::getConfig('version')); self::addScript('/js/fotorama.js'); + self::addScript('/js/tracks.js?ver=' . App::getConfig('version')); // self::addStyle('/css/style.css?ver=' . App::getConfig('version')); self::addStyle('/css/leaflet.css'); @@ -40,12 +41,12 @@ class IndexController extends Controller $category = Category::model()->getAll(array('order' => 'ord ASC')); $categoryArray = Category::model()->getAll(array('order' => 'ord ASC', 'asArray' => true)); - $routes = array(); - $favorites = array(); + $routes = $favorites = $tracks = array(); if (App::$user && App::$user->id) { self::addVar('user', App::$user->id); $routes = Route::model()->getByAuthor(App::$user->id); $favorites = Favorite::model()->getAllMy(); + $tracks = Trips::model()->getAll(array('where' => '`owner` = ?'), array(App::$user->id)); } else { self::addVar('user', '0'); } @@ -93,6 +94,7 @@ class IndexController extends Controller 'user' => App::$user, 'routes' => $routes, 'favorites' => $favorites, + 'tracks' => $tracks, 'og' => $og, )); } diff --git a/controllers/JsonController.php b/controllers/JsonController.php index 6535df9..4519f28 100644 --- a/controllers/JsonController.php +++ b/controllers/JsonController.php @@ -577,4 +577,200 @@ class JsonController extends Controller )); } + static function actionTrack() + { + $id = intval(App::getParam('id')); + + if (!$id) { + App::error404(); + } + + $trip = Trips::model()->getByPK($id); + + if ($trip->isEmpty() || ($trip->status != Trips::STATUS_PUBLIC && $trip->owner != App::$user->id)) { + App::error404(); + } + + if ($trip->json) { + header('Content-Type: application/json'); + print $trip->json; + die; + } + + $res = array( + 'name' => $trip->name, + 'time' => $trip->createdAt, + ); + + $resWayPoints = array(); + $resTracks = array(); + $resLatlngs = array(); + + + $wayPoints = WayPoints::model()->getAll(array('where' => '`tripId` = ?'), array($trip->id)); + if ($wayPoints) { + foreach ($wayPoints as $block) { + $resWayPoints[] = array( + 'lat' => floatval($block->lat), + 'lng' => floatval($block->lng), + 'time' => strtotime($block->createdAt), + 'name' => (string) $block->name, + 'description' => nl2br($block->description), + ); + } + } + + + $tracks = Tracks::model()->getAll(array('where' => '`tripId` = ?'), array($trip->id)); + if ($tracks) { + foreach ($tracks as $track) { + $resLatlngs = array(); + $trackPoints = TrackPoints::model()->getAll(array('where' => '`trackId` = ?'), array($track->id)); + if ($trackPoints) { + foreach ($trackPoints as $trackPoint) { + $resLatlngs[] = array( + 'lat' => $trackPoint->lat, + 'lng' => $trackPoint->lng, + ); + } + } + + $resTracks[] = array( + 'name' => (string) $track->name, + 'length' => 0, + 'latlngs' => $resLatlngs, + ); + } + + } + + $res['wayPoints'] = $resWayPoints; + $res['tracks'] = $resTracks; + + + $json = self::renderPartial('json.php', $res, TRUE); + + $trip->json = $json; + $trip->save(); + + header('Content-Type: application/json'); + print $json; + die; + } + + + static function actionSimpletrack() + { + $id = intval(App::getParam('id')); + + if (!$id) { + App::error404(); + } + + $trip = Trips::model()->getByPK($id); + + if ($trip->isEmpty() || ($trip->status != Trips::STATUS_PUBLIC && $trip->owner != App::$user->id)) { + App::error404(); + } + + $res = array( + 'name' => $trip->name, + 'time' => $trip->createdAt, + ); + + $resWayPoints = array(); + $resTracks = array(); + $resLatlngs = array(); + $totCnt = 0; + + + $wayPoints = WayPoints::model()->getAll(array('where' => '`tripId` = ?'), array($trip->id)); + if ($wayPoints) { + foreach ($wayPoints as $block) { + $resWayPoints[] = array( + 'lat' => floatval($block->lat), + 'lng' => floatval($block->lng), + 'time' => strtotime($block->createdAt), + 'name' => (string) $block->name, + 'description' => nl2br($block->description), + ); + } + } + + + $tracks = Tracks::model()->getAll(array('where' => '`tripId` = ?'), array($trip->id)); + if ($tracks) { + foreach ($tracks as $track) { + $resLatlngs = array(); + $trackPoints = TrackPoints::model()->getAll(array('where' => '`trackId` = ?', 'noKeys' => TRUE), array($track->id)); + if ($trackPoints) { + for ($index = 0; $index < count($trackPoints); $index++) { + + $trackPoint = $trackPoints[$index]; + + if ($index > 2 && $index < count($trackPoints)-2) { + + $nextPoint = $trackPoints[$index+1]; + $nextPoint = array( + 'lat' => $nextPoint->lat, + 'lng' => $nextPoint->lng, + ); + + $distance1 = Geo::distance($prevPoint, array('lat' => $trackPoint->lat, 'lng' => $trackPoint->lng)); + + if ($distance1 < 30) { + continue; + } + +// $distance2 = Geo::distance($nextPoint, array('lat' => $trackPoint->lat, 'lng' => $trackPoint->lng)); +// $distance3 = Geo::distance($prevPoint, $nextPoint); +// +// +// if (($distance3 / ($distance1+$distance2)) > 0.982) { +// continue; +// } + } + + $prevPoint = $trackPoints[$index]; + $prevPoint = array( + 'lat' => $prevPoint->lat, + 'lng' => $prevPoint->lng, + ); + + + $resLatlngs[] = array( + 'lat' => $trackPoint->lat, + 'lng' => $trackPoint->lng, + ); + } +// die; + } + + $totCnt += count($resLatlngs); + $resTracks[] = array( + 'name' => (string) $track->name, + 'length' => 0, + 'latlngs' => $resLatlngs, + 'points' => count($resLatlngs), + ); + } + + } + + $res['wayPoints'] = $resWayPoints; + $res['tracks'] = $resTracks; + $res['totCnt'] = $totCnt; + + + $json = self::renderPartial('json.php', $res, TRUE); + + $trip->json = $json; + $trip->save(); + + header('Content-Type: application/json'); + print $json; + die; + } + + } diff --git a/controllers/TracksController.php b/controllers/TracksController.php new file mode 100644 index 0000000..f65b33f --- /dev/null +++ b/controllers/TracksController.php @@ -0,0 +1,340 @@ +id) { + App::redirect('/'); + } + + self::$layout = 'layouts/page.php'; + self::addStyle('/css/style.css?ver=' . App::getConfig('version')); + self::addStyle('/css/pageStyle.css?ver=' . App::getConfig('version')); + self::addScript('/js/jquery-2.1.0.min.js'); + self::addScript('/js/jquery-ui-1.10.4.custom.min.js'); + self::addScript('/js/bootstrap.min.js'); + self::addStyle('/css/bootstrap.min.css'); + self::addStyle('/css/bootstrap-theme.min.css'); + } + + function actionIndex() + { + $trips = Trips::model()->getAll(array('where' => '`owner` = ?'), array(App::$user->id)); + + self::render('/tracks/index.php', array( + 'trips' => $trips, + )); + } + + function actionEdit() + { + $id = intval(App::getParam('id')); + + if (!$id) { + App::error404(); + } + + $trip = Trips::model()->getByPK($id); + + if ($trip->isEmpty() || $trip->owner != App::$user->id) { + App::error404(); + } + + self::render('/tracks/edit.php', array( + 'trip' => $trip, + 'tracks' => Tracks::model()->getAll(array('where' => '`tripId` = ' . $trip->id)), + 'waypoints' => WayPoints::model()->getAll(array('where' => '`tripId` = ' . $trip->id)), + )); + } + + + function actionFiles() + { + $files = TrackFiles::model()->getAll(array('where' => '`owner` = :owner'), array('owner' => App::$user->id)); + + self::render('/tracks/files.php', array( + 'files' => $files, + )); + } + + function actionUploadfile() + { + $temp = pathinfo($_FILES['file']['name']); + $filename = $_FILES['file']['name']; + $extension = strtolower($temp['extension']); + $uploaddir = App::getBasedir() . 'tracks/'; + + $supportedExtensions = array(TrackFiles::FORMAT_GPX, TrackFiles::FORMAT_KML, TrackFiles::FORMAT_KMZ); + + if (!in_array(strtoupper($extension), $supportedExtensions)) { + App::error404('Неизвестный тип'); + } + + $tmp = TrackFiles::model()->add(array( + 'owner' => App::$user->id, + 'name' => 'Трек ' . date('d-m-Y H:i:s'), + 'filename' => $filename, + 'format' => strtoupper($extension), + 'createdAt' => date('c'), + )); + + $newName = 'track' . $tmp->id . '.' . $extension; + if (!move_uploaded_file($_FILES['file']['tmp_name'], $uploaddir . $newName)) { + App::error404(); + } + + App::redirect('/tracks/import/id/' . $tmp->id); + } + + function actionGetFile() + { + $id = intval(App::getParam('id')); + + if (!$id) { + App::error404(); + } + + $trackFile = TrackFiles::model()->getByPK($id); + + if ($trackFile->isEmpty() || $trackFile->owner != App::$user->id) { + App::error404(); + } + + self::renderPartial('file.php', array( + 'filePath' => App::getBasedir() . 'tracks/track' . $id . '.' . strtolower($trackFile->format), + 'fileName' => $trackFile->filename, + )); + } + + function actionImport() + { + $id = (int) App::getParam('id'); + + if (!$id) { + App::error404(); + } + + $trackFile = TrackFiles::model()->getByPK($id); + + if ($trackFile->isEmpty() || $trackFile->owner != App::$user->id) { + App::error404(); + } + + switch ($trackFile->format) { + case TrackFiles::FORMAT_GPX: + self::importGpx($trackFile); + break; + case TrackFiles::FORMAT_KML: + case TrackFiles::FORMAT_KMZ: + self::importKml($trackFile); + break; + default: + App::error404(); + break; + } + + App::redirect('/tracks'); + } + + private static function importGpx($trackFile) + { + $gpxObject = simplexml_load_file(App::getBasedir() . 'tracks/track' . $trackFile->id . '.' . strtolower($trackFile->format)); + + $trip = Trips::model()->add( + array( + 'name' => isset($gpxObject->metadata->name) ? (string) $gpxObject->metadata->name : 'Track', + 'createdAt' => isset($gpxObject->metadata->time) ? $gpxObject->metadata->time : date('c'), + 'owner' => App::$user->id, + 'distance' => 0, + 'description' => 'Трек создан ' . date('d-m-Y H:i') . ' из файла ' . $trackFile->filename, + 'status' => Trips::STATUS_PRIVATE, + ) + ); + + $distance = 0; + $wayPoints = array(); + $tracks = array(); + $latlngs = array(); + $tracksCounter = 1; + $tracksCount = $tptCount = $wptCount = 0; + + foreach ($gpxObject as $key => $block) { + if ($key == 'wpt') { + if (empty($block)) { + continue; + } + + $wayPoint = WayPoints::model()->add( + array( + 'tripId' => $trip->id, + 'lat' => floatval($block['lat']), + 'lng' => floatval($block['lon']), + 'alt' => 0, + 'speed' => 0, + 'createdAt' => $block->time, + 'name' => (string) $block->name, + 'description' => (string) $block->desc, + ) + ); + + $wptCount++; + } + + if ($key == 'trk') { + if (empty($block->trkseg)) { + continue; + } + + foreach ($block->trkseg as $trkpt) { + if ($trkpt) { + $track = Tracks::model()->add( + array( + 'tripId' => $trip->id, + 'name' => (string) $block->name ? (string) $block->name : 'Фрагмент трека №' . $tracksCounter, + 'distance' => 0, + 'description' => '', + ) + ); + $distanceTmp = 0; + $prevPoint = array(); + $tracksCounter++; + $trackPoints = array(); + + foreach ($trkpt as $tpt) { + $trackPoint = TrackPoints::model()->add( + array( + 'trackId' => $track->id, + 'lat' => floatval($tpt['lat']), + 'lng' => floatval($tpt['lon']), + 'alt' => isset($tpt->ele) ? floatval($tpt->ele) : 0, + 'createdAt' => isset($tpt->time) ? $tpt->time : date('c'), + 'speed' => 0, + ) + ); + + if ($prevPoint) { + $distanceTmp += Geo::distance($prevPoint, array('lat' => floatval($tpt['lat']), 'lng' => floatval($tpt['lon']))); + } + + $prevPoint = array( + 'lat' => floatval($tpt['lat']), + 'lng' => floatval($tpt['lon']), + ); + $tptCount++; + } + + $distance += $distanceTmp; + $track->distance = $distanceTmp; + $track->save(); + } + } + $tracksCount++; + } + } + + $trip->distance = $distance; + $trip->save(); + + $trackFile->tracksCount = $tracksCount; + $trackFile->tptCount = $tptCount; + $trackFile->wptCount = $wptCount; + $trackFile->distance = $distance; + $trackFile->save(); + } + + private static function importKml($trackFile) + { + $kml = new Kml(App::getBasedir() . 'tracks/track' . $trackFile->id . '.' . strtolower($trackFile->format)); + + + $trip = Trips::model()->add( + array( + 'name' => $kml->getName(), + 'createdAt' => $kml->getTime(), + 'owner' => App::$user->id, + 'distance' => 0, + 'description' => 'Трек создан ' . date('d-m-Y H:i') . ' из файла ' . $trackFile->filename, + 'status' => Trips::STATUS_PRIVATE, + ) + ); + + $distance = 0; + $tracksCounter = 1; + $tracksCount = $tptCount = $wptCount = 0; + + foreach ($kml->getWaypoints() as $wpt) { + $wayPoint = WayPoints::model()->add( + array( + 'tripId' => $trip->id, + 'lat' => floatval($wpt['latlng']['lat']), + 'lng' => floatval($wpt['latlng']['lng']), + 'alt' => floatval($wpt['latlng']['alt']), + 'speed' => 0, + 'createdAt' => $wpt['when'], + 'name' => (string) $wpt['name'], + 'description' => (string) $wpt['description'], + ) + ); + + $wptCount++; + } + + foreach ($kml->getTracks() as $trackPart) { + if ($trackPart) { + $track = Tracks::model()->add( + array( + 'tripId' => $trip->id, + 'name' => $trackPart['name'] ? $trackPart['name'] : 'Фрагмент трека №' . $tracksCounter, + 'distance' => 0, + 'description' => $trackPart['description'], + ) + ); + + $distanceTmp = 0; + $prevPoint = array(); + $tracksCounter++; + $trackPoints = array(); + + foreach ($trackPart['latlng'] as $tpt) { + $trackPoint = TrackPoints::model()->add( + array( + 'trackId' => $track->id, + 'lat' => floatval($tpt['lat']), + 'lng' => floatval($tpt['lng']), + 'alt' => floatval($tpt['alt']), + 'createdAt' => 0, + 'speed' => 0, + ) + ); + + if ($prevPoint) { + $distanceTmp += Geo::distance($prevPoint, array('lat' => floatval($tpt['lat']), 'lng' => floatval($tpt['lng']))); + } + + $prevPoint = array( + 'lat' => floatval($tpt['lat']), + 'lng' => floatval($tpt['lng']), + ); + $tptCount++; + } + + $distance += $distanceTmp; + $track->distance = $distanceTmp; + $track->save(); + } + } + + + $trip->distance = $distance; + $trip->save(); + + $trackFile->tracksCount = count($kml->getTracks()); + $trackFile->tptCount = $tptCount; + $trackFile->wptCount = $wptCount; + $trackFile->distance = $distance; + $trackFile->save(); + } + +} diff --git a/models/TrackFiles.php b/models/TrackFiles.php new file mode 100644 index 0000000..889520b --- /dev/null +++ b/models/TrackFiles.php @@ -0,0 +1,21 @@ +_tableName_ = 'trackFiles'; + parent::__construct($fromArray); + } + + static function model() + { + return new self(); + } + +} diff --git a/models/TrackPoints.php b/models/TrackPoints.php new file mode 100644 index 0000000..6841536 --- /dev/null +++ b/models/TrackPoints.php @@ -0,0 +1,17 @@ +_tableName_ = 'trackPoints'; + parent::__construct($fromArray); + } + + static function model() + { + return new self(); + } + +} diff --git a/models/Tracks.php b/models/Tracks.php new file mode 100644 index 0000000..05fc827 --- /dev/null +++ b/models/Tracks.php @@ -0,0 +1,21 @@ +_tableName_ = 'tracks'; + parent::__construct($fromArray); + } + + static function model() + { + return new self(); + } + + function distance() + { + return Geo::formatedDistance($this->distance); + } +} diff --git a/models/Trips.php b/models/Trips.php new file mode 100644 index 0000000..ae2b4ae --- /dev/null +++ b/models/Trips.php @@ -0,0 +1,25 @@ +_tableName_ = 'trips'; + parent::__construct($fromArray); + } + + static function model() + { + return new self(); + } + + function distance() + { + return Geo::formatedDistance($this->distance); + } +} diff --git a/models/WayPoints.php b/models/WayPoints.php new file mode 100644 index 0000000..1e1ac2e --- /dev/null +++ b/models/WayPoints.php @@ -0,0 +1,17 @@ +_tableName_ = 'wayPoints'; + parent::__construct($fromArray); + } + + static function model() + { + return new self(); + } + +} diff --git a/public/ico/marker.png b/public/ico/marker.png new file mode 100644 index 0000000..4503353 Binary files /dev/null and b/public/ico/marker.png differ diff --git a/public/js/map.js b/public/js/map.js index b9e49cf..8c1b2bd 100644 --- a/public/js/map.js +++ b/public/js/map.js @@ -37,6 +37,13 @@ categories.simplepoint = L.icon({ popupAnchor: [7, 7] }); +categories.marker = L.icon({ + iconUrl: '/ico/marker.png', + iconSize: [32, 37], + iconAnchor: [16, 37], + popupAnchor: [0, 1] +}); + // ----------------------------------------------------------------------------- if (pointLat == pointLng) { @@ -234,6 +241,10 @@ function initPoints(useBounds) .setContent('Координаты: N°' + getURLParameter('lat').substring(0,8) + ' E°' + getURLParameter('lng').substring(0,8)) .openOn(myMap); } + } else if (getURLParameter('track') != 'null') + { + showTrack(getURLParameter('track')) + $('#trackShowHide' + getURLParameter('track')).prop('checked', true); } } }); @@ -256,12 +267,13 @@ function loadPointsInBounds() bounds: bounds }, success: function (data) { - for(var i=0; i < data.length; i++) { - if (typeof points[data[i].id] == 'undefined') { - markers.addLayer(constructPoint(data[i])); + if (typeof (data) != 'undefined' && data.length > 0) { + for(var i=0; i < data.length; i++) { + if (typeof points[data[i].id] == 'undefined') { + markers.addLayer(constructPoint(data[i])); + } } } - myMap.addLayer(markers); } }); diff --git a/public/js/tracks.js b/public/js/tracks.js new file mode 100644 index 0000000..0dac8e7 --- /dev/null +++ b/public/js/tracks.js @@ -0,0 +1,118 @@ +var trips = new Object; + +function showHideTrack(id) +{ + if($('#trackShowHide'+id).prop('checked')) { + showTrack(id) + } else { + hideTrack(id) + } +} + +function showTrack(id) +{ + if (typeof (trips[id]) == 'undefined') { + loadTrack(id) + } else { + if (trips[id].status != 'show') { + trips[id].addTo(myMap) + trips[id].status = 'show'; + } + + myMap.fitBounds(trips[id].getBounds()); + return true; + } +} + +function hideTrack(id) +{ + if (typeof (trips[id]) == 'undefined') { + return true; + } else { + if (trips[id].status == 'show') { + myMap.removeLayer(trips[id]); + } + + trips[id].status = 'hide'; + return true; + } +} + +function loadTrack(id) +{ + colors = ['#ff0000', '#ff8e00', '#ff0', '#0f0', '#003cff', '#ff00ad']; + colorIndex = 0; + tracks = new Array(); + markers = new Array(); + $.ajax({ + url: "/json/track/id/" + id, + success: function (data) { + trips[id] = L.featureGroup(); + + if (typeof (data.tracks) != 'undefined') { + for (var i = 0; i < data.tracks.length; i++) { + color = colors[colorIndex]; + colorIndex = (colorIndex == colors.length-1) ? 0 : colorIndex+1; + + tracks[i] = L.polyline(data.tracks[i].latlngs, {color: color, width: 4, opacity: 0.8}); + tracks[i].bindPopup(data.tracks[i].name); + trips[id].addLayer(tracks[i]) + } + } + + if (typeof (data.wayPoints) != 'undefined') { + for (var i = 0; i < data.wayPoints.length; i++) { + markers[i] = L.marker([data.wayPoints[i]['lat'], data.wayPoints[i]['lng']], {icon: categories.marker, title: data.wayPoints[i]['name']}) + markers[i].bindPopup('' + data.wayPoints[i]['name'] + '
' + data.wayPoints[i]['description']); + trips[id].addLayer(markers[i]) + } + } + + showTrack(id) + }, + error: function (data) { + alert('Не удалось загрузить трек. Возможно это приватный трек и вы не его владелец.') + } + }); +} + +function loadSimpleTrack(id) +{ + colors = ['red', 'green', 'blue', 'orange']; + colors = ['red']; + colorIndex = 0; + tracks = new Array(); + markers = new Array(); + $.ajax({ + url: "/json/simpletrack/id/" + id, + success: function (data) { + trips[id] = L.featureGroup(); + + if (typeof (data.tracks) != 'undefined') { + for (var i = 0; i < data.tracks.length; i++) { + color = colors[colorIndex]; + colorIndex = (colorIndex == colors.length-1) ? 0 : colorIndex+1; + + tracks[i] = L.polyline(data.tracks[i].latlngs, {color: color, width: 4, opacity: 0.8}); + tracks[i].bindPopup(data.tracks[i].name); + trips[id].addLayer(tracks[i]) + } + } + + if (typeof (data.wayPoints) != 'undefined') { + for (var i = 0; i < data.wayPoints.length; i++) { + markers[i] = L.marker([data.wayPoints[i]['lat'], data.wayPoints[i]['lng']], {icon: categories.marker, title: data.wayPoints[i]['name']}) + markers[i].bindPopup('' + data.wayPoints[i]['name'] + '
' + data.wayPoints[i]['description']); + trips[id].addLayer(markers[i]) + } + } + + showTrack(id) + }, + error: function (data) { + alert('Не удалось загрузить трек. Возможно это приватный трек и вы не его владелец.') + } + }); +} + + diff --git a/tracks/.gitKeep b/tracks/.gitKeep new file mode 100644 index 0000000..e69de29 diff --git a/views/file.php b/views/file.php new file mode 100644 index 0000000..6a6aad2 --- /dev/null +++ b/views/file.php @@ -0,0 +1,20 @@ +
-
-
+
+
+
@@ -103,6 +104,32 @@ if (App::$user) { +
+

+ Мои треки + +

+
+
+ + +
+ + name ?> + distance(); ?> + status == Trips::STATUS_PUBLIC):?> + [клик правой кнопкой -> копировать адрес]"> + + + +
+ + + У вас пока нет сохраненных треков. + Загляните в раздел управления треками . + +
+
diff --git a/views/tracks/edit.php b/views/tracks/edit.php new file mode 100644 index 0000000..d592fc1 --- /dev/null +++ b/views/tracks/edit.php @@ -0,0 +1,156 @@ + + + Выйти из редактора + + +

Свойства трека

+
+
+ + +
+
+ + +
+ + + Удалить трек + +
+ +
+ + + +
+
+ + +

Фрагменты трека ()

+ + + + +

Путевые точки ()

+ + + + diff --git a/views/tracks/files.php b/views/tracks/files.php new file mode 100644 index 0000000..c8a1d5f --- /dev/null +++ b/views/tracks/files.php @@ -0,0 +1,27 @@ +

Ваши исходные файлы с треками

+← вернуться к трекам +
+ + + id ?> +   + + + +    + + + +   + name ?> + — filename ?> + [tracksCount?> . tptCount ?> . wptCount ?>] +
+ + + + +

Ваши треки

+ + +
+
+ + + +   + +
+
+ + + +
+ + + + + id ?> — + name ?> (createdAt ?>) + status == Trips::STATUS_PUBLIC):?> + + +
+