findRadarPoint static method
Find radar chart point at tap location.
Searches through all radar data sets to find the point closest to the tap position within the specified tap radius. Radar charts have points arranged in a circle.
Parameters:
tapPosition- The position where the user tappeddataSets- List of radar data sets to search throughsize- Size of the chart areamaxValue- Maximum value for scaling radar pointsanimationProgress- Animation progress value (0.0 to 1.0)
Returns a ChartInteractionResult if a point is found, null otherwise.
Implementation
static ChartInteractionResult? findRadarPoint(
Offset tapPosition,
List<RadarDataSet> dataSets,
Size size,
double maxValue,
double animationProgress,
) {
if (dataSets.isEmpty) return null;
if (!_isValidSize(size) || !_isValidPosition(tapPosition)) {
return null;
}
if (!_isValidPositiveValue(maxValue) ||
!animationProgress.isFinite ||
animationProgress < 0.0 ||
animationProgress > 1.0) {
return null;
}
final firstDataSet = dataSets.first;
// Note: RadarDataSet has dataPoints property (list), not dataPoint
// This matches the usage in radar_chart_painter.dart
final numAxes = firstDataSet.dataPoints.length;
if (numAxes < 3) return null;
final center = Offset(size.width / 2, size.height / 2);
final radius = math.min(size.width, size.height) / 2 - _radarRadiusOffset;
if (!_isValidPositiveValue(radius)) return null;
// Pre-calculate constants
final tapRadius = ChartInteractionConstants.tapRadius;
final tapRadiusSquared = tapRadius * tapRadius;
const piOver2 = math.pi / 2;
const twoPi = 2 * math.pi;
final angleStep = twoPi / numAxes;
double minDistanceSquared = double.infinity;
ChartInteractionResult? nearestResult;
for (int dsIndex = 0; dsIndex < dataSets.length; dsIndex++) {
final dataSet = dataSets[dsIndex];
if (dataSet.dataPoints.length != numAxes) continue;
for (int ptIndex = 0; ptIndex < numAxes; ptIndex++) {
final radarPoint = dataSet.dataPoints[ptIndex];
if (!radarPoint.value.isFinite) continue;
// Calculate angle and point position
final angle = angleStep * ptIndex - piOver2;
final value = radarPoint.value.clamp(0.0, maxValue);
final normalizedValue = (value / maxValue) * animationProgress;
final pointRadius = radius * normalizedValue;
final point = Offset(
center.dx + pointRadius * math.cos(angle),
center.dy + pointRadius * math.sin(angle),
);
// Quick bounds check before distance calculation
if (!_isWithinQuickBounds(tapPosition, point, tapRadius)) {
continue;
}
// Calculate squared distance using helper
final distanceSquared = _squaredDistance(tapPosition, point);
if (distanceSquared == null) continue;
// Update nearest result if closer
if (distanceSquared < tapRadiusSquared &&
distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
// Convert RadarDataPoint to ChartDataPoint for compatibility
final chartPoint = ChartDataPoint(
x: ptIndex.toDouble(),
y: radarPoint.value,
label: radarPoint.label,
);
nearestResult = ChartInteractionResult(
point: chartPoint,
datasetIndex: dsIndex,
elementIndex: ptIndex,
isHit: true,
);
}
}
}
return nearestResult;
}