1

According to the documentation for Path:

Closed sub-paths enclose a (possibly discontiguous) region of the plane based on the current fillType.

As far as I understand this implies that when a Path object is closed it surrounds a two dimensional area.

When the user clicks on a point of the screen I want to calculate the distance between the point that the user clicks and the area that's surrounded by the path. I get the point that the user clicks via GestureDetector/onPanDown but I have trouble figuring out how to calculate the distance to the path (or the area surrounded by the path). All the functions that Path offers seem to return void or bool but no distances.

Imagine for illustration: (red is the Path object when I draw it to the screen and the X is supposed to be where my user clicks; the distance between the two represented by the green line is what I'm interested in) enter image description here

How do I calculate the distance?

Christian
  • 25,249
  • 40
  • 134
  • 225
  • It could be possible using the list of points the path is made of but unfortunately there is no API for that. – Amir_P Apr 16 '21 at 17:47
  • *"How do I calculate the distance?"* - check [Bezier.nearestTValue](https://pub.dev/documentation/bezier/latest/bezier/Bezier/nearestTValue.html) – pskink Apr 17 '21 at 06:55
  • 1
    You can do it manually with the list of points that makes the path. but the Path object does not support this currently. Is this acceptable? Please show more details about the question, for example, is the path made up of segments of made up of bezier curves? – ch271828n Apr 19 '21 at 11:41
  • @ch271828n I have a Flutter Path object that I get from Rive and no access to the individual points. Path, unfortunately doesn't allow easy access to the points on it. Maybe there's a way to draw the path on a canvas and then read that. – Christian Apr 20 '21 at 16:26
  • @Christian Rive must internally store the individual points. Thus, I suggest hack the Rive code, and expose those points to your code and use them. Indeed, I have done such hacking several times, for example, copy-and-paste the official TextField code, edit it, and create my own MyTextField to add features to existing flutter code. – ch271828n Apr 21 '21 at 00:48
  • @Christian could you please add an image to make it more clear? – Ravi Sevta Apr 21 '21 at 10:07
  • Sorry for not quite getting what you want. Do you want to know the distance between two points drawn in canvas? Or in a map? –  Apr 21 '21 at 11:44
  • @FahimHoque My user clicks on one point. I want the shortest distance between the point the user clicks and the path. – Christian Apr 21 '21 at 13:02
  • 1
    Is there an example of Path you would use? Is it always the same? – Naslausky Apr 22 '21 at 20:00
  • 1
    @Naslausky the path is not always the same. Depending on which Rive object I show the user and which Component inside the Rive Object I care about I get a different path. – Christian Apr 22 '21 at 20:02

1 Answers1

2

First of all traverse through all points of the path. and for each point find out the distance to clicked position and hold the shortest one.

So to get the points of the path use PathMetrics.

double getShortestDistance(Path path, Offset clickedPoint) {
    PathMetrics pathMetrics = path.computeMetrics();
    
    double minDistance;
    
    pathMetrics.toList().forEach((element) {
      for (var i = 0; i < element.length; i++) {
        Tangent tangent = element.getTangentForOffset(i.toDouble());
        Offset pos = tangent.position;
        
        double distance = getDistance(pos,clickedPoint);
        if(minDistance==null||distance<minDistance) {
          minDistance = distance;
        }
      }
    });

    return minDistance;
  }

  double getDistance(Offset pos, Offset clickedPoint) {
    double dx = pos.dx-clickedPoint.dx;
    double dy = pos.dy-clickedPoint.dy;
    double distance = sqrt(dx*dx+dy*dy);
    return distance.abs();
  }

got reference from here

Ravi Sevta
  • 2,817
  • 21
  • 37