How can I tell if a closed path contains a given point?

前端 未结 5 1227
广开言路
广开言路 2020-11-29 00:19

In Android, I have a Path object which I happen to know defines a closed path, and I need to figure out if a given point is contained within the path. What I was hoping for

5条回答
  •  旧巷少年郎
    2020-11-29 00:29

    WebKit's SkiaUtils has a C++ work-around for Randy Findley's bug:

    bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::FillType ft)
    {
      SkRegion rgn;
      SkRegion clip;
    
      SkPath::FillType originalFillType = originalPath->getFillType();
    
      const SkPath* path = originalPath;
      SkPath scaledPath;
      int scale = 1;
    
      SkRect bounds = originalPath->getBounds();
    
      // We can immediately return false if the point is outside the bounding rect
      if (!bounds.contains(SkFloatToScalar(point.x()), SkFloatToScalar(point.y())))
          return false;
    
      originalPath->setFillType(ft);
    
      // Skia has trouble with coordinates close to the max signed 16-bit values
      // If we have those, we need to scale. 
      //
      // TODO: remove this code once Skia is patched to work properly with large
      // values
      const SkScalar kMaxCoordinate = SkIntToScalar(1<<15);
      SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
    
      if (biggestCoord > kMaxCoordinate) {
          scale = SkScalarCeil(SkScalarDiv(biggestCoord, kMaxCoordinate));
    
          SkMatrix m;
          m.setScale(SkScalarInvert(SkIntToScalar(scale)), SkScalarInvert(SkIntToScalar(scale)));
          originalPath->transform(m, &scaledPath);
          path = &scaledPath;
      }
    
      int x = static_cast(floorf(point.x() / scale));
      int y = static_cast(floorf(point.y() / scale));
      clip.setRect(x, y, x + 1, y + 1);
    
      bool contains = rgn.setPath(*path, clip);
    
      originalPath->setFillType(originalFillType);
      return contains;
    }
    

提交回复
热议问题