Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
com.akaver.sportmap
SportMap-aurelia
Commits
c942d0cf
Commit
c942d0cf
authored
Apr 22, 2020
by
Andres Käver
Browse files
gradient track
parent
caf2881f
Pipeline
#795
passed with stages
in 1 minute and 17 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
package-lock.json
View file @
c942d0cf
...
...
@@ -5688,6 +5688,11 @@
"integrity"
:
"sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
,
"dev"
:
true
},
"gradstop"
:
{
"version"
:
"2.2.3"
,
"resolved"
:
"https://registry.npmjs.org/gradstop/-/gradstop-2.2.3.tgz"
,
"integrity"
:
"sha512-omtiHZCI/vykWcXNDYdrHhe7VUnnZvya94wAHRLI8ciDkAviXYrT+pwP7ybYqK7uwYir59auBCY5ggwBlVSmsg=="
},
"gulp"
:
{
"version"
:
"4.0.2"
,
"resolved"
:
"https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz"
,
...
...
package.json
View file @
c942d0cf
...
...
@@ -15,6 +15,7 @@
"
bootstrap
"
:
"
^4.4.1
"
,
"
eslint
"
:
"
^6.8.0
"
,
"
font-awesome
"
:
"
^4.7.0
"
,
"
gradstop
"
:
"
^2.2.3
"
,
"
jquery
"
:
"
3.4.1
"
,
"
leaflet
"
:
"
^1.6.0
"
,
"
leaflet-defaulticon-compatibility
"
:
"
^0.1.1
"
,
...
...
src/domain/IGpsLocation.ts
View file @
c942d0cf
...
...
@@ -6,4 +6,5 @@ export interface IGpsLocation {
altitude
:
number
;
verticalAccuracy
:
number
;
gpsLocationTypeId
:
string
;
recordedAt
:
string
;
}
src/utils/utils-general.ts
View file @
c942d0cf
...
...
@@ -34,3 +34,14 @@ export function validateLogLevel(logLevel: string | undefined): string {
}
}
export
function
decimalToHex
(
d
:
number
,
padding
?
:
number
|
null
):
string
{
let
hex
=
Number
(
d
).
toString
(
16
);
padding
=
typeof
(
padding
)
===
"
undefined
"
||
padding
===
null
?
padding
=
2
:
padding
;
while
(
hex
.
length
<
padding
)
{
hex
=
"
0
"
+
hex
;
}
return
hex
;
}
src/utils/utils-leaflet.ts
0 → 100644
View file @
c942d0cf
import
{
IGpsLocation
}
from
'
domain/IGpsLocation
'
;
import
{
log
}
from
'
app
'
;
export
function
distanceBetweenLatLon
(
lat1
:
number
,
lon1
:
number
,
lat2
:
number
,
lon2
:
number
):
number
{
if
((
lat1
==
lat2
)
&&
(
lon1
==
lon2
))
{
return
0
;
}
else
{
const
radlat1
=
Math
.
PI
*
lat1
/
180
;
const
radlat2
=
Math
.
PI
*
lat2
/
180
;
const
theta
=
lon1
-
lon2
;
const
radtheta
=
Math
.
PI
*
theta
/
180
;
let
dist
=
Math
.
sin
(
radlat1
)
*
Math
.
sin
(
radlat2
)
+
Math
.
cos
(
radlat1
)
*
Math
.
cos
(
radlat2
)
*
Math
.
cos
(
radtheta
);
if
(
dist
>
1
)
{
dist
=
1
;
}
dist
=
Math
.
acos
(
dist
);
dist
=
dist
*
180
/
Math
.
PI
;
dist
=
dist
*
60
*
1853.159616
;
// in meters
return
dist
;
}
}
function
timeBetweenDates
(
date0
:
Date
,
date1
:
Date
):
number
{
return
Math
.
abs
(
date0
.
getTime
()
-
date1
.
getTime
());
}
function
addToBucket
(
buckets
:
L
.
LatLngExpression
[][][],
bucketNo
:
number
,
latLon
:
L
.
LatLngExpression
,
latLonPrev
:
L
.
LatLngExpression
):
L
.
LatLngExpression
[][][]
{
if
(
bucketNo
>=
buckets
.
length
)
return
buckets
;
buckets
[
bucketNo
].
push
([
latLonPrev
,
latLon
]);
return
buckets
;
}
// minSpeed and maxSpeed - seconds per km
export
function
getColorCodedPolylines
(
locations
:
IGpsLocation
[],
minPace
:
number
=
6
,
maxPace
:
number
=
10
,
paceBuckets
:
number
=
256
):
L
.
LatLngExpression
[][][]
{
if
(
!
locations
||
locations
.
length
==
0
)
return
[];
const
result
:
L
.
LatLngExpression
[][][]
=
[];
for
(
let
index
=
0
;
index
<
paceBuckets
;
index
++
)
{
result
.
push
([]);
}
const
paceRange
=
maxPace
-
minPace
;
const
paceStep
=
paceRange
/
paceBuckets
;
let
prevLocation
:
IGpsLocation
|
null
=
null
;
for
(
let
index
=
0
;
index
<
locations
.
length
;
index
++
)
{
const
location
=
locations
[
index
];
if
(
prevLocation
)
{
const
distance
=
distanceBetweenLatLon
(
location
.
latitude
,
location
.
longitude
,
prevLocation
.
latitude
,
prevLocation
.
longitude
);
const
duration
=
timeBetweenDates
(
new
Date
(
location
.
recordedAt
),
new
Date
(
prevLocation
.
recordedAt
));
// skip bad locations
if
(
distance
<
1
||
duration
<
1000
)
continue
;
// calculate the speed in minutes per km
const
paceMinutesPerKm
=
duration
/
distance
/
60
;
let
bucketNo
=
Math
.
round
(((
paceMinutesPerKm
-
minPace
)
/
paceStep
));
if
(
bucketNo
<
0
)
{
bucketNo
=
0
}
else
if
(
bucketNo
>=
paceBuckets
){
bucketNo
=
paceBuckets
-
1
;
}
console
.
log
(
paceMinutesPerKm
,
bucketNo
);
addToBucket
(
result
,
bucketNo
,
[
location
.
latitude
,
location
.
longitude
],
[
prevLocation
.
latitude
,
prevLocation
.
longitude
]);
//log.debug('distance duration pace', distance, duration, paceMinutesPerKm);
}
prevLocation
=
location
;
}
console
.
log
(
result
);
return
result
;
}
src/views/home/index.html
View file @
c942d0cf
...
...
@@ -28,5 +28,5 @@
</div>
</div>
<div
id=
"map"
></div>
<div
show.bind=
"selectedGpsSession"
>
Track length: ${trackLength} km
</div>
<div
show.bind=
"selectedGpsSession"
>
Track length: ${trackLength
/ 1000
} km
</div>
</template>
src/views/home/index.ts
View file @
c942d0cf
...
...
@@ -7,10 +7,14 @@ import { PLATFORM } from 'aurelia-pal';
import
{
autoinject
,
LogManager
,
View
,
observable
}
from
'
aurelia-framework
'
;
import
{
RouterConfiguration
,
Router
,
RouteConfig
,
NavigationInstruction
}
from
'
aurelia-router
'
;
import
{
EventAggregator
,
Subscription
}
from
'
aurelia-event-aggregator
'
;
import
'
leaflet/dist/leaflet.css
'
;
import
'
leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css
'
;
import
*
as
L
from
'
leaflet
'
;
import
'
leaflet-defaulticon-compatibility
'
;
import
{
distanceBetweenLatLon
,
getColorCodedPolylines
}
from
'
utils/utils-leaflet
'
;
import
{
decimalToHex
}
from
'
utils/utils-general
'
;
import
gradstop
from
'
gradstop
'
;
export
const
log
=
LogManager
.
getLogger
(
'
app.HomeIndex
'
);
...
...
@@ -35,10 +39,14 @@ export class HomeIndex {
viewportHeight
=
Math
.
max
(
document
.
documentElement
.
clientHeight
,
window
.
innerHeight
||
0
);
viewportWidth
=
Math
.
max
(
document
.
documentElement
.
clientWidth
,
window
.
innerWidth
||
0
);
constructor
(
private
gpsSessionService
:
GpsSessionService
,
private
gpsLocationService
:
GpsLocationService
)
{
private
paceColorGradient
:
string
[]
=
[];
constructor
(
private
gpsSessionService
:
GpsSessionService
,
private
gpsLocationService
:
GpsLocationService
)
{
this
.
paceColorGradient
=
gradstop
({
stops
:
1024
,
inputFormat
:
'
hex
'
,
colorArray
:
[
'
#00FF00
'
,
'
#FFFF00
'
,
'
#FF0000
'
]
});
}
// ================================= view lifecycle ===============================
...
...
@@ -158,60 +166,57 @@ export class HomeIndex {
const
polylinePoints
:
L
.
LatLngExpression
[]
=
[];
this
.
trackLength
=
0
;
const
paceBuckets
=
getColorCodedPolylines
(
this
.
gpsLocations
,
6
,
18
,
1024
);
this
.
gpsLocations
.
forEach
((
location
,
index
)
=>
{
polylinePoints
.
push
([
location
.
latitude
,
location
.
longitude
]);
if
(
index
>
0
)
{
this
.
trackLength
=
this
.
trackLength
+
this
.
distance
(
this
.
trackLength
=
this
.
trackLength
+
distance
BetweenLatLon
(
this
.
gpsLocations
[
index
-
1
].
latitude
,
this
.
gpsLocations
[
index
-
1
].
longitude
,
location
.
latitude
,
location
.
longitude
);
}
if
(
location
.
gpsLocationTypeId
==
GpsLocationTypes
.
wayPoint
&&
this
.
showWp
)
{
log
.
debug
(
'
adding wp to
'
,
[
location
.
latitude
,
location
.
longitude
])
//
log.debug('adding wp to ', [location.latitude, location.longitude])
L
.
marker
([
location
.
latitude
,
location
.
longitude
],
{
icon
:
iconWp
}).
addTo
(
this
.
map
);
}
else
if
(
location
.
gpsLocationTypeId
==
GpsLocationTypes
.
checkPoint
&&
this
.
showCp
)
{
log
.
debug
(
'
adding cp to
'
,
[
location
.
latitude
,
location
.
longitude
])
//
log.debug('adding cp to ', [location.latitude, location.longitude])
L
.
marker
([
location
.
latitude
,
location
.
longitude
],
{
icon
:
iconCp
}).
addTo
(
this
.
map
);
}
});
paceBuckets
.
forEach
((
paceSegment
,
bucketNo
)
=>
{
paceSegment
.
forEach
(
lineSegment
=>
{
const
polyline
=
L
.
polyline
(
lineSegment
).
setStyle
({
color
:
this
.
paceColorGradient
[
bucketNo
],
weight
:
5
}).
addTo
(
this
.
map
);
})
})
// add start marker
if
(
polylinePoints
.
length
>
0
)
{
L
.
marker
([
this
.
gpsLocations
[
0
].
latitude
,
this
.
gpsLocations
[
0
].
longitude
],
{
icon
:
iconS
}).
addTo
(
this
.
map
);
this
.
map
.
setView
([
this
.
gpsLocations
[
0
].
latitude
,
this
.
gpsLocations
[
0
].
longitude
],
15
);
}
// add finish marker
if
(
polylinePoints
.
length
>
1
)
{
L
.
marker
([
this
.
gpsLocations
[
this
.
gpsLocations
.
length
-
1
].
latitude
,
this
.
gpsLocations
[
this
.
gpsLocations
.
length
-
1
].
longitude
],
{
icon
:
iconF
}).
addTo
(
this
.
map
);
}
/*
if (polylinePoints.length > 0) {
const polyline = L.polyline(polylinePoints).addTo(this.map);
this.map.fitBounds(polyline.getBounds());
}
*/
}
distance
(
lat1
:
number
,
lon1
:
number
,
lat2
:
number
,
lon2
:
number
):
number
{
if
((
lat1
==
lat2
)
&&
(
lon1
==
lon2
))
{
return
0
;
}
else
{
const
radlat1
=
Math
.
PI
*
lat1
/
180
;
const
radlat2
=
Math
.
PI
*
lat2
/
180
;
const
theta
=
lon1
-
lon2
;
const
radtheta
=
Math
.
PI
*
theta
/
180
;
let
dist
=
Math
.
sin
(
radlat1
)
*
Math
.
sin
(
radlat2
)
+
Math
.
cos
(
radlat1
)
*
Math
.
cos
(
radlat2
)
*
Math
.
cos
(
radtheta
);
if
(
dist
>
1
)
{
dist
=
1
;
}
dist
=
Math
.
acos
(
dist
);
dist
=
dist
*
180
/
Math
.
PI
;
dist
=
dist
*
60
*
1.853159616
;
return
dist
;
}
}
}
types/gradstop.d.ts
0 → 100644
View file @
c942d0cf
declare
module
'
gradstop
'
{
function
gradstop
(
options
:
any
):
string
[];
export
=
gradstop
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment