def calculate_segment_radii(self, segments): # Special case: If only one segment, just use a static large 'straight' # radius, there is no curve. if len(segments) == 1: segments[0]['radius'] = 1000000 i = 0 while i < len(segments): first_segment = segments[i] i = i + 1 if 'length' not in first_segment: first_segment['length'] = distance_on_earth(first_segment['start'][0], first_segment['start'][1], first_segment['end'][0], first_segment['end'][1] ) if i < len(segments): second_segment = segments[i] if 'length' not in second_segment: second_segment['length'] = distance_on_earth(second_segment['start'][0], second_segment['start'][1], second_segment['end'][0], second_segment['end'][1] ) else: second_segment = None if second_segment: base_length = distance_on_earth(first_segment['start'][0], first_segment['start'][1], second_segment['end'][0], second_segment['end'][1] ) else: base_length = None # ignore curvature from zero-distance if first_segment['length'] > 0 and second_segment and second_segment['length'] > 0 and base_length > 0: # Circumcircle radius calculation from http://www.mathopenref.com/trianglecircumcircle.html a = first_segment['length'] b = second_segment['length'] c = base_length r = (a * b * c)/math.sqrt(math.fabs((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c))) else: r = 1000000 # The first segment only is part of one triangle, so just use that radius. # Note that 1 is the first segment since we've already incremented i above. if i == 1: first_segment['radius'] = r # Otherwise, set the radius of the previous segment to the smaller radius of the two circumcircles it's a part of. # An alternative implementation would be to average the radii or do some sort # of weighted average, but I think I chose to use the shorter radius as curves # are often followed by long straight-aways, and this method seemed to work well # with the data. else: if first_segment['radius'] > r: first_segment['radius'] = r # If there is a second segment, set its initial radius to that of this first triangle. if second_segment: second_segment['radius'] = r
def calculate_segment_radii(self, segments): # Special case: If only one segment, just use a static large 'straight' # radius, there is no curve. if len(segments) == 1: segments[0]['radius'] = 1000000 i = 0 while i < len(segments): first_segment = segments[i] i = i + 1 if 'length' not in first_segment: first_segment['length'] = distance_on_earth(first_segment['start'][0], first_segment['start'][1], first_segment['end'][0], first_segment['end'][1] ) if i < len(segments): second_segment = segments[i] if 'length' not in second_segment: second_segment['length'] = distance_on_earth(second_segment['start'][0], second_segment['start'][1], second_segment['end'][0], second_segment['end'][1] ) else: second_segment = None if second_segment: base_length = distance_on_earth(first_segment['start'][0], first_segment['start'][1], second_segment['end'][0], second_segment['end'][1] ) else: base_length = None if second_segment: r = circum_circle_radius(first_segment['length'], second_segment['length'], base_length) else: r = 10000 # The first segment only is part of one triangle, so just use that radius. # Note that 1 is the first segment since we've already incremented i above. if i == 1: first_segment['radius'] = r # Otherwise, set the radius of the previous segment to the smaller radius of the two circumcircles it's a part of. # An alternative implementation would be to average the radii or do some sort # of weighted average, but I think I chose to use the shorter radius as curves # are often followed by long straight-aways, and this method seemed to work well # with the data. else: if first_segment['radius'] > r: first_segment['radius'] = r # If there is a second segment, set its initial radius to that of this first triangle. if second_segment: second_segment['radius'] = r
def calculate_segment_radii(self, segments): # Special case: If only one segment, just use a static large 'straight' # radius, there is no curve. if len(segments) == 1: segments[0]['radius'] = 1000000 i = 0 while i < len(segments): first_segment = segments[i] i = i + 1 if 'length' not in first_segment: first_segment['length'] = distance_on_earth( first_segment['start'][0], first_segment['start'][1], first_segment['end'][0], first_segment['end'][1]) if i < len(segments): second_segment = segments[i] if 'length' not in second_segment: second_segment['length'] = distance_on_earth( second_segment['start'][0], second_segment['start'][1], second_segment['end'][0], second_segment['end'][1]) else: second_segment = None if second_segment: base_length = distance_on_earth(first_segment['start'][0], first_segment['start'][1], second_segment['end'][0], second_segment['end'][1]) else: base_length = None if second_segment: r = circum_circle_radius(first_segment['length'], second_segment['length'], base_length) else: r = 10000 # The first segment only is part of one triangle, so just use that radius. # Note that 1 is the first segment since we've already incremented i above. if i == 1: first_segment['radius'] = r # Otherwise, set the radius of the previous segment to the smaller radius of the two circumcircles it's a part of. # An alternative implementation would be to average the radii or do some sort # of weighted average, but I think I chose to use the shorter radius as curves # are often followed by long straight-aways, and this method seemed to work well # with the data. else: if first_segment['radius'] > r: first_segment['radius'] = r # If there is a second segment, set its initial radius to that of this first triangle. if second_segment: second_segment['radius'] = r
def filter_deflection_of_straight_segments(self, segments, start_index, look_ahead): if look_ahead < 3: raise ValueError("look_ahead must be 3 or more") try: first_straight = segments[start_index] next_straight = segments[start_index + look_ahead] # if (first_straight['curvature_level'] and not 'curvature_filtered' in first_straight) or (next_straight['curvature_level'] and not 'curvature_filtered' in next_straight): if (first_straight['curvature_level'] and not 'curvature_filtered' in first_straight) or (next_straight['curvature_level'] and not 'curvature_filtered' in next_straight): return heading_a = self.get_segment_heading(first_straight) heading_b = self.get_segment_heading(next_straight) heading_diff = abs(heading_a - heading_b) # Compare the difference in heading to the angle that wold be expected # for a curve just barely meeting our threshold for straight/curved. gap_distance = distance_on_earth(first_straight['end'][0], first_straight['end'][1], next_straight['start'][0], next_straight['start'][1]) min_variance = gap_distance / self.level_1_max_radius if abs(heading_diff) < min_variance: # Mark them as curvature_filtered so that we can show them in the output for i in range(start_index, start_index + look_ahead): if segments[i]['curvature_level']: segments[i]['curvature_filtered'] = True if not self.keep_eliminated: # unset the curvature level of the intermediate segments for i in range(start_index, start_index + look_ahead): segments[i]['curvature_level'] = 0 segments[i]['curvature'] = 0 except IndexError: return
def calculate_segment_radii(self, segments): # Special case: If only one segment, just use a static large 'straight' # radius, there is no curve. if len(segments) == 1: segments[0]['radius'] = AddSegmentLengthAndRadius.MAX_RADIUS for i, segment in enumerate(segments): next_index = i + 1 if next_index < len(segments): next_segment = segments[next_index] base_length = distance_on_earth(segment['start'][0], segment['start'][1], next_segment['end'][0], next_segment['end'][1]) radius = circum_circle_radius(segment['length'], next_segment['length'], base_length) # The first segment only is part of one triangle, so just use that radius. # Note that 1 is the first segment since we've already incremented i above. # Otherwise, set the radius of the previous segment to the smaller radius of the two circumcircles it's a part of. # An alternative implementation would be to average the radii or do some sort # of weighted average, but I think I chose to use the shorter radius as curves # are often followed by long straight-aways, and this method seemed to work well # with the data. if i == 0: segment['radius'] = radius elif segment['radius'] > radius: segment['radius'] = radius next_segment['radius'] = radius else: if segment['radius'] > AddSegmentLengthAndRadius.MAX_RADIUS: segment['radius'] = AddSegmentLengthAndRadius.MAX_RADIUS
def calculate_length(self, segments): for segment in segments: segment['length'] = distance_on_earth( segment['start'][0], segment['start'][1], segment['end'][0], segment['end'][1] )
def process(self, iterable): for collection in iterable: for way in collection['ways']: all_segments = way['segments'] last_index = len(all_segments) - 1 indexes = [i for i, segment in enumerate(all_segments) if i == 0 or i == last_index or self.select_segment(segment) ] way['segments'] = filtered_segments = [all_segments[i] for i in indexes] for i, segment in enumerate(way['segments']): if i + 1 < len(way['segments']): segment['end'] = end = filtered_segments[i + 1]['start'] start = segment['start'] segment['length'] = distance_on_earth(start[0], start[1], end[0], end[1]) yield(collection)
def process(self, iterable): for collection in iterable: for way in collection['ways']: all_segments = way['segments'] last_index = len(all_segments) - 1 indexes = [ i for i, segment in enumerate(all_segments) if i == 0 or i == last_index or self.select_segment(segment) ] way['segments'] = filtered_segments = [ all_segments[i] for i in indexes ] for i, segment in enumerate(way['segments']): if i + 1 < len(way['segments']): segment['end'] = end = filtered_segments[i + 1]['start'] start = segment['start'] segment['length'] = distance_on_earth( start[0], start[1], end[0], end[1]) yield (collection)
def calculate_length(self, segments): for segment in segments: segment['length'] = distance_on_earth(segment['start'][0], segment['start'][1], segment['end'][0], segment['end'][1])