def from_dict(self, track_dict): """Populate this object's values with values from a dict, either from RCL's API or a file """ self.start_finish_point = GeoPoint.fromPointJson(track_dict.get('start_finish')) self.finish_point = GeoPoint.fromPointJson(track_dict.get('finish')) self.country_code = track_dict.get('country_code', self.country_code) self.created = track_dict.get('created', self.created) self.updated = track_dict.get('updated', self.updated) self.name = track_dict.get('name', self.name) self.configuration = track_dict.get('configuration', self.configuration) self.length = track_dict.get('length', self.length) self.track_id = track_dict.get('id') map_points_array = track_dict.get('track_map_array') if map_points_array: for point in map_points_array: self.map_points.append(GeoPoint.fromPoint(point[0], point[1])) sector_array = track_dict.get('sector_points') if sector_array: for point in sector_array: self.sector_points.append(GeoPoint.fromPoint(point[0], point[1])) if not self.short_id > 0: raise Warning("Could not parse trackMap: short_id is invalid")
def fromJson(self, trackJson): venueNode = trackJson.get('venue') if (venueNode): self.startFinishPoint = GeoPoint.fromPointJson(venueNode.get('start_finish')) self.finishPoint = GeoPoint.fromPointJson(venueNode.get('finish')) self.countryCode = venueNode.get('country_code', self.countryCode) self.createdAt = venueNode.get('created', self.createdAt) self.updatedAt = venueNode.get('updated', self.updatedAt) self.name = venueNode.get('name', self.name) self.configuration = venueNode.get('configuration', self.configuration) self.length = venueNode.get('length', self.length) self.trackId = venueNode.get('id', self.trackId) self.shortId = self._createShortId() mapPointsNode = venueNode.get('track_map_array') mapPoints = [] if mapPointsNode: for point in mapPointsNode: mapPoints.append(GeoPoint.fromPoint(point[0], point[1])) self.mapPoints = mapPoints sectorNode = venueNode.get('sector_points') sectorPoints = [] if sectorNode: for point in sectorNode: sectorPoints.append(GeoPoint.fromPoint(point[0], point[1])) self.sectorPoints = sectorPoints if not self.shortId > 0: raise Warning("Could not parse trackMap: shortId is invalid")
def fromJson(self, trackJson): if trackJson: self.trackId = trackJson.get('id', self.trackId) self.trackType = trackJson.get('type', self.trackType) sectorsJson = trackJson.get('sec', None) del self.sectors[:] if self.trackType == TRACK_TYPE_CIRCUIT: self.startLine.fromJson(trackJson.get('sf', None)) sectorCount = CONFIG_SECTOR_COUNT_CIRCUIT else: self.startLine.fromJson(trackJson.get('st', self.startLine)) self.finishLine.fromJson(trackJson.get('fin', self.finishLine)) sectorCount = CONFIG_SECTOR_COUNT_STAGE returnedSectorCount = len(sectorsJson) if sectorsJson: for i in range(sectorCount): sector = GeoPoint() if i < returnedSectorCount: sectorJson = sectorsJson[i] sector.fromJson(sectorJson) self.sectors.append(sector) self.sectorCount = sectorCount self.stale = False
def from_dict(self, track_dict): """Populate this object's values with values from a dict, either from RCL's API or a file """ self.start_finish_point = GeoPoint.fromPointJson( track_dict.get('start_finish')) self.finish_point = GeoPoint.fromPointJson(track_dict.get('finish')) self.country_code = track_dict.get('country_code', self.country_code) self.created = track_dict.get('created', self.created) self.updated = track_dict.get('updated', self.updated) self.name = track_dict.get('name', self.name) self.configuration = track_dict.get('configuration', self.configuration) self.length = track_dict.get('length', self.length) self.track_id = track_dict.get('id') map_points_array = track_dict.get('track_map_array') if map_points_array: for point in map_points_array: self.map_points.append(GeoPoint.fromPoint(point[0], point[1])) sector_array = track_dict.get('sector_points') if sector_array: for point in sector_array: self.sector_points.append( GeoPoint.fromPoint(point[0], point[1])) if not self.short_id > 0: raise Warning("Could not parse trackMap: short_id is invalid")
def fromJson(self, trackJson): venueNode = trackJson.get('venue') if (venueNode): self.startFinishPoint = GeoPoint.fromPointJson( venueNode.get('start_finish')) self.finishPoint = GeoPoint.fromPointJson(venueNode.get('finish')) self.countryCode = venueNode.get('country_code', self.countryCode) self.createdAt = venueNode.get('created', self.createdAt) self.updatedAt = venueNode.get('updated', self.updatedAt) self.name = venueNode.get('name', self.name) self.configuration = venueNode.get('configuration', self.configuration) self.length = venueNode.get('length', self.length) self.trackId = venueNode.get('id', self.trackId) self.shortId = self._createShortId() mapPointsNode = venueNode.get('track_map_array') mapPoints = [] if mapPointsNode: for point in mapPointsNode: mapPoints.append(GeoPoint.fromPoint(point[0], point[1])) self.mapPoints = mapPoints sectorNode = venueNode.get('sector_points') sectorPoints = [] if sectorNode: for point in sectorNode: sectorPoints.append(GeoPoint.fromPoint(point[0], point[1])) self.sectorPoints = sectorPoints if not self.shortId > 0: raise Warning("Could not parse trackMap: shortId is invalid")
def __init__(self, **kwargs): self.stale = False self.trackType = TRACK_TYPE_CIRCUIT self.sectorCount = CONFIG_SECTOR_COUNT self.startLine = GeoPoint() self.finishLine = GeoPoint() self.sectors = []
def fromJson(self, trackJson): venueNode = trackJson.get('venue') if (venueNode): self.startFinishPoint = GeoPoint.fromPointJson( venueNode.get('start_finish')) self.finishPoint = GeoPoint.fromPointJson(venueNode.get('finish')) self.countryCode = venueNode.get('country_code', self.countryCode) self.updatedAt = venueNode.get('updated', self.updatedAt) self.name = venueNode.get('name', self.name) self.configuration = venueNode.get('configuration', self.configuration) self.length = venueNode.get('length', self.length) self.trackId = venueNode.get('id', self.trackId) mapPointsNode = venueNode.get('track_map_array') mapPoints = [] if mapPointsNode: for point in mapPointsNode: mapPoints.append(GeoPoint.fromPoint(point[0], point[1])) self.mapPoints = mapPoints sectorNode = venueNode.get('sector_points') sectorPoints = [] if sectorNode: for point in sectorNode: sectorPoints.append(GeoPoint.fromPoint(point[0], point[1])) self.sectorPoints = sectorPoints
def __init__(self, **kwargs): self.stale = False self.trackId = None self.trackType = TRACK_TYPE_CIRCUIT self.sectorCount = CONFIG_SECTOR_COUNT self.startLine = GeoPoint() self.finishLine = GeoPoint() self.sectors = []
def _get_location_data(self, params): ''' Retrieve cached or query Location data as appropriate. ''' source_ref = params.source_ref source_key = str(source_ref) cache = self._session_location_cache.get(source_key) if cache == None: session = source_ref.session lap = source_ref.lap f = Filter().neq('Latitude', 0).and_().neq('Longitude', 0).eq("CurrentLap", lap) dataset = self.query(sessions=[session], channels=["Latitude", "Longitude"], data_filter=f) records = dataset.fetch_records() cache = [] for r in records: lat = r[1] lon = r[2] cache.append(GeoPoint.fromPoint(lat, lon)) self._session_location_cache[source_key] = cache Clock.schedule_once(lambda dt: params.callback(cache))
def select_map(self, latitude, longitude): if self.track_manager: point = GeoPoint.fromPoint(latitude, longitude) track = self.track_manager.find_nearby_track(point) if track != None: self.ids.track.setTrackPoints(track.map_points) self.track = track
def select_map(self, latitude, longitude): """ Find and display a nearby track by latitude / longitude The selection will favor a previously selected track in the nearby area :param latitude :type latitude float :param longitude :type longitude float :returns the selected track, or None if there are no nearby tracks :type Track """ if not latitude or not longitude: return None point = GeoPoint.fromPoint(latitude, longitude) nearby_tracks = self.track_manager.find_nearby_tracks(point) saved_tracks = self.get_pref_track_selections() saved_nearby_tracks = [ t for t in nearby_tracks if t.track_id in saved_tracks ] # select the saved nearby track or just a nearby track track = next(iter(saved_nearby_tracks), None) track = next(iter(nearby_tracks), None) if track is None else track if self.track != track: # only update the trackmap if it's changing self._select_track(track) return track
def select_map(self, latitude, longitude): """ Find and display a nearby track by latitude / longitude The selection will favor a previously selected track in the nearby area :param latitude :type latitude float :param longitude :type longitude float :returns the selected track, or None if there are no nearby tracks :type Track """ if not latitude or not longitude: return None point = GeoPoint.fromPoint(latitude, longitude) nearby_tracks = self.track_manager.find_nearby_tracks(point) saved_tracks = self.get_pref_track_selections() saved_nearby_tracks = [t for t in nearby_tracks if t.track_id in saved_tracks] # select the saved nearby track or just a nearby track track = next(iter(saved_nearby_tracks), None) track = next(iter(nearby_tracks), None) if track is None else track if self.track != track: # only update the trackmap if it's changing self._select_track(track) return track
def _on_sample(self, sample): gps_quality = sample.get('GPSQual') latitude = sample.get('Latitude') longitude = sample.get('Longitude') if self._rc_api.connected and gps_quality >= GpsConfig.GPS_QUALITY_2D: self._update_current_location(GeoPoint.fromPoint(latitude, longitude), GeoProvider.GPS_SOURCE_RACECAPTURE) self._rc_gps_quality = gps_quality
def _check_internal_gps_update(self, *args): location = self._internal_gps_conn.getCurrentLocation() if not location: return location_time = location.getTime() if location_time != self._last_internal_location_time: self._internal_gps_active = True if self._should_use_internal_source: point = GeoPoint.fromPoint(location.getLatitude(), location.getLongitude()) self._update_current_location(point, GeoProvider.GPS_SOURCE_INTERNAL) self._last_internal_location_time = location_time
def select_map(self, latitude, longitude): ''' Find and display a nearby track by latitude / longitude :param latitude :type latitude float :param longitude :type longitude float ''' if self.track_manager: point = GeoPoint.fromPoint(latitude, longitude) track = self.track_manager.find_nearby_track(point) self._select_track(track)
def select_map(self, latitude, longitude): ''' Find and display a nearby track by latitude / longitude :param latitude :type latitude float :param longitude :type longitude float :returns the selected track :type Track ''' point = GeoPoint.fromPoint(latitude, longitude) track = self.track_manager.find_nearby_track(point) if self.track != track: #only update the trackmap if it's changing self._select_track(track) return track
def get_location_data(self, source_ref): source_key = str(source_ref) cache = self._session_location_cache.get(source_key) if cache == None: session = source_ref.session lap = source_ref.lap f = Filter().neq('Latitude', 0).and_().neq('Longitude', 0).eq("LapCount", lap) dataset = self.query(sessions = [session], channels = ["Latitude", "Longitude"], data_filter = f) records = dataset.fetch_records() cache = [] for r in records: lat = r[1] lon = r[2] cache.append(GeoPoint.fromPoint(lat, lon)) self._session_location_cache[source_key]=cache return cache
def _get_location_data(self, source_ref, callback): ''' Retrieve cached or query Location data as appropriate. ''' session = source_ref.session lap = source_ref.lap f = Filter().neq('Latitude', 0).and_().neq('Longitude', 0).eq("CurrentLap", lap) dataset = self.query(sessions=[session], channels=["Latitude", "Longitude"], data_filter=f) records = dataset.fetch_records() cache = [] for r in records: lat = r[1] lon = r[2] cache.append(GeoPoint.fromPoint(lat, lon)) self._session_location_cache[str(source_ref)] = cache Clock.schedule_once(lambda dt: callback(cache))
def _get_location_data(self, params): ''' Retrieve cached or query Location data as appropriate. ''' source_ref = params.source_ref source_key = str(source_ref) cache = self._session_location_cache.get(source_key) if cache == None: session = source_ref.session lap = source_ref.lap f = Filter().neq('Latitude', 0).and_().neq('Longitude', 0).eq("LapCount", lap) dataset = self.query(sessions = [session], channels = ["Latitude", "Longitude"], data_filter = f) records = dataset.fetch_records() cache = [] for r in records: lat = r[1] lon = r[2] cache.append(GeoPoint.fromPoint(lat, lon)) self._session_location_cache[source_key]=cache Clock.schedule_once(lambda dt: params.callback(cache))
def _create_session_name(self): """ Creates a session name attempting to use the nearby venue name first, then falling to a date stamp :return: String name """ nearby_venues = self._track_manager.find_nearby_tracks( GeoPoint.fromPoint(self._gps_sample.latitude, self._gps_sample.longitude)) session_names = [c.name for c in self._datastore.get_sessions()] # use the venue name if found nearby, otherwise use a date prefix = None if len(nearby_venues) == 0 else nearby_venues[0].name if prefix is None: prefix = format_date() # now find a unique name index = 1 while True: session_name = '{} - {}'.format(prefix, index) if session_name not in session_names: return session_name index += 1
def _on_finish_circuit(self): # close the circuit by adding the start point as the last point, # so there's no gap in the circuit first_point = self._track.map_points[0] self._add_trackmap_point( GeoPoint.fromPoint(first_point.latitude, first_point.longitude))
def _on_finish_circuit(self): # close the circuit by adding the start point as the last point, # so there's no gap in the circuit first_point = self._track.map_points[0] self._add_trackmap_point(GeoPoint.fromPoint(first_point.latitude, first_point.longitude))
class Track(object): def __init__(self, **kwargs): self.stale = False self.trackId = None self.trackType = TRACK_TYPE_CIRCUIT self.sectorCount = CONFIG_SECTOR_COUNT self.startLine = GeoPoint() self.finishLine = GeoPoint() self.sectors = [] def fromJson(self, trackJson): if trackJson: self.trackId = trackJson.get('id', self.trackId) self.trackType = trackJson.get('type', self.trackType) sectorsJson = trackJson.get('sec', None) del self.sectors[:] if self.trackType == TRACK_TYPE_CIRCUIT: self.startLine.fromJson(trackJson.get('sf', None)) sectorCount = CONFIG_SECTOR_COUNT_CIRCUIT else: self.startLine.fromJson(trackJson.get('st', self.startLine)) self.finishLine.fromJson(trackJson.get('fin', self.finishLine)) sectorCount = CONFIG_SECTOR_COUNT_STAGE returnedSectorCount = len(sectorsJson) if sectorsJson: for i in range(sectorCount): sector = GeoPoint() if i < returnedSectorCount: sectorJson = sectorsJson[i] sector.fromJson(sectorJson) self.sectors.append(sector) self.sectorCount = sectorCount self.stale = False @classmethod def fromTrackMap(cls, trackMap): t = Track() t.trackId = trackMap.short_id t.trackType = TRACK_TYPE_STAGE if trackMap.finish_point else TRACK_TYPE_CIRCUIT t.startLine = copy(trackMap.start_finish_point) t.finishLine = copy(trackMap.finish_point) maxSectorCount = CONFIG_SECTOR_COUNT_CIRCUIT if t.trackType == TRACK_TYPE_CIRCUIT else CONFIG_SECTOR_COUNT_STAGE sectorCount = 0 for point in trackMap.sector_points: sectorCount += 1 if sectorCount > maxSectorCount: break t.sectors.append(copy(point)) return t def toJson(self): sectors = [] for sector in self.sectors: sectors.append(sector.toJson()) trackJson = {} trackJson['id'] = self.trackId trackJson['type'] = self.trackType trackJson['sec'] = sectors if self.trackType == TRACK_TYPE_STAGE: trackJson['st'] = self.startLine.toJson() trackJson['fin'] = self.finishLine.toJson() else: trackJson['sf'] = self.startLine.toJson() return trackJson
def key_action(self, instance, keyboard, keycode, text, modifiers): if text == '`': # sekret! lat, lon = SimulatedTrackmap.get_simulated_point() point = GeoPoint.fromPoint(lat, lon) self._update_current_point(point)
def _race_setup(self): """ Logic tree for setting up a race event, including track map selection and automatic configuration """ # skip if this screen is not active if self.manager is not None and self.manager.current_screen != self: return # skip if we're not connected if not self._rc_api.connected: return # skip if GPS data is not good if self._gps_sample.gps_qual <= GpsConfig.GPS_QUALITY_NO_FIX: return track_cfg = self._rc_config.trackConfig auto_detect = track_cfg.autoDetect # skip if we haven't enabled auto detection if not auto_detect: return # what track is currently configured? current_track = TrackMap.from_track_cfg(track_cfg.track) # is the currently configured track in the list of nearby tracks? # if so, just keep this one tracks = self._track_manager.find_nearby_tracks( self._gps_sample.geopoint) prefs = self._settings.userPrefs last_track_set_time = datetime.datetime.fromtimestamp( prefs.get_last_selected_track_timestamp()) track_set_a_while_ago = datetime.datetime.now( ) > last_track_set_time + datetime.timedelta( days=DashboardView.AUTO_CONFIGURE_WAIT_PERIOD_DAYS) # is the currently configured track in the area? current_track_is_nearby = current_track.short_id in (t.short_id for t in tracks) # no need to re-detect a nearby track that was recently set if current_track_is_nearby and not track_set_a_while_ago: Logger.info( 'DashboardView: Nearby track was recently set, skipping auto configuration' ) return # we found only one track nearby, so select it and be done. if len(tracks) == 1: new_track = tracks[0] Logger.info('DashboardView: auto selecting track {}({})'.format( new_track.name, new_track.short_id)) track_cfg.track.import_trackmap(new_track) self._set_rc_track(track_cfg) return # ok. To prevent repeatedly pestering the user about asking to configure a track # check if the user last cancelled near the same location last_cancelled_location = GeoPoint.from_string( prefs.get_user_cancelled_location()) radius = last_cancelled_location.metersToDegrees( TrackManager.TRACK_DEFAULT_SEARCH_RADIUS_METERS, TrackManager.TRACK_DEFAULT_SEARCH_BEARING_DEGREES) if last_cancelled_location.withinCircle(self._gps_sample.geopoint, radius): Logger.info( "DashboardView: Still near the same location where the user last cancelled track configuration. Not pestering again" ) return # if we made it this far, we're going to ask the user to help select or create a track Clock.schedule_once(lambda dt: self._load_track_setup_view(track_cfg))
def _update_reference_mark(self): point = self.position self.ids.track.update_reference_mark( TrackMapGauge.REFERENCE_MARK_KEY, GeoPoint.fromPoint(point[0], point[1]))
def _draw_current_map(self): def _calc_heat_pct(heat_value, heat_min, heat_range): if heat_value is not None and heat_range > 0: return int(((heat_value - heat_min) / heat_range) * 100.0) else: return 0 left = self.pos[0] bottom = self.pos[1] self.canvas.clear() heat_width_step = dp(self.HEAT_MAP_WIDTH_STEP) path_count = len(self._scaled_paths.keys()) heat_width = dp(self.heat_width_scale * self.height) + ( (path_count - 1) * heat_width_step) with self.canvas: Color(*self.track_color) Line(points=self._scaled_map_points, width=dp(self.track_width_scale * self.height), closed=True, cap='round', joint='round') color_gradient = HeatColorGradient() # draw all of the traces for key, path_points in self._scaled_paths.iteritems(): heat_path = self._heat_map_values.get(key) if heat_path: # draw heat map point_count = len(path_points) heat_min = self.heat_min heat_range = self.heat_max - heat_min value_index = 0 current_heat_pct = 0 i = 0 line_points = [] try: line_points.extend( [path_points[i], path_points[i + 1]]) current_heat_pct = _calc_heat_pct( heat_path[value_index], heat_min, heat_range) while i < point_count - 2: heat_pct = _calc_heat_pct(heat_path[value_index], heat_min, heat_range) if heat_pct != current_heat_pct: heat_color = color_gradient.get_color_value( heat_pct / 100.0) Color(*heat_color) Line(points=line_points, width=heat_width, closed=False, joint='miter', cap='round') line_points = [ path_points[i - 2], path_points[i - 1] ] current_heat_pct = heat_pct line_points.extend( [path_points[i], path_points[i + 1]]) value_index += 1 i += 2 heat_width -= heat_width_step except IndexError: # if the number of heat values mismatch the heat map points, terminate early pass else: # draw regular map trace Color(*self._paths[key].color) Line(points=path_points, width=dp(self.path_width_scale * self.height), closed=True, cap='square', joint='miter') target_size = (self.target_width_scale * self.height) * self.target_scale # draw start point if GeoPoint.is_valid(self.start_point): Color(*self.start_point_color) scaled_point = self._scale_geopoint(self.start_point) Rectangle(texture=TrackMapView.start_image.texture, pos=self._center_point(scaled_point, (target_size, target_size)), size=[target_size, target_size]) # draw finish point if GeoPoint.is_valid(self.finish_point): Color(*self.finish_point_color) scaled_point = self._scale_geopoint(self.finish_point) Rectangle(texture=TrackMapView.finish_image.texture, pos=self._center_point(scaled_point, (target_size, target_size)), size=[target_size, target_size]) # draw the sector points sector_count = 0 for sector_point in self.sector_points: sector_count += 1 scaled_point = self._scale_geopoint(sector_point) label = CoreLabel(text='{:>2}'.format(sector_count), font_size=target_size * 0.8, font_name='resource/fonts/ASL_regular.ttf') label.refresh() texture = label.texture centered_point = self._center_point(scaled_point, texture.size) Color(*self.sector_point_color) Rectangle(source='resource/trackmap/sector_64px.png', pos=self._center_point(scaled_point, texture.size), size=[target_size, target_size]) Color(0.0, 0.0, 0.0, 1.0) # Tweak font position to improve centering. SHould be a better way to do this trim_x = texture.size[0] * 0.1 trim_y = -texture.size[1] * 0.05 Rectangle(size=texture.size, pos=(centered_point[0] + trim_x, centered_point[1] + trim_y), texture=texture) # draw the dynamic markers marker_size = (self.marker_width_scale * self.height) * self.marker_scale for key, marker_point in self._marker_points.iteritems(): scaled_point = self._scale_point(marker_point, self.height, left, bottom) Color(*marker_point.color) self._marker_locations[key] = Line(circle=(scaled_point.x, scaled_point.y, marker_size), width=marker_size, closed=True) Color(1.0, 1.0, 1.0, 1.0)
def _update_reference_mark(self): point = self.position self.ids.track.update_reference_mark(TrackMapGauge.REFERENCE_MARK_KEY, GeoPoint.fromPoint(point[0], point[1]))
def _race_setup(self): """ Logic tree for setting up a race event, including track map selection and automatic configuration """ # skip if this screen is not active if self.manager is not None and self.manager.current_screen != self: return # skip if we're not connected if not self._rc_api.connected: return # skip if GPS data is not good if self._gps_sample.gps_qual <= GpsConfig.GPS_QUALITY_NO_FIX: return track_cfg = self._rc_config.trackConfig auto_detect = track_cfg.autoDetect # skip if we haven't enabled auto detection if not auto_detect: return # what track is currently configured? current_track = TrackMap.from_track_cfg(track_cfg.track) # is the currently configured track in the list of nearby tracks? # if so, just keep this one tracks = self._track_manager.find_nearby_tracks(self._gps_sample.geopoint) prefs = self._settings.userPrefs last_track_set_time = datetime.datetime.fromtimestamp(prefs.get_last_selected_track_timestamp()) track_set_a_while_ago = datetime.datetime.now() > last_track_set_time + datetime.timedelta(days=DashboardView.AUTO_CONFIGURE_WAIT_PERIOD_DAYS) # is the currently configured track in the area? current_track_is_nearby = current_track.short_id in (t.short_id for t in tracks) # no need to re-detect a nearby track that was recently set if current_track_is_nearby and not track_set_a_while_ago: Logger.info('DashboardView: Nearby track was recently set, skipping auto configuration') return # we found only one track nearby, so select it and be done. if len(tracks) == 1: new_track = tracks[0] Logger.info('DashboardView: auto selecting track {}({})'.format(new_track.name, new_track.short_id)) track_cfg.track.import_trackmap(new_track) self._set_rc_track(track_cfg) return # ok. To prevent repeatedly pestering the user about asking to configure a track # check if the user last cancelled near the same location last_cancelled_location = GeoPoint.from_string(prefs.get_user_cancelled_location()) radius = last_cancelled_location.metersToDegrees(TrackManager.TRACK_DEFAULT_SEARCH_RADIUS_METERS, TrackManager.TRACK_DEFAULT_SEARCH_BEARING_DEGREES) if last_cancelled_location.withinCircle(self._gps_sample.geopoint, radius): Logger.info("DashboardView: Still near the same location where the user last cancelled track configuration. Not pestering again") return # if we made it this far, we're going to ask the user to help select or create a track Clock.schedule_once(lambda dt: self._load_track_setup_view(track_cfg))
def _draw_current_map(self): def _calc_heat_pct(heat_value, heat_min, heat_range): if heat_value is not None and heat_range > 0: return int(((heat_value - heat_min) / heat_range) * 100.0) else: return 0 left = self.pos[0] bottom = self.pos[1] self.canvas.clear() heat_width_step = self.HEAT_MAP_WIDTH_STEP path_count = len(self._scaled_paths.keys()) heat_width = (self.heat_width_scale * self.height) + ((path_count - 1) * heat_width_step) with self.canvas: Color(*self.track_color) Line(points=self._scaled_map_points, width=self.track_width_scale * self.height, closed=True, cap='round', joint='round') color_gradient = HeatColorGradient() # draw all of the traces for key, path_points in self._scaled_paths.iteritems(): heat_path = self._heat_map_values.get(key) if heat_path: # draw heat map point_count = len(path_points) heat_min = self.heat_min heat_range = self.heat_max - heat_min value_index = 0 current_heat_pct = 0 i = 0 line_points = [] try: line_points.extend([path_points[i], path_points[i + 1]]) current_heat_pct = _calc_heat_pct(heat_path[value_index], heat_min, heat_range) while i < point_count - 2: heat_pct = _calc_heat_pct(heat_path[value_index], heat_min, heat_range) if heat_pct != current_heat_pct: heat_color = color_gradient.get_color_value(heat_pct / 100.0) Color(*heat_color) Line(points=line_points, width=heat_width, closed=False, joint='miter', cap='round') line_points = [path_points[i - 2], path_points[i - 1]] current_heat_pct = heat_pct line_points.extend([path_points[i], path_points[i + 1]]) value_index += 1 i += 2 heat_width -= heat_width_step except IndexError: # if the number of heat values mismatch the heat map points, terminate early pass else: # draw regular map trace Color(*self._paths[key].color) Line(points=path_points, width=self.path_width_scale * self.height, closed=True, cap='square', joint='miter') target_size = (self.target_width_scale * self.height) * self.target_scale # draw start point if GeoPoint.is_valid(self.start_point): Color(*self.start_point_color) scaled_point = self._scale_geopoint(self.start_point) Rectangle(texture=TrackMapView.start_image.texture, pos=self._center_point(scaled_point, (target_size, target_size)), size=[target_size, target_size]) # draw finish point if GeoPoint.is_valid(self.finish_point): Color(*self.finish_point_color) scaled_point = self._scale_geopoint(self.finish_point) Rectangle(texture=TrackMapView.finish_image.texture, pos=self._center_point(scaled_point, (target_size, target_size)), size=[target_size, target_size]) # draw the sector points sector_count = 0 for sector_point in self.sector_points: sector_count += 1 scaled_point = self._scale_geopoint(sector_point) label = CoreLabel(text='{:>2}'.format(sector_count), font_size=target_size * 0.8, font_name='resource/fonts/ASL_regular.ttf') label.refresh() texture = label.texture centered_point = self._center_point(scaled_point, texture.size) Color(*self.sector_point_color) Rectangle(source='resource/trackmap/sector_64px.png', pos=self._center_point(scaled_point, texture.size), size=[target_size, target_size]) Color(0.0, 0.0, 0.0, 1.0) # Tweak font position to improve centering. SHould be a better way to do this trim_x = texture.size[0] * 0.1 trim_y = -texture.size[1] * 0.05 Rectangle(size=texture.size, pos=(centered_point[0] + trim_x, centered_point[1] + trim_y), texture=texture) # draw the dynamic markers marker_size = (self.marker_width_scale * self.height) * self.marker_scale for key, marker_point in self._marker_points.iteritems(): scaled_point = self._scale_point(marker_point, self.height, left, bottom) Color(*marker_point.color) self._marker_locations[key] = Line(circle=(scaled_point.x, scaled_point.y, marker_size), width=marker_size, closed=True) Color(1.0, 1.0, 1.0, 1.0)