Point inside a 2D Polygon - java

Following piece of java code is a solution to determine whether a 2D Point is within a Polygon or not (taken from here). I think this code has some problems. For example for this polygon:
Point[] polygon = new Point[5];
polygon[0] = new Point(30,20);
polygon[1] = new Point(80,10);
polygon[2] = new Point(75,100);
polygon[3] = new Point(40,100);
polygon[4] = new Point(55,65);
It returns true (inside) for (76,82) but this point is on the edge (Code returns false correctly for another point on the edge : (45,17)).
Also it returns false (not inside) for (45,90) but it is inside of the polygon. What is the problem?
public boolean IsPointInPolygon(Point p, Point[] polygon)
{
double minX = polygon[0].x;
double maxX = polygon[0].x;
double minY = polygon[0].y;
double maxY = polygon[0].y;
for ( int i = 1 ; i < polygon.length; i++ )
{
Point q = polygon[i];
minX = Math.min(q.x, minX);
maxX = Math.max(q.x, maxX);
minY = Math.min(q.y, minY);
maxY = Math.max(q.y, maxY);
}
if ( p.x <= minX || p.x >= maxX || p.y <= minY || p.y >= maxY )
{
return false;
}
boolean inside = false;
int j = polygon.length - 1;
for (int i = 0 ;i < polygon.length ; j = i++)
{
if (( polygon[i].y > p.y ) != ( polygon[j].y > p.y) &&
p.x <= (polygon[j].x - polygon[i].x ) * ( p.y - polygon[i].y ) / ( polygon[j].y - polygon[i].y ) + polygon[i].x)
{
inside = !inside;
}
}
return inside;
}
I think I should change my code to below, but I am not sure !
float tempX = ((float)((polygon[i].x - polygon[j].x) * (p.y - polygon[i].y)) / (polygon[i].y - polygon[j].y)) + polygon[i].x;
if (p.x < tempX) {
inside = !inside;
}
else if (p.x == tempX) {
return false;
}

This algorithm
if ( p.x <= minX || p.x >= maxX || p.y <= minY || p.y >= maxY )
{
return false;
}
Is wrong. It only checks if the point is within a rectangle, bounded by minX, maxX, minY, maxY
You can't test if a point is within a polygon without using all the polygon vertices.
Use java.awt.Polygon :
public boolean isPointInPolygon(Point p, Point[] points)
{
Polygon polygon = new Polygon();//java.awt.Polygon
for(Point point : points) {
polygon.addPoint(point.x, point.y);
}
return polygon.contains(p);
}
Testing it with
Point[] points = new Point[5];
points[0] = new Point(30,20);
points[1] = new Point(80,10);
points[2] = new Point(75,100);
points[3] = new Point(40,100);
points[4] = new Point(55,65);
System.out.println(isPointInPolygon(new Point(76,82), points) );
prints out false.

Related

Find Centroid of Quadrilateral

Help me please with how to find Centroid of Quadrilateral? I have this constructor:
public Quadrilateral(Point a, Point b, Point c, Point d) {
if (a == null || b == null || c == null || d == null) {
throw new IllegalArgumentException();
}
if (collinear(a, b, c)) {
throw new IllegalArgumentException();
}
double[][] points = { { a.getX(), a.getY() }, { b.getX(), b.getY() },
{ c.getX(), c.getY() }, { d.getX(), d.getY() } };
if (!isConvex(points)) {
throw new IllegalArgumentException();
}
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
Then I find four centroids of triangles inside quadrilateral:
public Point centroid() {
Point center1 = centroidTriangle(a,b,c);
Point center2 = centroidTriangle(a,c,d);
Point center3 = centroidTriangle(a,d,b);
Point center4 = centroidTriangle(b,d,c);
return null;
}
private Point centroidTriangle(Point a, Point b, Point c) {
double xx = (a.getX() + b.getX() + c.getX()) / 3;
double xy = (a.getY() + b.getY() + c.getY()) / 3;
return new Point(xx, xy);
}
Then I need to find two diagonals between "leftUp" - "rightDown" and "leftDown"-"rightUp" centroids.
But how can I find position of centroid to make correct pairs of them? And how to find then centroid of all quadrilateral?
Good day.
After finding centers of triangles you need to find intersection of lines which made with (center1,center2) and (center3,center4). So point of intersection is Centroid of Quadrilateral
public Point centroid() {
Point center1 = centroidTriangle(a,b,c);
Point center2 = centroidTriangle(a,c,d);
Point center3 = centroidTriangle(a,d,b);
Point center4 = centroidTriangle(b,d,c);
return new Segment(center1,center2)
.intersection(new Segment(center3,center4));
}
Segment:
import java.util.Objects;
import static java.lang.Math.sqrt;
import static java.lang.StrictMath.pow;
class Segment {
Point start;
Point end;
public Segment(Point start, Point end) {
if(Objects.isNull(start) || Objects.isNull(end) || start.equals(end))
throw new RuntimeException();
this.start = start;
this.end = end;
}
double length() {
return sqrt(pow(end.getX() - start.getX(), 2) + pow(end.getY() - start.getY(), 2));
}
Point middle() {
return new Point((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
}
Point intersection(Segment another) {
double k1 = (end.getY() - start.getY()) / (end.getX() - start.getX());
double k2 = (another.end.getY() - another.start.getY()) / (another.end.getX() - another.start.getX());
if (k1 == k2) return null;
double b1 = (start.getY() * end.getX() - end.getY() * start.getX()) / (end.getX() - start.getX());
double b2 = (another.start.getY() * another.end.getX() - another.end.getY() * another.start.getX()) /
(another.end.getX() - another.start.getX());
double x = (b2 - b1) / (k1 - k2);
double y = (k1 * b2 - k2 * b1) / (k1 - k2);
if ((x > start.getX() && x > end.getX()) || (x > another.start.getX() && x > another.end.getX()) ||
(x < start.getX() && x < end.getX()) || (x < another.start.getX() && x < another.end.getX()) ||
(y > start.getY() && y > end.getY()) || (y > another.start.getY() && y > another.end.getY()) ||
(y < start.getY() && y < end.getY()) || (y < another.start.getY() && y < another.end.getY()))
return null;
return new Point(x, y);
}
}

is there any way to make player give specific items when in the coords?

I'm making my custom plugin and I want to make one thing:
when a player is in a specified region/coords like from 0, 60, 0 to 50, 80, 50 set players inventory clear
Globally, you have to check if it was not in before move, and if it will be in just after.
You can do like that:
#EventHandler
public void onMove(PlayerMoveEvent e) { // when move
if(e.isCancelled())
return;
if(!isLocIn(e.getFrom()) && isLocIn(e.getTo())) { // if was not in but will be in
e.getPlayer().getInventory().clear(); // clear inventory
}
}
private boolean isLocIn(Location loc) {
// enter min & max values
int minX = 0, minY = 60, minZ = 0;
int maxX = 50, maxY = 80, maxZ = 50;
// get content from given loc
double x = loc.getX();
double y = loc.getY();
double z = loc.getZ();
return x > minX && x < maxX && y > minY && y < maxY && z > minZ && z < maxZ; // check in x/y/z are more than min and lower than max
}

Rendering section of a BufferedImage within a Rectangle

I am currently trying to draw just a section of a BufferedImage that is within the bounds of a Rectangle on the fly. The image gets moved, and thus the size of the image in the rectangle changes.
Visual depiction:
Currently, this is what I have and it works great with a low res image. But if I scale the minimap up, this becomes very inefficient and causes lag
private BufferedImage extractPixels() {
int[] imagePixels = new int[scaledImage.getWidth() * scaledImage.getHeight()];
scaledImage.getRGB(0, 0, scaledImage.getWidth(), scaledImage.getHeight(), imagePixels,
0, scaledImage.getWidth());
int maxX = 0, maxY = 0;
boolean first = false;
for (int y = 0; y < scaledImage.getHeight(); y++) {
for (int x = 0; x < scaledImage.getWidth(); x++) {
int px = (int)(this.x + x);
int py = (int)(this.y + y);
if (viewingArea.contains(px, py)) {
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
if (!first) {
imageX = x;
imageY = y;
first = true;
}
}
}
}
int xCount = maxX - imageX;
int yCount = maxY - imageY;
if (imageX < 0 || imageX > scaledImage.getWidth() || imageX + xCount > scaledImage.getWidth()) return null;
if (imageY < 0 || imageY > scaledImage.getHeight() || imageY + yCount > scaledImage.getHeight()) return null;
return scaledImage.getSubimage(imageX, imageY, xCount, yCount);
}
In Render loop:
public void Render(PixelRenderer renderer) {
BufferedImage image = extractPixels();
if (image != null) renderer.renderImage(image, x + imageX, y + imageY);
}
Is there a way to do this more efficiently, so that re-scaling has less of an effect on performance?
Fixed by calculating where the image should subimage from, and the size of the subimage dependent on the position of the main image.
private BufferedImage extractPixels() {
double xp = viewingArea.x - this.x;
double yp = viewingArea.y - this.y;
double iw = viewingArea.width;
double ih = viewingArea.height;
int rightBound = scaledImage.getWidth() - viewingArea.width;
int bottomBound = scaledImage.getHeight() - viewingArea.height;
if (xp < 0) {
xp = 0;
iw = viewingArea.width - (this.x - viewingArea.x);
imageX = viewingArea.x + (viewingArea.width - (int)iw);
} else if (xp >= 0 && xp < rightBound) {
xp -= dx;
iw -= dx;
imageX = viewingArea.x;
}
if (xp >= rightBound) {
iw = viewingArea.width - ((int)xp - (scaledImage.getWidth() - viewingArea.width));
imageX = viewingArea.x;
}
if (yp < 0) {
yp = 0;
ih = viewingArea.height - (this.y - viewingArea.y);
imageY = viewingArea.x + (viewingArea.height - (int)ih);
} else if (yp >= 0 && yp < bottomBound) {
yp -= dy;
ih -= dy;
imageY = viewingArea.y;
}
if (yp >= bottomBound) {
ih = viewingArea.height - ((int)yp - (scaledImage.getHeight() - viewingArea.height));
imageY = viewingArea.y;
}
if (iw < 0) iw = Math.abs(iw);
if (ih < 0) ih = Math.abs(ih);
if (xp < 0) xp = Math.abs(xp);
if (yp < 0) yp = Math.abs(yp);
BufferedImage result = new BufferedImage((int)iw, (int)ih, BufferedImage.TYPE_INT_RGB);
try {
result = scaledImage.getSubimage((int)xp, (int)yp, (int)iw, (int)ih);
} catch (Exception e) {
//TODO: Log to game engine something bad has happened
e.printStackTrace();
}
return result;
}

How can I see if two rectangles have one equal point using java?

I have rectangle A = upper left point (-4,-1), bottom right point (-2-2) and rectangle B upper left point (-2,-2), bottom right point (-1,-3)
then:
Rectangle first = new Rectangle(-4,-1,2,1); //x1,y1,width,height
Rectangle second = new Rectangle(-2,-2,1,1);
OK, I have 2 rectangles with 1 same point.
I use first.intersects(second) and this returns false..
How can I use java to do this, I need something return True if One point or more into Rectangle A belongs Rectangle B?
My code now:
public class GeometriaRectangle2 {
public static void main(String[] args) {
Scanner lector = new Scanner(System.in);
while (lector.hasNextLine()) {
String a[] = lector.nextLine().split(",");
int b[] = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = Integer.parseInt(a[i]);
}
int c = Math.abs(b[0] - b[2]);
int d = Math.abs(b[1] - b[3]);
int e = Math.abs(b[4] - b[6]);
int f = Math.abs(b[5] - b[7]);
Rectangle r = new Rectangle(b[0], b[1], c, d);
Rectangle r2 = new Rectangle(b[4], b[5], e, f);
int tw = r.width;
int th = r.height;
int rw = r2.width;
int rh = r2.height;
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
System.out.println(false);
}
int tx = r.x;
int ty = r.y;
int rx = r2.x;
int ry = r2.y;
rw += rx;
rh += ry;
tw += tx;
th += ty;
// overflow || intersect or attached
if ((rw < rx || rw >= tx) && (rh < ry || rh >= ty)
&& (tw < tx || tw >= rx) && (th < ty || th >= ry)) {
System.out.println(true);
} else {
System.out.println(false);
}
}
}
}
Example: input:
-3,3,-1,1,1,-1,3,-3
-3,3,-1,1,-2,4,2,2
output:
False
True
java.awt.Rectangle is part of AWT and is designed for representing discrete areas in images (and on the screen). Points and dimensions are integers. The intersects() method does what you want, and the rectangles you have given do not intersect. false is the correct value.
Think of pixels in an image. The coordinates of a java.awt.Rectangle are essentially the centers of pixels, the dimensions are the count. So new Rectangle(-4, -1, 2, 1), for example, does not have its bottom right at (-2, -2) as you assume, its bottom right is at (-3, -1):
The upper-most left-most pixel of the red rectangle is the pixel at (-4, -1). The bottom-most right-most pixel is the pixel at (-3, -1). Also note that it does not overlap the blue rectangle.
Even if this were not the case, your rectangles do not intersect. They touch at one point, but do not overlap. Arguably, the intersection is a "rectangle" at (-2, -2) with width 0 and height 0 - which is empty.
You may also modifies the current code of intersects function to suit your needs. In your case you want to state it true when there is a pair of points from two rectangles (even the side line's) are sharing the same coordinate - (read: attached). Thus, you may try something like this:
public boolean intersectsOrAttached(Rectangle r, Rectangle r2) {
int tw = r.width;
int th = r.height;
int rw = r2.width;
int rh = r2.height;
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
return false;
}
int tx = r.x;
int ty = r.y;
int rx = r2.x;
int ry = r2.y;
rw += rx;
rh += ry;
tw += tx;
th += ty;
//overflow || intersect or attached
return ((rw < rx || rw >= tx) &&
(rh < ry || rh >= ty) &&
(tw < tx || tw >= rx) &&
(th < ty || th >= ry));
}
UPDATE:
Actually online judging system is a little bit tricky.
I managed to get it accepted partially, I'm not sure whether it's time or memory constraints, as well as some overlooked bound-cases that we couldn't figure out easily.
But here it is, it's better if you can make it optimized by yourself:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class OverlappingRectangles {
public static void main(String[] args) {
String f = args[0];
try {
BufferedReader br = new BufferedReader(new FileReader(f));
while (br.ready()) {
String cs[] = br.readLine().split(",");
int[] ci = new int[cs.length];
int i = 0;
for (String s : cs) {
ci[i] = Integer.parseInt(s);
i += 1;
}
if (ck(ci[0], ci[1], ci[2], ci[3], ci[4], ci[5], ci[6], ci[7])) {
System.out.println("True");
} else {
System.out.println("False");
}
}
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
}
}
public static boolean ck(int rx, int ry, int rw, int rh, int tx, int ty, int tw, int th) {
//ATTENTION!
//rx,ry -> upper-left corner of rect A
//rw,rh -> bottom-right corner of rect A
//tx,ty -> upper-left corner of rect B
//tw,th -> bottom-right corner of rect B
return ((rw < rx || rw >= tx)
&& (rh < ry || rh >= ty)
&& (tw < tx || tw >= rx)
&& (th < ty || th >= ry));
}
}

Point in Polygon Android

I am developing an android application. In the application I have integrated map with polygon. Now I want to check whether the given marker is inside the polygon or not. Help Me please.
Following function is used to check the lat long in the polygon
pnpoly(no_of_vertex, lat, lng,(float) (point.latitude),(float) (point.longitude))
boolean pnpoly(int nvert, float vertx[], float verty[], float testx, float testy)
{
int i, j;
boolean c = false;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c =true;
}
return c;
}
I got the solution to my question following is the code
**private boolean isPointInPolygon(LatLng tap, ArrayList<LatLng> vertices) {
int intersectCount = 0;
for(int j=0; j<vertices.size()-1; j++) {
if( LineIntersect(tap, vertices.get(j), vertices.get(j+1)) ) {
intersectCount++;
}
}
return (intersectCount%2) == 1; // odd = inside, even = outside;
}
private boolean LineIntersect(LatLng tap, LatLng vertA, LatLng vertB) {
double aY = vertA.latitude;
double bY = vertB.latitude;
double aX = vertA.longitude;
double bX = vertB.longitude;
double pY = tap.latitude;
double pX = tap.longitude;
if ( (aY>pY && bY>pY) || (aY<pY && bY<pY) || (aX<pX && bX<pX) ) {
return false; }
double m = (aY-bY) / (aX-bX);
double bee = (-aX) * m + aY; // y = mx + b
double x = (pY - bee) / m;
return x > pX;
}**

Categories