2013-04-04 14 views
8

Niedawno zrobiłem zajęcia w języku Java, aby obliczyć, czy point(X,Y) jest wewnątrz wielokąta. (X i Ydouble, ponieważ będą współrzędnymi geograficznymi).Test punktu wewnątrz wielokąta w Androidzie

wiem, że Java ma klasę Polygon, ale musiałem użyć Path2D i Point2D, ponieważ Polygon nie pozwalają double „s, tylko liczby całkowite :(

Raz mam wielokąta odbywa się w Path2D, ja stosowane metody contains (Path2D miał go), a problem został rozwiązany

Ale teraz chcę zaimportować do Androida, a problem jest tutaj, bo Path2D musi importować.

i na Androidzie nie istnieje, więc nie mogę z niego korzystać.

Czy istnieje zatem klasa podobna do Path2D, która miała metodę contains? lub muszę sam obliczyć?

Oto jak to zrobiłem w Javie przy użyciu 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

Może mogłeś tylko pomnożone wszystkie 'wartości double' przez 10000 i używał ich z klasą Java 'Polygon'? –

Odpowiedz

29

Można używać prostego bibliotekę dokładnie o to: https://github.com/snatik/polygon-contains-point.

Przygotuj wielokąt:

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(); 

I sprawdzić natomiast punkt znajduje się wewnątrz wielokąta:

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

Współpracuje z typów zmiennoprzecinkowych i wielokątów, które zawierają otwory :)

+1

Hi @sromku! Mam jedno pytanie, muszę odczytać plik KML, aby uzyskać współrzędne, ale może to być ponad 100 punktów ... więc jak mogę użyć Buildera dla wszystkich, te punkty? Bo moim pomysłem jest odczytać kml, zdobyć punkty w wektorze (na przykład), a następnie zbudować wielokąt ... tak ... Nie wiem jak używać w taki sposób, w jaki robiłeś :(pomóż mi? Dzięki! (kod działa perfekcyjnie!) – Shudy

+0

Zwróć uwagę, że ten kod kończy się niepowodzeniem w przypadku testowym, w którym bezpośrednio trafiłeś w wierzchołek dziwnym, pochylonym promieniem, którego używa. – Tatarize

+0

Ta biblioteka ma problemy nawet z najprostszymi kształtami, przed rozważeniem sprawdź listę problemów. https://github.com/sromku/polygon-contains-point/issues –

4

Niestety @ sromku Zapytałem siebie (nigdy nie korzystałem z tego typu rzeczy)

To jak rozwiązałem, jeśli ktoś ma to samo pytanie:

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

Oto jak to zrobiłem w Androidzie. Jest on oparty na programie java (algorytm odlewania ray): 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

Proszę udostępnić link, aby uzyskać klasę Polygon –

+0

czy to działa? –

9

Można użyć Google Maps PolyUtil:

import com.google.maps.android.PolyUtil; 

boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true); 
Powiązane problemy