|
import os |
|
from shapely.geometry import Polygon |
|
|
|
class DamageCalculator: |
|
def __init__(self): |
|
self.cost_ranges = { |
|
"Scratch": { |
|
"Minor": (1000, 3000), |
|
"Moderate": (3000, 5000), |
|
"Severe": (5000, 10000) |
|
}, |
|
"Dent": { |
|
"Minor": (2000, 4000), |
|
"Moderate": (4000, 10000), |
|
"Severe": (10000, 15000) |
|
}, |
|
"Paint chip": { |
|
"Minor": (1000, 2000), |
|
"Moderate": (2000, 4000), |
|
"Severe": (4000, 10000) |
|
}, |
|
"Broken part": (1000, 7000) |
|
} |
|
|
|
def parse_coordinates(self, file_path): |
|
polygons = [] |
|
class_names = [] |
|
with open(file_path, 'r') as file: |
|
for line in file: |
|
parts = line.strip().split() |
|
class_name = [] |
|
coordinates = [] |
|
for part in parts: |
|
try: |
|
coordinates.append(float(part)) |
|
except ValueError: |
|
class_name.append(part) |
|
if class_name and coordinates: |
|
class_name = " ".join(class_name) |
|
try: |
|
if len(coordinates) % 2 != 0: |
|
raise ValueError("Coordinates are not in pairs.") |
|
polygon = Polygon([(coordinates[i], coordinates[i+1]) for i in range(0, len(coordinates), 2)]) |
|
polygons.append(polygon) |
|
class_names.append(class_name) |
|
except ValueError as e: |
|
print(f"Skipping line due to error: {e}") |
|
else: |
|
print(f"Skipping line due to insufficient data: {line.strip()}") |
|
return class_names, polygons |
|
|
|
def calculate_severity(self, coverage_percentage): |
|
if 3 < coverage_percentage <= 30: |
|
return "Minor" |
|
elif 30 < coverage_percentage <= 60: |
|
return "Moderate" |
|
elif coverage_percentage > 60: |
|
return "Severe" |
|
return "N/A" |
|
|
|
def calculate_cost(self, damage_class, severity): |
|
if damage_class == "Broken part": |
|
return self.cost_ranges["Broken part"] |
|
elif severity in self.cost_ranges[damage_class]: |
|
return self.cost_ranges[damage_class][severity] |
|
return (0, 0) |
|
|
|
def summarize_damage_by_part(self, damage_polygons, part_polygons): |
|
intersection_info = self.calculate_intersection_area(damage_polygons, part_polygons) |
|
|
|
summary = {} |
|
for info in intersection_info: |
|
part_class = info['part_class'] |
|
damage_class = info['damage_class'] |
|
coverage_percentage = info['coverage_percentage'] |
|
|
|
if part_class not in summary: |
|
summary[part_class] = {'total_coverage': 0, 'damage_types': {}} |
|
|
|
summary[part_class]['total_coverage'] += coverage_percentage |
|
|
|
if damage_class not in summary[part_class]['damage_types']: |
|
summary[part_class]['damage_types'][damage_class] = 0 |
|
|
|
summary[part_class]['damage_types'][damage_class] += coverage_percentage |
|
|
|
for part_class in summary: |
|
total_coverage = summary[part_class]['total_coverage'] |
|
for damage_class in summary[part_class]['damage_types']: |
|
summary[part_class]['damage_types'][damage_class] = ( |
|
summary[part_class]['damage_types'][damage_class] / total_coverage * 100 |
|
) |
|
|
|
summary[part_class]['undamaged'] = 100 - total_coverage |
|
|
|
return summary |
|
|
|
def calculate_intersection_area(self, damage_polygons, part_polygons): |
|
intersection_info = [] |
|
front_back_door_detected = any(part_class in ['Front-door', 'Back-door'] for part_class, _ in part_polygons) |
|
|
|
for damage_class, damage_polygon in damage_polygons: |
|
for part_class, part_polygon in part_polygons: |
|
if damage_polygon.intersects(part_polygon): |
|
intersection = damage_polygon.intersection(part_polygon) |
|
intersection_area = intersection.area |
|
part_area = part_polygon.area |
|
coverage_percentage = (intersection_area / part_area) * 100 |
|
|
|
|
|
if coverage_percentage <= 3: |
|
continue |
|
|
|
|
|
if part_class in ['Front-bumper', 'Back-bumper']: |
|
if front_back_door_detected: |
|
coverage_percentage *= 0.2 |
|
else: |
|
coverage_percentage *= 0.6 |
|
|
|
if coverage_percentage <= 3: |
|
continue |
|
|
|
|
|
if part_class in ['Headlight', 'Tail-light']: |
|
if damage_class == 'Broken part' and coverage_percentage > 50: |
|
intersection_info.append({ |
|
"damage_class": damage_class, |
|
"part_class": part_class, |
|
"intersection_area": intersection_area, |
|
"part_area": part_area, |
|
"coverage_percentage": coverage_percentage |
|
}) |
|
continue |
|
|
|
|
|
if part_class in ['Front-wheel', 'Back-wheel', 'License-plate']: |
|
continue |
|
|
|
intersection_info.append({ |
|
"damage_class": damage_class, |
|
"part_class": part_class, |
|
"intersection_area": intersection_area, |
|
"part_area": part_area, |
|
"coverage_percentage": coverage_percentage |
|
}) |
|
|
|
|
|
summarized_info = {} |
|
for info in intersection_info: |
|
key = (info['damage_class'], info['part_class']) |
|
if key not in summarized_info: |
|
summarized_info[key] = { |
|
"intersection_area": 0, |
|
"part_area": info['part_area'], |
|
"coverage_percentage": 0, |
|
"count": 0 |
|
} |
|
summarized_info[key]["intersection_area"] += info["intersection_area"] |
|
summarized_info[key]["coverage_percentage"] += info["coverage_percentage"] |
|
summarized_info[key]["count"] += 1 |
|
|
|
final_info = [] |
|
for (damage_class, part_class), values in summarized_info.items(): |
|
part_area = values["part_area"] |
|
intersection_area = values["intersection_area"] |
|
coverage_percentage = values["coverage_percentage"] |
|
count = values["count"] |
|
severity = self.calculate_severity(coverage_percentage) |
|
cost_min, cost_max = self.calculate_cost(damage_class, severity) |
|
final_info.append({ |
|
"damage_class": damage_class, |
|
"part_class": part_class, |
|
"intersection_area": intersection_area, |
|
"part_area": part_area, |
|
"coverage_percentage": coverage_percentage, |
|
"severity": severity, |
|
"cost_min": cost_min, |
|
"cost_max": cost_max, |
|
"count": count |
|
}) |
|
|
|
return final_info |
|
|