Пример #1
0
def calculate_projection_to_nearest_row(codes, rows):
    
    # Copy rows so we can add temporary fields without modifying original
    rows = copy.copy(rows)
    
    CodeWithProjection = namedtuple('CodeWithProjection', 'code projection')
    codes_with_projections = []
    
    # Order codes and rows from left to right
    codes = sorted(codes, key=lambda c: c.field_position[0])
    rows = sorted(rows, key=lambda r: r.center_field_position[0])
    
    for row in rows:
        row.ordered_items = [row.start_code, row.end_code]
    
    for code in codes:
        
        rows_with_distance_to_code = [(row, abs(row.center_field_position[0] - code.field_position[0])) for row in rows]
        sorted_rows_with_distance_to_code = sorted(rows_with_distance_to_code, key=lambda r: r[1])
        closest_rows_to_code = [row[0] for row in sorted_rows_with_distance_to_code[:4]]
        
        min_distance = sys.float_info.max
        closest_row = None
        closest_after_in_closest_row = None
        for row in closest_rows_to_code:
            
            closest_beneath = None
            closest_after = None
            for item in row.ordered_items:
                if code.field_position[1] > item.field_position[1]:
                    closest_beneath = item
                else:
                    closest_after = item
                    break

            if closest_beneath is None or closest_after is None:
                continue # not in this row for sure

            distance_to_code, _ = lateral_and_projection_distance_2d(code.field_position, closest_beneath.field_position, closest_after.field_position)
            distance_to_code = abs(distance_to_code)
            
            if distance_to_code < min_distance:
                min_distance = distance_to_code
                closest_after_in_closest_row = closest_after
                closest_row = row
                
        if closest_row is not None and min_distance < 3: # TODO remove hard-coded value
            
            _, row_projection = lateral_and_projection_distance_2d(code.field_position, row.start_code.field_position, row.end_code.field_position)
            
            closest_item_idx = closest_row.ordered_items.index(closest_after_in_closest_row)
            closest_row.ordered_items.insert(closest_item_idx, code)
            
            code.row = closest_row.number
            codes_with_projections.append(CodeWithProjection(code, row_projection))
        else:
            code.row = -1
            print "Couldn't find a row for code {}. Closest row is {} meters away.".format(code.name, min_distance)
        
    return codes_with_projections
Пример #2
0
 def filter_plants_by_segment_part(self, segment_part):
     
     possible_plants = segment_part.possible_plants
     
     for plant in possible_plants:
         lateral_distance, projection_distance = lateral_and_projection_distance_2d(plant['position'], segment_part.start.position, segment_part.end.position)
         plant['lateral'] = lateral_distance
         plant['projection'] = projection_distance
     
     # Order from start to end code
     possible_plants = sorted(possible_plants, key=lambda p: p['projection'])
     
     # Throw out any that are too close to or behind start/end code
     if segment_part.start.type == 'GroupCode':
         closest_at_start = self.closest_group_code_spacing
     elif segment_part.start.type == 'RowCode':
         closest_at_start = self.closest_row_code_spacing 
     else:
         closest_at_start = self.closest_plant_spacing
         
     if segment_part.start.type == 'GroupCode':
         closest_at_end = segment_part.length - self.closest_group_code_spacing
     elif segment_part.start.type == 'RowCode':
         closest_at_end = segment_part.length - self.closest_row_code_spacing 
     else:
         closest_at_end = segment_part.length - self.closest_plant_spacing
 
     filtered_plants = [p for p in possible_plants if p['projection'] >= closest_at_start and p['projection'] <= closest_at_end]
 
     return filtered_plants
Пример #3
0
 def split_segment_into_parts(self, segment_part, forward_plant, reverse_plant):
     
     if not forward_plant or not reverse_plant:
         return [] # Can't split up any more. 
     
     # First change reverse plant projection to be in the forward direction to make it consistent.
     _, reverse_plant.projection = lateral_and_projection_distance_2d(reverse_plant.position, segment_part.start.position,
                                                                         segment_part.end.position)
     
     projection_difference = reverse_plant.projection - forward_plant.projection
     
     selected_plants = []
     if abs(projection_difference) < 0.0001:
         # Segments split on same plant so it doesn't matter which one we choose.
         selected_plants = [forward_plant]
     elif projection_difference > self.closest_plant_spacing:
         # Normal case where forward/reverse don't overlap. We should now have 3 segments.
         selected_plants = [forward_plant, reverse_plant]
     else:
         # Forward/reverse overlap.  Need to decide which one to use.
         if forward_plant.type == 'CreatedPlant' and reverse_plant.type == 'CreatedPlant':
             avg_position = np.mean([forward_plant.position, reverse_plant.position], axis=0)
             avg_plant = CreatedPlant(name='plant', position=avg_position, zone=forward_plant.zone)
             avg_plant.projection = np.mean([forward_plant.projection, reverse_plant.projection], axis=0)
             selected_plants = [avg_plant]
         elif forward_plant.type == 'Plant' and reverse_plant.type == 'Plant':
             if forward_plant.penalty < reverse_plant.penalty:
                 selected_plants = [forward_plant]
             else:
                 selected_plants = [reverse_plant]
         elif forward_plant.type == 'Plant':
             selected_plants = [forward_plant]
         elif reverse_plant.type == 'Plant':
             selected_plants = [reverse_plant]
         else:
             assert(False)
     
     if len(selected_plants) == 0:
         return []
     elif len(selected_plants) == 1:
         selected_plant = selected_plants[0]
         first_subpart = SegmentPart(start=segment_part.start, end=selected_plant)
         second_subpart = SegmentPart(start=selected_plant, end=segment_part.end)
         before_plants, after_plants = self.split_possible_plants_by_projections(segment_part.possible_plants, [selected_plant.projection])
         first_subpart.possible_plants = before_plants
         second_subpart.possible_plants = after_plants
         return [first_subpart, second_subpart]
     elif len(selected_plants) == 2:
         first_subpart = SegmentPart(start=segment_part.start, end=selected_plants[0])
         second_subpart = SegmentPart(start=selected_plants[0], end=selected_plants[1])
         third_subpart = SegmentPart(start=selected_plants[1], end=segment_part.end)
         first_subpart.possible_plants, second_subpart.possible_plants, third_subpart.possible_plants = \
             self.split_possible_plants_by_projections(segment_part.possible_plants, [selected_plants[0].projection, selected_plants[1].projection])
         return [first_subpart, second_subpart, third_subpart]
     else:
         assert(False)