2013-04-04 6 views
8

Neulich habe ich eine Klasse in Java, um zu berechnen, ob eine point(X,Y) in einem Polygon ist. (X und Y sind double, weil Geokoordinaten sein werden).Test von Punkt innerhalb Polygon in Android

Ich weiß, dass Java die Klasse hat Polygon, aber ich hatte Path2D und Point2D, zu verwenden, da Polygon nicht double ‚s erlauben, nur ganze Zahlen :(

Sobald ich das Polygon in Path2D getan haben, ich die Methode contains (Path2D hatte), und mein Problem gelöst wurde

Aber jetzt möchte ich Android importieren, und das Problem ist hier, weil Path2D Bedürfnisse zu importieren.

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

und in Android existieren nicht AWT, also kann ich nicht verwenden.

Also, gibt es eine Klasse ähnlich Path2D, die contains Methode hatte? oder muss ich selbst berechnen?

Hier ist, wie ich in Java tat Path2D mit:

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

Vielleicht könnten Sie einfach die 'alle von 10.000 double' Werte haben sich vervielfacht und benutzte sie mit der Java 'Polygon' Klasse? –

Antwort

29

Sie können meine einfache Bibliothek benutzen, um genau dies: https://github.com/snatik/polygon-contains-point.

Bereiten Polygon:

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

Und überprüfen Sie während der Punkt innerhalb des Polygons ist:

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

Es arbeitet mit Schwimmertypen und mit Polygonen, die Löcher enthalten :)

+1

Hallo @sromku! Ich habe eine Frage, ich muss eine KML-Datei lesen, um die Koordinaten zu erhalten, aber das können mehr als 100 Punkte sein ... also wie kann ich den Builder für alle verwenden, diese Punkte? Weil meine Idee ist, die kml zu lesen, die Punkte in einem Vektor zu erhalten (zum Beispiel), und dann das Polygon zu bauen ... soo .. Ich weiß nicht, wie man in der Art, wie Sie getan haben, verwendet :(Können Sie Danke !! (der Code funktioniert perfekt!) – Shudy

+0

Beachten Sie, dass dieser Code den Testfall fehlschlägt, wo Sie den Scheitelpunkt direkt mit einem seltsamen schrägen Strahl treffen, den er verwendet. – Tatarize

+0

Diese Bibliothek hat auch Probleme mit den einfachsten Formen, überprüfen Sie die Problemliste vor der Berücksichtigung. https://github.com/sromku/polygon-contains-point/issues –

4

Leider @ sromku Ich fragte mich selbst (ich habe nie diese Art von Dingen)

Das ist wie ich gelöst habe, wenn jemand die gleiche Frage hat

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

Hier ist, wie ich es in Android gemacht habe. Es ist auf diesem Java-Programm (Ray-Casting-Algorithmus) basiert: 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

Bitte teilen Sie den Link, um die Polygon-Klasse –

+0

zu bekommen. Funktioniert das? –

9

Sie können Google Maps PolyUtil:

import com.google.maps.android.PolyUtil; 

boolean inside = PolyUtil.containsLocation(new LatLng(...), poly, true);