Finding a point in polygon in android - java

I am using the following code to find a point of coordinates exists in the code or not:
mMap.setOnMapClickListener(new OnMapClickListener()
{
public void onMapClick(LatLng point)
{
boolean checkPoly = true;
Point2D[] points = new Point2D[ myPoints.size()];
for ( int i = 0; i < myPoints.size(); i ++)
{
LatLng pt = myPoints.get(i);
points[i] = new Point2D(pt.latitude, pt.longitude);
}
Polygon2D polygon2d = new SimplePolygon2D(points);
double a = point.latitude;
double b = point.longitude;
Point2D myPt = new Point2D(a,b);
checkPoly = polygon2d.contains(myPt);
Log.i("CHECK", String.valueOf(checkPoly));
if (checkPoly)
{
setMarker(point);
}
else
Toast.makeText(NewSearch.this,"The Location is outside of the Area", Toast.LENGTH_LONG).show();
}
I am using the JavaGeom 0.11.1 library for finding polygon point. However this code was working exactly fine. Note that myPoints array is an ArrayList<LatLng> of all vertices of the polygons drawn on map. However something happened and now it's working for opposite that is outside of map; if i change !checkPoly then it works fine.
Does anyone know what is wrong?

I looked at the source for the polygon boundary definition. It's using the usual convention for "inside," which requires the vertices to be given in CCW order around the "inside" space. It's likely your boundary is given in CW order, which makes the "inside" what most people would call the outside.
In other words, what you think is a polygon is really a hole in the infinite polygon that covers the whole x-y universe.
So reverse the order of boundary vertices and things should start working as you intend.
ADDITION
If you can't reverse the order of vertices, there is a different polygon membership test that doesn't rely on point order. If you are testing membership of the point (x,y), this algorithm assumes that the point (infinity, y) is outside the polygon and then decides whether (x,y) is on the opposide side. The implementation here in C is due to WR Franklin. It would be easy to port this to Java. I've used it several times with excellent results.

I have been using Google android-maps-utils library and you can make use of the PolyUtil class, particularly at this method:
public static boolean containsLocation(LatLng point, List<LatLng> polygon, boolean geodesic)

Related

Java Spigot Set the direction of the vector relative to the player's position

I have a problem with the correct vector alignment. I want to get a vector pointing in the same direction as the player, but with a constant Y value of 0. The point is, whatever the player's vertical and horizontal rotation, the vector's Y value was 0. The vector is always supposed to point horizontally (value 0), but keeping the direction of the player's rotation.
This picture shows the situation from the side. The red line represents an example of the player's viewing direction (up - down), and the green one the effect I want to achieve. Regardless of the direction in which the player is looking, up or down, the green line remains unchanged:
Here, in turn, I have presented this situation from the top. The red line is the player's viewing direction (left - right) and the green is the effect I want to achieve. As you can see, the player's rotation on this axis sets my vector exactly the same.
I was able to write a piece of code, but it doesn't behave correctly: the Y axis gets higher and higher as the player turns up or down. I don't know why:
Vector playerDirection = player.getLocation().getDirection();
Vector vector = new Vector(playerDirection.getX(), 0, playerDirection.getZ()).normalize().multiply(3);
How to do it correctly?
tl;dr:
Vector vector = new Vector(-1 * Math.sin(Math.toRadians(player.getLocation().getYaw())), 0, Math.cos(Math.toRadians(player.getLocation().getYaw())));
You are missing a fundamental principal of creating a new Vector based on where a player is looking. I don't know the math of it very well, but I can mess around with the math of people who are better than I at Geometry.
As such, let's try to reduce the number of Vector variables you have defined. Taking a quick peek at the source for Location, we can actually create your Vector directly to avoid having multiple defined.
public Vector getDirection() {
Vector vector = new Vector();
double rotX = this.getYaw();
double rotY = this.getPitch();
vector.setY(-Math.sin(Math.toRadians(rotY)));
double xz = Math.cos(Math.toRadians(rotY));
vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
return vector;
}
As you can see, the pitch and yaw of a player are not a 1:1 relationship. No idea why, but let's repurpose their logic.
Here's how we'll do that:
public Vector getVectorForAdixe(Location playerLoc) {
Vector vector = new Vector();
double rotX = playerLoc.getYaw();
double rotY = 0; // this is the important change from above
// Original Code:
// vector.setY(-Math.sin(Math.toRadians(rotY)));
// Always resolves to 0, so just do that
vector.setY(0);
// Original Code:
// double xz = Math.cos(Math.toRadians(rotY));
// Always resolves to 1, so just do that
double xz = 1;
vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
return vector;
Nice! Now, cleaning it up a bit to remove those comments and unnecessary variables:
public Vector getVectorForAdixe(Location playerLoc) {
Vector vector = new Vector();
double rotX = playerLoc.getYaw();
vector.setY(0);
vector.setX(-1 * Math.sin(Math.toRadians(rotX)));
vector.setZ(Math.cos(Math.toRadians(rotX)));
return vector;
Why does this math work like that? No idea! But this should almost certainly work for you. Could even inline it if you really wanted to keep it how you had it originally:
Vector vector = new Vector(-1 * Math.sin(Math.toRadians(player.getLocation().getYaw())), 0, Math.cos(Math.toRadians(player.getLocation().getYaw())));
Closing note, if you want to be able to get the pitch/yaw FROM the vector, that code is here: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/Location.java#310

Updating coordinates for a moving libGDX object

I have a number of TextButtons I can drag, checking if they overlap an Image when I let go. Currently what I'm experiencing is either a particular object will detect collision located anywhere on screen, or it will never collide. Note that I'm not using the native DragAndDrop class, but have adapted a parallel implementation from a book.
Given that my TextButtons move when I drag them, I think the following function is updating the (x,y) of the object:
public void touchDragged(InputEvent event, float eventOffsetX, float eventOffsetY, int pointer)
{
float deltaX = eventOffsetX - grabOffsetX;
float deltaY = eventOffsetY - grabOffsetY;
a.moveBy(deltaX, deltaY);
}
Is that correct that the Actor a's x, y change due to moveBy? Because my latter collision detection - where I examine the dragged objects coordinates - reports the same x,y coordinates for the dragged object no matter where I release it. Here's the log for releasing the object from two different locations on the screen:
Does (626.8995, 393.1301)(923.8995, 393.1301)(923.8995, 499.1301)(626.8995, 499.1301) fit into (610.0, 256.0)(990.0, 256.0)(990.0, 677.0)(610.0, 677.0)?
Does (626.8995, 393.1301)(923.8995, 393.1301)(923.8995, 499.1301)(626.8995, 499.1301) fit into (610.0, 256.0)(990.0, 256.0)(990.0, 677.0)(610.0, 677.0)?
and here's the collision detection and sys out generating those log messages:
//this is called by the dragged obj, a, on touchUp() against each of the targets
public boolean overlaps(Actor other)
{
//a is the first, dragged object, other is the target
if (poly1 == null)
poly1 = getPolygon(a);
Polygon poly2 = getPolygon(other);
float[] p1v = poly1.getVertices();
StringBuilder sb = new StringBuilder();
for (int i=0; i<p1v.length-1; i+=2)
sb.append("(").append(p1v[i]).append(", ").append(p1v[i+1]).append(")");
float[] p2v = poly2.getVertices();
StringBuilder sb2 = new StringBuilder();
for (int i=0; i<p2v.length-1; i+=2)
sb2.append("(").append(p2v[i]).append(", ").append(p2v[i+1]).append(")");
System.out.println("Does " + sb + " fit into " + sb2 + "?");
// initial test to improve performance
if ( !poly1.getBoundingRectangle().overlaps(poly2.getBoundingRectangle()) )
return false;
return Intersector.overlapConvexPolygons( poly1, poly2 );
}
public Polygon getPolygon(Actor a) {
Polygon p = new Polygon();
// float[] vertex = { a.getOriginX(), a.getOriginY(), a.getOriginX(), a.getY(), a.getX(), a.getY(), a.getX(), a.getOriginY() };//new float[8];
// float[] vertex = { 0, 0, a.getWidth(), 0, a.getWidth(), a.getHeight(), 0, a.getHeight()};
float[] vertex = { a.getX(), a.getY(), (a.getX() + a.getWidth()), a.getY(), (a.getX() + a.getWidth()), (a.getY() + a.getHeight()), a.getX(), (a.getY() + a.getHeight())};
p.setVertices(vertex);
// p.setPosition(a.getX(), a.getY());
//p.setOrigin(a.getOriginX(), a.getOriginY());
return p;
}
There are a HORDE of collision detection posts already on StackOverflow, and they helped some in showing me how to form valid polygons. Perhaps the 3rd party drag and drop is why I'm not finding my answer in the wealth of knowledge out there, but I'm leaning towards some annoying mistake I'm overlooking.
Score another one for logic failure. Originally I thought I'd just be saving the dimensions of the dragged polygon when I decided to cache it, thinking it would save a few polygon creation steps as it was checked against a number of potential targets. Later, as I kept reworking what values to feed the polygon vertices, I tied in the location of the polygon as well. So it was just caching the first place I dragged it to, and using that every time I dragged it somewhere.
Thanks for the comment, it helped me move past thinking I wasn't understanding the classes. I'm doubtful this particular mistake/resolution will ever be of use to someone else, and would be very understanding if this post is removed.

How to create Polygon from Point (Spatial4j)

I want to do some geometric calculations in Java and found that Spatial4j should suit my needs.
I want to be able to compute stuff like whether two polygons overlap or what their bounding box is.
My thinking is that I need to create a polygon from a series of points.
To that end I have tested with this code:
Point point1 = shapeFactory.pointXY(0, 0);
Point point2 = shapeFactory.pointXY(5, 1);
Point point3 = shapeFactory.pointXY(3, 3);
Point point4 = shapeFactory.pointXY(0, 1);
List<Point> points = new ArrayList<>();
points.addAll(Arrays.asList(point1, point2, point3, point4));
So, I have my points now. How do I go about making a polygon (or for that matter any shape) from these points ?
I would think that shapeFactory.polygon() would create me a polygon but that throws me an UnsupportedOperationException. Any help ?
Alright, it seems that Spatial4j does not connect the points, so it is not a filled shape. Instead I relied on the Spatial4j implementation of JTS and that did the trick. (Spatial4j's polygon is not implemented).
JtsSpatialContextFactory jtsSpatialContextFactory = new JtsSpatialContextFactory();
JtsSpatialContext jtsSpatialContext = jtsSpatialContextFactory.newSpatialContext();
JtsShapeFactory jtsShapeFactory = jtsSpatialContext.getShapeFactory();
ShapeFactory.PolygonBuilder polygonBuilder = jtsShapeFactory.polygon();
// note due to it being a builder one needs to chain the points.
Shape shape1 = polygonBuilder.pointXY(4, 0).pointXY(3, 3).pointXY(1, 4).pointXY(0, 0).pointXY(4, 0).build();
Now doing for example shape.getArea() returns the surface area.
One can also create a Geometry from a Shape by doing jtsShapeFactory.getGeometryFrom(shape), which then returns a Geometry.
Note: Watch out with doing polygonBuilder.pointXY() even after calling build(). It will still append these points to whatever was chained to the builder before the build.

Removing element from ArrayList Java Processing Boid example

Got this BOID application going in Processing with some steering algorithms.
The boids are stored
in two separate ArrayLists for each colour.
The red boid (predator) has a
pursue function:
class Creature {
int prey = 1;
PVector pursue(ArrayList boids) {
PVector steer = new PVector();
if (prey < boids.size()) {
Creature boid = (Creature) boids.get(prey);
steer = PVector.sub(boid.location, location);
steer.mult(maxpursue);
}
return steer;
}
This function gets the red boids to stand on top of the targeted white boid.
The problem is getting this white boid to disappear when all the red boids are on top of it. (Like shown in the image above)
I can add a new boid or predator with the following, but i cannot remove?:
void mousePressed() {
if (mouseButton == LEFT){
Creature predator = new Creature(mouseX, mouseY, 2);
planet.boids.add(predator);
} else if (mouseButton == RIGHT) {
Creature boid = new Creature(mouseX, mouseY, 1);
planet.boids.add(boid);
planet.boids.remove(boid); // This line does not work?
}
}
The code you posted doesn't make a ton of sense. You want to remove an existing Boid, so why on earth are you creating a new one and then immediately removing it?
You haven't posted an MCVE, so I can only answer in a general sense, but here's what you need to do:
Step 1: Refactor your code so that it makes more sense. Comment every single line if you have to, just to be sure you know exactly what the code is doing. But you shouldn't be doing things like adding a new Boid and then removing it in the very next line. Break your problem down into smaller steps, and make sure each step works perfectly by itself before trying to mix it with other funtionality.
Step 2: Create a function that takes a single white Boid and the List of red Boids, and returns true if that white Boid should be removed. Test this function by itself using hard-coded values in a standalone example sketch.
Step 3: Iterate over your white Boids and call the function you created in step 2 for each one. If the function returns true, then remove that white Boid. You might want to use an Iterator for this step.
If you get stuck on one of those steps, then post an MCVE along with a specific question, and we'll go from there. It's hard to answer general "how do I do this" type questions, but it's much easier to answer specific "I tried X, expected Y, but got Z instead" type questions- especially if we have an MCVE we can actually run on our own machines instead of some disconnected snippets.

How to move an entire GPen object?

In Java using the acm.graphics GPen is there any way to move the entire drawn sequence of lines? I've read the manual thoroughly and I'm beginning to think it's not possible which brings me to my second question. Are there any other graphics objects in Java that work very similar to a pen that can also be moved. The reason I'm asking is because I've been working on a graphing program that allows mouse gestures to be used to pan around and zoom in and out. After building functionality for implicit functions I realized simply clearing the drawing board and redrawing everything is not going to cut it anymore so I really need to work on more efficient ways to handle intermediate changes of the graph without having to recalculate everything. For example with this or similar code:
GPen p = new GPen();
p.setLocation(100,100); //places the pen on the canvas at 100, 100
p.drawLine(-50,0); //draw a line left 50 pixels
p.drawLine(50,-50); //draw a line right and up 50 pixels each
p.drawLine(0,50); //draw a line down 50 pixels
This would result in a simple right triangle who's bottom right most point is at 100, 100 on a particular canvas. What I need to do is be able to move this same drawn sequence of lines relative to one another to another origin. What I hoping for is a class that has separate methods for setLocation() and move() where setLocation() controls pen position and move() would move the entire object around.
Ok so having received almost no attention on here I've came to the conclusion that such a method just needs to be written from scratch and went ahead and did that. I'm not entirely sure how helpful posting my proprietary code would be but in the event that anybody could use it I'll post the basic idea of it. Since Pen utilities are essentially a bunch of lines and lines are a bunch of from and to's I created an object that I called FPen (for FunctionPen) that accepts the instructions for from and to. While defining FPen you pass it where to start and how far to go however many times you need and that's it. Once you've passed these instructions I created another method called returnGPen(Color c) which will on call use the instructions it has on hand and generate the desired GPen object. When you want to move the entire GPen you can then create a method called adjustOrigin(double oX, double oY); which will calculate a change from a previously recorded origin and this new one and go through the list of instructions and adjust them appropriately.
My needs for this Class are strictly for my Graphing program and are not entirely finished either but it does work for most purposes.
import acm.graphics.GPen;
import java.awt.Color;
import java.util.ArrayList;
public class FPen{
private double relativeCenterX;
private double relativeCenterY;
private ArrayList<Double> fromX = new ArrayList<Double>();
private ArrayList<Double> fromY = new ArrayList<Double>();
private ArrayList<Double> distX = new ArrayList<Double>();
private ArrayList<Double> distY = new ArrayList<Double>();
public FPen(double rX, double rY, double z){
relativeCenterX = rX;
relativeCenterY = rY;
}
public void adjustOrigin(double cX, double cY){
double changeX = relativeCenterX-cX;
double changeY = relativeCenterY-cY;
for(int i = 0; i < fromX.size(); i++){
fromX.set(i,fromX.get(i)+changeX*zoom);
fromY.set(i,fromY.get(i)-changeY*zoom);
}
relativeCenterX = cX;
relativeCenterY = cY;
}
public void clear(){
fromX.clear();
fromY.clear();
distX.clear();
distY.clear();
}
public void drawLine(double fX, double fY, double tX, double tY){
fromX.add(fX);
fromY.add(fY);
distX.add(tX);
distY.add(tY);
}
public GPen returnGPen(Color c){
GPen pen = new GPen();
pen.setColor(c);
for(int i = 0; i < fromX.size(); i++){
pen.setLocation(fromX.get(i),fromY.get(i));
pen.drawLine(distX.get(i),distY.get(i));
}
return pen;
}
}
Of course a unexpected nice thing that came out of this was the idea that I can now quickly benchmark different drawing routines by creating different methods for each and calling what I'm interested in.

Categories