2013-04-04 2 views
8

На днях я сделал класс на Java, чтобы вычислить, находится ли point(X,Y) внутри многоугольника. (X и Y - double, так как будут геокоординаты).Тест точки внутри полигона в Android

Я знаю, что Java имеет класс Polygon, но я должен был использовать Path2D и Point2D, потому что Polygon не позволяют double «с, только целые числа :(

После того, как я многоугольник сделано в Path2D, я используется метод contains (Path2D было это), и проблема была решена

Но теперь, я хочу, чтобы импортировать в Android, и проблема здесь, потому что Path2D потребности в импорте:.

import java.awt.geom.Path2D; 
import java.awt.geom.Point2D; 

и в Android не существует awt, поэтому я не могу использовать.

Итак, есть ли класс, похожий на Path2D который имел contains метод? или я должен рассчитать один?

Вот как я сделал в Java с помощью Path2D:

private void ConstructPolygon(Vector<Point2D> coodinates) 
{  
    this.polygon.moveTo(coodinates.get(0).getX(), coodinates.get(0).getY());   

    //System.out.println(coodinates.get(0).getX() + " " + coodinates.get(0).getY()); 
    //System.out.println("asda"); 

    for(int i = 1; i < this.num_points; i++) 
    { 
     //System.out.println(coodinates.get(i).getX() + " " + coodinates.get(i).getY()); 
     this.polygon.lineTo(coodinates.get(i).getX(), coodinates.get(i).getY()); 
    } 
    this.polygon.closePath(); 
} 
public boolean InsideCity(Point2D punto) 
{ 
    return this.polygon.contains(punto);     
} 
+0

Может быть, вы могли бы просто умноженной все 'double' значения на 10000 и использовали их с классом Java 'Polygon'? –

ответ

29

Вы можете использовать мою простую библиотеку именно для этого: https://github.com/snatik/polygon-contains-point.

Подготовка полигона:

Polygon polygon = Polygon.Builder() 
    .addVertex(new Point(1, 3)) 
    .addVertex(new Point(2, 8)) 
    .addVertex(new Point(5, 4)) 
    .addVertex(new Point(5, 9)) 
    .addVertex(new Point(7, 5)) 
    .addVertex(new Point(6, 1)) 
    .addVertex(new Point(3, 1)) 
    .build(); 

И проверьте в то время как точка находится внутри многоугольника:

Point point = new Point(4.5f, 7); 
boolean contains = polygon.contains(point); 

Он работает с типами с плавающей точкой и с полигонами, которые содержат отверстия :)

+1

Привет @sromku! У меня есть один вопрос: мне нужно прочитать файл KML для получения координат, но это может быть более 100 баллов ... так как я могу использовать Builder для всех, эти точки? Потому что моя идея - прочитать kml, получить точки в векторе (например), а затем построить многоугольник ... soo .. Я не знаю, как использовать так, как вы это сделали :(Можете ли вы Помогите мне? Спасибо! (код работает отлично!) – Shudy

+0

Обратите внимание, что этот код не проходит тест, где вы случайно попали в вершину с помощью странного наклонного луча, который он использует. – Tatarize

+0

В этой библиотеке есть проблемы даже с простейшими формами, проверьте список проблем перед рассмотрением. https://github.com/sromku/polygon-contains-point/issues –

4

К сожалению @ sromku Я спросил себя (я никогда не использовал такие вещи)

Это как я решил, если у кого-то есть тот же вопрос

Builder poly2 = new Polygon.Builder(); 
    for(int i = 0; i< xpoints.length;i++){ 
     poly2.addVertex(new Point(xpoints[i],ypoints[i])); 
    } 
    Polygon polygon2 = poly2.build(); 
5

Вот как я это сделал в Android. Он основан на этой Java программы (луч алгоритма литья): https://gis.stackexchange.com/questions/42879/check-if-lat-long-point-is-within-a-set-of-polygons-using-google-maps/46720#46720

public boolean pointInPolygon(LatLng point, Polygon polygon) { 
     // ray casting alogrithm http://rosettacode.org/wiki/Ray-casting_algorithm 
     int crossings = 0; 
     List<LatLng> path = polygon.getPoints(); 
     path.remove(path.size()-1); //remove the last point that is added automatically by getPoints() 

     // for each edge 
     for (int i=0; i < path.size(); i++) { 
      LatLng a = path.get(i); 
      int j = i + 1; 
      //to close the last edge, you have to take the first point of your polygon 
      if (j >= path.size()) { 
       j = 0; 
      } 
      LatLng b = path.get(j); 
      if (rayCrossesSegment(point, a, b)) { 
       crossings++; 
      } 
     } 

     // odd number of crossings? 
     return (crossings % 2 == 1); 
    } 

    public boolean rayCrossesSegment(LatLng point, LatLng a,LatLng b) { 
       // Ray Casting algorithm checks, for each segment, if the point is 1) to the left of the segment and 2) not above nor below the segment. If these two conditions are met, it returns true 
       double px = point.longitude, 
       py = point.latitude, 
       ax = a.longitude, 
       ay = a.latitude, 
       bx = b.longitude, 
       by = b.latitude; 
      if (ay > by) { 
       ax = b.longitude; 
       ay = b.latitude; 
       bx = a.longitude; 
       by = a.latitude; 
      } 
      // alter longitude to cater for 180 degree crossings 
      if (px < 0 || ax <0 || bx <0) { px += 360; ax+=360; bx+=360; } 
      // if the point has the same latitude as a or b, increase slightly py 
      if (py == ay || py == by) py += 0.00000001; 


      // if the point is above, below or to the right of the segment, it returns false 
      if ((py > by || py < ay) || (px > Math.max(ax, bx))){ 
       return false; 
      } 
      // if the point is not above, below or to the right and is to the left, return true 
      else if (px < Math.min(ax, bx)){ 
       return true; 
      } 
      // if the two above conditions are not met, you have to compare the slope of segment [a,b] (the red one here) and segment [a,p] (the blue one here) to see if your point is to the left of segment [a,b] or not 
      else { 
       double red = (ax != bx) ? ((by - ay)/(bx - ax)) : Double.POSITIVE_INFINITY; 
       double blue = (ax != px) ? ((py - ay)/(px - ax)) : Double.POSITIVE_INFINITY; 
       return (blue >= red); 
      } 

    } 
+0

Просьба поделиться ссылкой, чтобы получить класс Polygon – 2015-04-28 07:53:43

+0

, работает ли это? –

9

Вы можете использовать Google Maps PolyUtil:

import com.google.maps.android.PolyUtil; 

boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true); 
Смежные вопросы