Visitar URL original
Visualize geofences on front-end by IcognitoUnown · Pull Request #2171 · RocketMap/RocketMap · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"ga": true,
"google": true,
"moment": false,
"randomColor": false,
"MarkerClusterer": true,

"isTouchDevice": true,
Expand Down
25 changes: 24 additions & 1 deletion pogom/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from bisect import bisect_left

from . import config
from .models import (Pokemon, Gym, Pokestop, ScannedLocation,
from .models import (Geofence, Pokemon, Gym, Pokestop, ScannedLocation,
MainWorker, WorkerStatus, Token, HashKeys,
SpawnPoint)
from .utils import now, dottedQuadToNum, get_blacklist
Expand Down Expand Up @@ -162,6 +162,8 @@ def fullmap(self):
args.spawnpoint_scanning) else True

visibility_flags = {
'geofences': bool(args.geofence_file or
args.geofence_excluded_file),
'gyms': not args.no_gyms,
'pokemons': not args.no_pokemon,
'pokestops': not args.no_pokestops,
Expand Down Expand Up @@ -371,6 +373,27 @@ def raw_data(self):
oSwLat=oSwLat, oSwLng=oSwLng,
oNeLat=oNeLat, oNeLng=oNeLng))

if request.args.get('geofences', 'true') == 'true':
db_geofences = Geofence.get_geofences()

geofences = {}
for g in db_geofences:
# Check if already there
geofence = geofences.get(g['name'], None)
if not geofence: # Create a new sub-dict if new
geofences[g['name']] = {
'excluded': g['excluded'],
'name': g['name'],
'coordinates': []
}
coordinate = {
'lat': g['latitude'],
'lng': g['longitude']
}
geofences[g['name']]['coordinates'].append(coordinate)

d['geofences'] = geofences

if request.args.get('status', 'false') == 'true':
args = get_args()
d = {}
Expand Down
2 changes: 2 additions & 0 deletions pogom/geofence.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import logging

from .utils import get_args
from .models import Geofence

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -33,6 +34,7 @@ def __init__(self):
args.geofence_file, excluded=False)
self.excluded_areas = self.parse_geofences_file(
args.geofence_excluded_file, excluded=True)
Geofence.push_geofences(self.geofenced_areas+self.excluded_areas)
log.info('Loaded %d geofenced and %d excluded areas.',
len(self.geofenced_areas),
len(self.excluded_areas))
Expand Down
84 changes: 78 additions & 6 deletions pogom/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,77 @@ def get_all(cls):
return results


# Geofence DB Model
class Geofence(BaseModel):
name = Utf8mb4CharField(max_length=50)
excluded = BooleanField()
coordinates_id = SmallIntegerField()
latitude = DoubleField()
longitude = DoubleField()

class Meta:
primary_key = False

@staticmethod
def clear_all():
# Remove all geofences without interfering with other threads.
with flaskDb.database.transaction():
DeleteQuery(Geofence).execute()

@staticmethod
def remove_duplicates(geofences):
# Remove old geofences without interfering with other DB threads.
with flaskDb.database.transaction():
for g in geofences:
(DeleteQuery(Geofence)
.where(Geofence.name == g['name'])
.execute())

@staticmethod
def push_geofences(geofences):
Geofence.remove_duplicates(geofences)

db_geofences = []
for g in geofences:
coordinates_id = 0
for c in g['polygon']:
db_geofences.append({
'excluded': g['excluded'],
'name': g['name'],
'coordinates_id': coordinates_id,
'latitude': c['lat'],
'longitude': c['lon']
})
coordinates_id = coordinates_id + 1

# Make a DB save.
with flaskDb.database.transaction():
Geofence.insert_many(db_geofences).execute()

return db_geofences

@staticmethod
def get_geofences():
query = Geofence.select().dicts()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Control the situation when there are no geofences.
I know that this should be called in that situation but you never know.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is controlled by just returning an empty query which doesn't get looped due to for gf in query and returns am empty array geofences.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SiteEffect Peewee raises an exception if there are not data, not an empty iterable, not sure why


# Performance: disable the garbage collector prior to creating a
# (potentially) large dict with append().
gc.disable()

geofences = []
for g in query:
if args.china:
g['polygon']['latitude'], g['polygon']['longitude'] = \
transform_from_wgs_to_gcj(g['polygon']['latitude'],
g['polygon']['longitude'])
geofences.append(g)

# Re-enable the GC.
gc.enable()

return geofences


class Pokemon(BaseModel):
# We are base64 encoding the ids delivered by the api
# because they are too big for sqlite to handle.
Expand Down Expand Up @@ -2747,10 +2818,11 @@ def bulk_upsert(cls, data, db):

def create_tables(db):
db.connect()
tables = [Pokemon, Pokestop, Gym, Raid, ScannedLocation, GymDetails,
GymMember, GymPokemon, Trainer, MainWorker, WorkerStatus,
SpawnPoint, ScanSpawnPoint, SpawnpointDetectionData,
Token, LocationAltitude, PlayerLocale, HashKeys]
tables = [Geofence, Pokemon, Pokestop, Gym, Raid, ScannedLocation,
GymDetails, GymMember, GymPokemon, Trainer, MainWorker,
WorkerStatus, SpawnPoint, ScanSpawnPoint,
SpawnpointDetectionData, Token, LocationAltitude, PlayerLocale,
HashKeys]
for table in tables:
if not table.table_exists():
log.info('Creating table: %s', table.__name__)
Expand All @@ -2761,8 +2833,8 @@ def create_tables(db):


def drop_tables(db):
tables = [Pokemon, Pokestop, Gym, Raid, ScannedLocation, Versions,
GymDetails, GymMember, GymPokemon, Trainer, MainWorker,
tables = [Geofence, Pokemon, Pokestop, Gym, Raid, ScannedLocation,
Versions, GymDetails, GymMember, GymPokemon, Trainer, MainWorker,
WorkerStatus, SpawnPoint, ScanSpawnPoint,
SpawnpointDetectionData, LocationAltitude, PlayerLocale,
Token, HashKeys]
Expand Down
4 changes: 4 additions & 0 deletions static/js/map.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,10 @@ var StoreOptions = {
default: false,
type: StoreTypes.Boolean
},
'showGeofences': {
default: false,
type: StoreTypes.Boolean
},
'playSound': {
default: false,
type: StoreTypes.Boolean
Expand Down
110 changes: 110 additions & 0 deletions static/js/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ var lastpokemon
var lastslocs
var lastspawns

var polygons = []
var geofencesSet = false

var selectedStyle = 'light'

var updateWorker
Expand Down Expand Up @@ -415,6 +418,7 @@ function initSidebar() {
$('#sound-switch').prop('checked', Store.get('playSound'))
$('#pokemoncries').toggle(Store.get('playSound'))
$('#cries-switch').prop('checked', Store.get('playCries'))
$('#geofences-switch').prop('checked', Store.get('showGeofences'))

// Only create the Autocomplete element if it's enabled in template.
var elSearchBox = document.getElementById('next-location')
Expand Down Expand Up @@ -829,6 +833,28 @@ function spawnpointLabel(item) {
return str
}

function geofenceLabel(item) {
var str
if (item.excluded) {
str = `
<div>
<b>Excluded Area</b>
</div>`
} else {
str = `
<div>
<b>Geofence</b>
</div>`
}

str += `
<div>
${item.name}
</div>`

return str
}

function addRangeCircle(marker, map, type, teamId) {
var targetmap = null
var circleCenter = new google.maps.LatLng(marker.position.lat(), marker.position.lng())
Expand Down Expand Up @@ -1257,6 +1283,62 @@ function setupSpawnpointMarker(item) {
return marker
}

function setupGeofencePolygon(item) {
var randomcolor = randomColor()
// Random with color seed randomColor({hue: 'pink'})
// Total random '#'+Math.floor(Math.random()*16777215).toString(16);
if (item.excluded === true) {
randomcolor = randomColor({hue: 'red'})
} else {
randomcolor = randomColor({hue: 'green'})
}

var polygon = new google.maps.Polygon({
map: map,
paths: item['coordinates'],
strokeColor: randomcolor,
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: randomcolor,
fillOpacity: 0.5
})

var markerPosition = polygonCenter(polygon)

polygon.infoWindow = new google.maps.InfoWindow({
content: geofenceLabel(item),
disableAutoPan: true,
position: markerPosition
})

addListeners(polygon)

return polygon
}

function polygonCenter(polygon) {
var hyp, Lat, Lng

var X = 0
var Y = 0
var Z = 0
polygon.getPath().forEach(function (vertex, inex) {
var lat
var lng
lat = vertex.lat() * Math.PI / 180
lng = vertex.lng() * Math.PI / 180
X += Math.cos(lat) * Math.cos(lng)
Y += Math.cos(lat) * Math.sin(lng)
Z += Math.sin(lat)
})

hyp = Math.sqrt(X * X + Y * Y)
Lat = Math.atan2(Z, hyp) * 180 / Math.PI
Lng = Math.atan2(Y, X) * 180 / Math.PI

return new google.maps.LatLng(Lat, Lng)
}

function clearSelection() {
if (document.selection) {
document.selection.empty()
Expand Down Expand Up @@ -1406,6 +1488,7 @@ function loadRawData() {
var loadScanned = Store.get('showScanned')
var loadSpawnpoints = Store.get('showSpawnpoints')
var loadLuredOnly = Boolean(Store.get('showLuredPokestopsOnly'))
var loadGeofences = Store.get('showGeofences')

var bounds = map.getBounds()
var swPoint = bounds.getSouthWest()
Expand All @@ -1430,6 +1513,7 @@ function loadRawData() {
'scanned': loadScanned,
'lastslocs': lastslocs,
'spawnpoints': loadSpawnpoints,
'geofences': loadGeofences,
'lastspawns': lastspawns,
'swLat': swLat,
'swLng': swLng,
Expand Down Expand Up @@ -1782,6 +1866,26 @@ function updateSpawnPoints() {
})
}

function updateGeofences(geofences) {
var i
if (!Store.get('showGeofences') && geofencesSet === true) {
for (i = 0; i < polygons.length; i++) {
polygons[i].setMap(null)
}
polygons = []
geofencesSet = false
return false
} else if (Store.get('showGeofences') && geofencesSet === false) {
var key
i = 0
for (key in geofences) {
polygons[i] = setupGeofencePolygon(geofences[key])
i++
}
geofencesSet = true
}
}

function updateMap() {
loadRawData().done(function (result) {
processPokemons(result.pokemons)
Expand All @@ -1803,6 +1907,7 @@ function updateMap() {
updateScanned()
updateSpawnPoints()
updatePokestops()
updateGeofences(result.geofences)

if ($('#stats').hasClass('visible')) {
countMarkers(map)
Expand Down Expand Up @@ -2740,6 +2845,11 @@ $(function () {
}
})

$('#geofences-switch').change(function () {
Store.set('showGeofences', this.checked)
updateMap()
})

$('#lock-marker-switch').change(function () {
Store.set('lockMarker', this.checked)
searchMarker.setDraggable(!this.checked)
Expand Down
Loading