Поменял усреднение

This commit is contained in:
2025-12-02 11:47:47 +03:00
parent b9e17df32c
commit a18071b7ec
3 changed files with 465 additions and 610 deletions

View File

@@ -317,7 +317,7 @@ class PointsAveragingAPIView(LoginRequiredMixin, View):
})
# Apply clustering algorithm
avg_coord, valid_indices = self._find_cluster_center(points_data)
avg_coord, valid_indices, avg_type = self._find_cluster_center(points_data)
# Mark outliers and calculate distances
outliers = []
@@ -391,6 +391,7 @@ class PointsAveragingAPIView(LoginRequiredMixin, View):
'has_outliers': len(outliers) > 0,
'avg_coordinates': avg_coords_str,
'avg_coord_tuple': avg_coord,
'avg_type': avg_type,
'avg_time': median_time_str,
'frequency': first_point.get('frequency', '-'),
'freq_range': first_point.get('freq_range', '-'),
@@ -414,13 +415,13 @@ class PointsAveragingAPIView(LoginRequiredMixin, View):
If only 1 point, return it as center.
Returns:
tuple: (avg_coord, set of valid point indices)
tuple: (avg_coord, set of valid point indices, avg_type)
"""
if len(points_data) == 0:
return (0, 0), set()
return (0, 0), set(), "ГК"
if len(points_data) == 1:
return points_data[0]['coord_tuple'], {0}
return points_data[0]['coord_tuple'], {0}, "ГК"
# Step 1: Take first point as reference
first_coord = points_data[0]['coord_tuple']
@@ -435,35 +436,32 @@ class PointsAveragingAPIView(LoginRequiredMixin, View):
valid_indices.add(i)
# Step 3: Calculate average of all valid points using Gauss-Kruger projection
avg_coord = self._calculate_average_from_indices(points_data, valid_indices)
avg_coord, avg_type = self._calculate_average_from_indices(points_data, valid_indices)
return avg_coord, valid_indices
return avg_coord, valid_indices, avg_type
def _calculate_average_from_indices(self, points_data, indices):
"""
Calculate average coordinate from points at given indices.
Uses arithmetic averaging in Gauss-Kruger projection.
Uses arithmetic averaging in Gauss-Kruger or UTM projection.
Algorithm:
1. Determine GK zone from the first point
2. Transform all coordinates to GK projection
3. Calculate arithmetic mean of X and Y
4. Transform result back to WGS84
Returns:
tuple: (avg_coord, avg_type) where avg_type is "ГК", "UTM" or "Геод"
"""
indices_list = sorted(indices)
if not indices_list:
return (0, 0)
return (0, 0), "ГК"
if len(indices_list) == 1:
return points_data[indices_list[0]]['coord_tuple']
return points_data[indices_list[0]]['coord_tuple'], "ГК"
# Collect coordinates for averaging
coords = [points_data[idx]['coord_tuple'] for idx in indices_list]
# Use Gauss-Kruger projection for averaging
avg_coord = average_coords_in_gk(coords)
# Use Gauss-Kruger/UTM projection for averaging
avg_coord, avg_type = average_coords_in_gk(coords)
return avg_coord
return avg_coord, avg_type
class RecalculateGroupAPIView(LoginRequiredMixin, View):
@@ -489,7 +487,7 @@ class RecalculateGroupAPIView(LoginRequiredMixin, View):
# If include_all is False, use only non-outlier points and apply clustering
if include_all:
# Average all points - no outliers, all points are valid
avg_coord = self._calculate_average_from_indices(points, set(range(len(points))))
avg_coord, avg_type = self._calculate_average_from_indices(points, set(range(len(points))))
valid_indices = set(range(len(points)))
else:
# Filter out outliers first
@@ -499,7 +497,7 @@ class RecalculateGroupAPIView(LoginRequiredMixin, View):
return JsonResponse({'error': 'No valid points after filtering'}, status=400)
# Apply clustering algorithm
avg_coord, valid_indices = self._find_cluster_center(points)
avg_coord, valid_indices, avg_type = self._find_cluster_center(points)
# Mark outliers and calculate distances
for i, point in enumerate(points):
@@ -560,6 +558,7 @@ class RecalculateGroupAPIView(LoginRequiredMixin, View):
'success': True,
'avg_coordinates': avg_coords_str,
'avg_coord_tuple': avg_coord,
'avg_type': avg_type,
'total_points': len(points),
'valid_points_count': len(valid_points),
'outliers_count': len(outliers),
@@ -575,13 +574,13 @@ class RecalculateGroupAPIView(LoginRequiredMixin, View):
1. Take the first point as reference
2. Find all points within 56 km of the first point
3. Calculate average of all found points using Gauss-Kruger projection
4. Return final average and indices of valid points
4. Return final average, indices of valid points, and averaging type
"""
if len(points) == 0:
return (0, 0), set()
return (0, 0), set(), "ГК"
if len(points) == 1:
return tuple(points[0]['coord_tuple']), {0}
return tuple(points[0]['coord_tuple']), {0}, "ГК"
# Step 1: Take first point as reference
first_coord = tuple(points[0]['coord_tuple'])
@@ -595,27 +594,30 @@ class RecalculateGroupAPIView(LoginRequiredMixin, View):
if distance <= RANGE_DISTANCE:
valid_indices.add(i)
# Step 3: Calculate average of all valid points using Gauss-Kruger projection
avg_coord = self._calculate_average_from_indices(points, valid_indices)
# Step 3: Calculate average of all valid points
avg_coord, avg_type = self._calculate_average_from_indices(points, valid_indices)
return avg_coord, valid_indices
return avg_coord, valid_indices, avg_type
def _calculate_average_from_indices(self, points, indices):
"""
Calculate average coordinate from points at given indices.
Uses arithmetic averaging in Gauss-Kruger projection.
Uses arithmetic averaging in Gauss-Kruger or UTM projection.
Returns:
tuple: (avg_coord, avg_type)
"""
indices_list = sorted(indices)
if not indices_list:
return (0, 0)
return (0, 0), "ГК"
if len(indices_list) == 1:
return tuple(points[indices_list[0]]['coord_tuple'])
return tuple(points[indices_list[0]]['coord_tuple']), "ГК"
# Collect coordinates for averaging
coords = [tuple(points[idx]['coord_tuple']) for idx in indices_list]
# Use Gauss-Kruger projection for averaging
avg_coord = average_coords_in_gk(coords)
# Use Gauss-Kruger/UTM projection for averaging
avg_coord, avg_type = average_coords_in_gk(coords)
return avg_coord
return avg_coord, avg_type