If I have the following chart in Flutter:
Where the green graph is a Path
object with many lineTo
segments, how do I find the y-coordinate for a point with a given x-coordinate?
As you can see in the image, there is a gray dotted line at a specific point on the x-axis and I want to draw a point where it intersects with the green graph.
Here is an example path:
final path = Path();
path.moveTo(0, 200);
path.lineTo(10, 210);
path.lineTo(30, 190);
path.lineTo(55, 150);
path.lineTo(80, 205);
path.lineTo(100, 0);
And I want to find the y-coordinate for the point at dx = 75
.
The easiest way to achieve this for any path that only has a single point for every x
(i.e. where there is only a single graph / line from left to right) is using the binary search algorithm.
You can then simply use the distance of the path, which is obtained using Path.computeMetrics
, to perform binary search and find the offset via Path.getTangentForOffset
:
const searchDx = 75;
const iterations = 12;
final pathMetric = path.computeMetrics().first;
final pathDistance = pathMetric.length;
late Offset closestOffset;
var closestDistance = pathDistance / 2;
for (var n = 1; n <= iterations; n++) {
closestOffset = pathMetric.getTangentForOffset(closestDistance)!.position;
if (closestOffset.dx == searchDx) break;
final change = pathDistance / pow(2, n);
if (closestOffset.dx < searchDx) {
closestDistance += change;
} else {
closestDistance -= change;
}
}
print(closestOffset); // Offset(75.0, 193.9)
Note that if you want to run significantly more iterations (which should not be necessary due to the nature of binary search), you should replace final change = pathDistance / pow(2, n);
by a cheaper operation like storing the left and right points of your current search interval.
You can find the full working code as an example on Dartpad.