Point in Polygon Android - java

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;
}**

Related

A* algorithm current node spreading outwards instead of one direction

The yellow circle indicates the starting node and the red circle is indicating the goal node. I can't understand why my current node is spreading outwards instead of the image below where the node is just going straight into the goal.
I'm currently following this guide Link
I just can't get this part into my head on how should I choose a better path using G cost. It says that a lower G cost means a better path. but what node should I compare to that lower G cost?
If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square.
My desired output should be like this.
public class AStar {
private List<Node> open = new ArrayList<Node>();
private List<Node> close = new ArrayList<Node>();
private Node[][] nodes;
private GIS gis;
private MapListener mapListener;
private Arrow arrow;
public AStar(GIS gis) {
this.gis = gis;
mapListener = new MapListener(this);
createMapNodes();
}
private void createMapNodes() {
nodes = new Node[gis.getUslMap().getTileWidth()][gis.getUslMap().getTileHeight()];
for (int x = 0; x < gis.getUslMap().getTileWidth(); x++) {
for (int y = 0; y < gis.getUslMap().getTileHeight(); y++) {
TiledMapTileLayer.Cell cell = gis.getUslMap().getPathLayer().getCell(x, y);
arrow = new Arrow();
nodes[x][y] = new Node(cell, arrow, x, y);
if (cell != null) {
nodes[x][y].setBounds(x * Map.TILE.getSize(), y * Map.TILE.getSize(), Map.TILE.getSize(), Map.TILE.getSize());
nodes[x][y].getLabel().setBounds(x * Map.TILE.getSize(), y * Map.TILE.getSize(), Map.TILE.getSize(), Map.TILE.getSize());
nodes[x][y].getArrow().getImage().setBounds(x * Map.TILE.getSize(), y * Map.TILE.getSize(), Map.TILE.getSize(), Map.TILE.getSize());
mapListener = new MapListener(this);
nodes[x][y].addListener(mapListener);
gis.getUslMap().getStage().getActors().add(nodes[x][y].getLabel());
gis.getUslMap().getStage().getActors().add(nodes[x][y].getArrow().getImage());
gis.getUslMap().getStage().addActor(nodes[x][y]);
nodes[x][y].debug();
}
}
}
}
private void clearNodes() {
for (int x = 0; x < gis.getUslMap().getTileWidth(); x++) {
for (int y = 0; y < gis.getUslMap().getTileHeight(); y++) {
nodes[x][y].gCost = 0;
nodes[x][y].hCost = 0;
nodes[x][y].fCost = 0;
nodes[x][y].getLabel().setText("");
nodes[x][y].getArrow().setDrawable("blank");
}
}
close.clear();
open.clear();
}
public void search(Vector2 start, Node goal) {
clearNodes();
Node current = nodes[(int) start.x][(int) start.y];
open.add(current);
while (!open.isEmpty()) {
current = getLowestFCost(open);
if (current == goal)
return;
open.remove(current);
close.add(current);
// Prints the Fcost.
current.getLabel().setText(current.fCost + "");
// Detect the adjacent tiles or nodes of the current node
// and calculate the G, H and F cost
for (int x = -1; x < 2; x++) {
for (int y = -1; y < 2; y++) {
int dx = current.x + x;
int dy = current.y + y;
if (isValidLocation(dx, dy)) {
if (isWalkable(x, y, nodes[dx][dy]))
continue;
if (!open.contains(nodes[dx][dy])) {
open.add(nodes[dx][dy]);
nodes[dx][dy].parent = current;
if (isDiagonal(x, y))
nodes[dx][dy].gCost = current.gCost + 14;
else
nodes[dx][dy].gCost = current.gCost + 10;
nodes[dx][dy].fCost = nodes[dx][dy].gCost + heuristic(nodes[dx][dy], goal);
} else if (open.contains(nodes[dx][dy])&&) {
}
}
}
}
}
}
private boolean isWalkable(int x, int y, Node node) {
return x == 0 && y == 0 || node.getCell() == null || close.contains(node);
}
private boolean isValidLocation(int dx, int dy) {
return dx > 0 && dx < gis.getUslMap().getTileWidth() &&
dy > 0 && dy < gis.getUslMap().getTileHeight();
}
private boolean isDiagonal(int x, int y) {
return x == -1 && y == 1 || x == 1 && y == 1 ||
x == -1 && y == -1 || y == -1 && x == 1;
}
private Node getLowestFCost(List<Node> open) {
int lowestCost = 0;
int index = 0;
for (int i = 0; i < open.size(); i++) {
if (open.get(i).fCost <= lowestCost) {
lowestCost = open.get(i).fCost;
index = i;
}
}
return open.get(index);
}
private int heuristic(Node start, Node goal) {
int dx = Math.abs(start.x - goal.x);
int dy = Math.abs(start.y - goal.y);
start.hCost = 10 * (dx + dy);
return start.hCost;
}
}
My node.class
private TiledMapTileLayer.Cell cell;
private Label label;
private Arrow arrow;
boolean diagonal;
Node parent;
int x;
int y;
int hCost;
int gCost;
int fCost;
public Node(TiledMapTileLayer.Cell cell, Arrow arrow, int x, int y) {
this.cell = cell;
this.x = x;
this.y = y;
this.arrow = arrow;
label = new Label("", Assets.getInstance().getMapAsset().getAssetSkin(), "default");
label.setPosition(this.getX(), this.getY());
}
TiledMapTileLayer.Cell getCell() {
return cell;
}
Label getLabel() {
return label;
}
public Arrow getArrow() {
return arrow;
}
I think you have a problem to get the lowestcost:
private Node getLowestFCost(List<Node> open) {
int lowestCost = 0;
int index = 0;
for (int i = 0; i < open.size(); i++) {
if (open.get(i).fCost <= lowestCost) {
lowestCost = open.get(i).fCost;
index = i;
}
}
return open.get(index);
}
you initiate lowestCost = 0 but fCost always more than 0, so this function is not really work. It makes the lowest cost obtained from initial lowestCost, not from fCost open list. Try to initiate lowestCost with big number or first value in open list.

Java 2D Polygon - Polygon Collision Detection

Recently I have been using the Polygon class to create asteroids as well as bullets and a spaceship. I am currently trying to create the collision detection for the program however it appears that the collision detection only works around 1/5 of the time (no pattern appears as to why it works).
Here's the code..
Creating the Polygon:
void renderPoly() {
int j;
int s = sides;
double r, angle;
int x, y;
for (j = 0; j < s; j++) {
angle = 2 * Math.PI / s * j;
r = MIN_ROCK_SIZE + (int) (Math.random() * (MAX_ROCK_SIZE - MIN_ROCK_SIZE));
x = (int) (r * Math.cos(angle));
y = (int) (r * -Math.sin(angle));
cOM[0] += x;
cOM[1] += y;
pointData[j][0] = x;
pointData[j][1] = y;
}
cOM[0] /= asteroidShape.npoints;
cOM[1] /= asteroidShape.npoints;
for (int i = 0; i < asteroidShape.npoints; i++) {
pointData[i][0] += cOM[0];
pointData[i][1] += cOM[1];
}
}
rotating and moving the polygon:
void move() {
int x, y, i;
//change rotation
theta += rotVel;
//change x
asteroidData[0] += deltaX;
//change y
asteroidData[1] += deltaY;
for (i = 0; i < asteroidShape.npoints; i++) {
x = (int) (pointData[i][0] * Math.cos(theta) - pointData[i][1] * Math.sin(theta) );
y = (int) (pointData[i][0] * Math.sin(theta) + pointData[i][1] * Math.cos(theta) );
asteroidShape.xpoints[i] = x + asteroidData[0];
asteroidShape.ypoints[i] = y + asteroidData[1];
asteroidShape.invalidate();
}
}
check if touching bullet:
boolean hitBullet(Bullet b) {
this.asteroidShape.invalidate();
for (int i = 0; i < b.bulletShape.npoints; i++)
if (this.asteroidShape.contains(b.bulletShape.xpoints[i], b.bulletShape.ypoints[i]) )
return true;
for (int j = 0; j < this.asteroidShape.npoints; j++)
if (b.bulletShape.contains(this.asteroidShape.xpoints[j], this.asteroidShape.ypoints[j]) )
return true;
return false;
}
(the ship method is the same except the constructor requires a ship object)
as well as the loop that calls it in the 'game' class:
for (int i = 0; i < aArray.length-1; i++) {
if (aArray[i] != null) {
for (int j = 0; j < bArray.length-1; j++) {
if (bArray[j] != null) {
if (aArray[i].hitBullet(bArray[j])) {
aArray[i] = null;
bArray[j] = null;
i = aArray.length-1;
j = bArray.length-1;
}
}
else {
i = aArray.length-1;
j = bArray.length-1;
}
}
}
else {
i = aArray.length-1;
}
}
I have been looking around at alternative solutions such as the Separating Axis Theorem however I do have convex polygons at times and since this method (.contains()) already exists I would like to use it.
Any help would be appreciated, thanks!
The easy way to solve this that I've found is to convert Shapes (in your case Polygon(2D?)) into Areas. You can use Area.intersect(Area) to see if two Areas have collided

Perspective View to Parallel View

in the example which is given in the book "Computer Graphics for Java Programmers, Second Edition"
there is transformation with view vector
private void shiftToOrigin()
{ float xwC = 0.5F * (xMin + xMax),
ywC = 0.5F * (yMin + yMax),
zwC = 0.5F * (zMin + zMax);
int n = w.size();
for (int i=1; i<n; i++)
if (w.elementAt(i) != null)
{ ((Point3D)w.elementAt(i)).x -= xwC;
((Point3D)w.elementAt(i)).y -= ywC;
((Point3D)w.elementAt(i)).z -= zwC;
}
float dx = xMax - xMin, dy = yMax - yMin, dz = zMax - zMin;
rhoMin = 0.6F * (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
rhoMax = 1000 * rhoMin;
rho = 3 * rhoMin;
}
private void initPersp()
{
float costh = (float)Math.cos(theta),
sinth = (float)Math.sin(theta),
cosph = (float)Math.cos(phi),
sinph = (float)Math.sin(phi);
v11 = -sinth; v12 = -cosph * costh; v13 = sinph * costh;
v21 = costh; v22 = -cosph * sinth; v23 = sinph * sinth;
v32 = sinph; v33 = cosph;
v43 = -rho;
}
float eyeAndScreen(Dimension dim)
// Called in paint method of Canvas class
{ initPersp();
int n = w.size();
e = new Point3D[n];
vScr = new Point2D[n];
float xScrMin=1e30F, xScrMax=-1e30F,
yScrMin=1e30F, yScrMax=-1e30F;
for (int i=1; i<n; i++)
{
Point3D P = (Point3D)(w.elementAt(i));
if (P == null)
{ e[i] = null; vScr[i] = null;
}
else
{ float x = v11 * P.x + v21 * P.y;
float y = v12 * P.x + v22 * P.y + v32 * P.z;
float z = v13 * P.x + v23 * P.y + v33 * P.z + v43;
Point3D Pe = e[i] = new Point3D(x, y, z);
float xScr = -Pe.x/Pe.z, yScr = -Pe.y/Pe.z;
vScr[i] = new Point2D(xScr, yScr);
if (xScr < xScrMin) xScrMin = xScr;
if (xScr > xScrMax) xScrMax = xScr;
if (yScr < yScrMin) yScrMin = yScr;
if (yScr > yScrMax) yScrMax = yScr;
}
}
float rangeX = xScrMax - xScrMin, rangeY = yScrMax - yScrMin;
d = 0.95F * Math.min(dim.width/rangeX, dim.height/rangeY); //d burada
imgCenter = new Point2D(d * (xScrMin + xScrMax)/2,
d * (yScrMin + yScrMax)/2);
for (int i=1; i<n; i++)
{
if (vScr[i] != null){vScr[i].x *= d; vScr[i].y *= d;}
}
return d * Math.max(rangeX, rangeY);
// Maximum screen-coordinate range used in CvHLines for HP-GL
}
here float xScr = -Pe.x/Pe.z, yScr = -Pe.y/Pe.z; when we divide x and y with z that give as a perspective view if we don't divide it with z the view will be parallel(orthogonal)
this is OK but if we want to this parallel view coordinates with hidden line algorithm in same book it calculates lines wrongly. I couldn't find where problem is. What can cause this problem?
here hidden line algorithm:
private void lineSegment(Graphics g, Point3D Pe, Point3D Qe,
Point2D PScr, Point2D QScr, int iP, int iQ, int iStart)
{
double u1 = QScr.x - PScr.x; //t
double u2 = QScr.y - PScr.y; //t
double minPQx = Math.min(PScr.x, QScr.x);//t
double maxPQx = Math.max(PScr.x, QScr.x);//t
double minPQy = Math.min(PScr.y, QScr.y);//t
double maxPQy = Math.max(PScr.y, QScr.y);//t
double zP = Pe.z; //t
double zQ = Qe.z; //t
double minPQz = Math.min(zP, zQ);//t
Point3D[] e = obj.getE();//e eye
Point2D[] vScr = obj.getVScr(); //vscr screen
for (int i=iStart; i<nTria; i++)//t
{
Tria t = tr[i];
int iA = t.iA, iB = t.iB, iC = t.iC;
Point2D AScr = vScr[iA], BScr = vScr[iB], CScr = vScr[iC];
// 1. Minimax test for x and y screen coordinates: //t
if (maxPQx <= AScr.x && maxPQx <= BScr.x && maxPQx <= CScr.x
|| minPQx >= AScr.x && minPQx >= BScr.x && minPQx >= CScr.x
|| maxPQy <= AScr.y && maxPQy <= BScr.y && maxPQy <= CScr.y
|| minPQy >= AScr.y && minPQy >= BScr.y && minPQy >= CScr.y)
continue;
// 2. Test if PQ is an edge of ABC: //t
if ((iP == iA || iP == iB || iP == iC) &&
(iQ == iA || iQ == iB || iQ == iC))
continue;
// 3. Test if PQ is clearly nearer than ABC://t
Point3D Ae = e[iA], Be = e[iB], Ce = e[iC];
double zA = Ae.z, zB = Be.z, zC = Ce.z;
if (minPQz >= zA && minPQz >= zB && minPQz >= zC)
continue;
// 4. Do P and Q (in 2D) lie in a half plane defined
// by line AB, on the side other than that of C?
// Similar for the edges BC and CA.
double eps = 0.1; // Relative to numbers of pixels //t
if (Tools2D.area2(AScr, BScr, PScr) < eps &&
Tools2D.area2(AScr, BScr, QScr) < eps ||
Tools2D.area2(BScr, CScr, PScr) < eps &&
Tools2D.area2(BScr, CScr, QScr) < eps ||
Tools2D.area2(CScr, AScr, PScr) < eps &&
Tools2D.area2(CScr, AScr, QScr) < eps)
continue;
// 5. Test (2D) if A, B and C lie on the same side
// of the infinite line through P and Q://t
double PQA = Tools2D.area2(PScr, QScr, AScr);
double PQB = Tools2D.area2(PScr, QScr, BScr);
double PQC = Tools2D.area2(PScr, QScr, CScr);
if (PQA < +eps && PQB < +eps && PQC < +eps ||
PQA > -eps && PQB > -eps && PQC > -eps)
continue;
// 6. Test if neither P nor Q lies behind the
// infinite plane through A, B and C://t
int iPol = refPol[i];
Polygon3D pol = (Polygon3D)polyList.elementAt(iPol);
double a = pol.getA(), b = pol.getB(), c = pol.getC(),
h = pol.getH(), eps1 = 1e-5 * Math.abs(h),
hP = a * Pe.x + b * Pe.y + c * Pe.z,
hQ = a * Qe.x + b * Qe.y + c * Qe.z;
if (hP > h - eps1 && hQ > h - eps1)
continue;
// 7. Test if both P and Q behind triangle ABC://t
boolean PInside =
Tools2D.insideTriangle(AScr, BScr, CScr, PScr);
boolean QInside =
Tools2D.insideTriangle(AScr, BScr, CScr, QScr);
if (PInside && QInside)
return;
// 8. If P nearer than ABC and inside, PQ visible;//t
// the same for Q:
double h1 = h + eps1;
boolean PNear = hP > h1, QNear = hQ > h1;
if (PNear && PInside || QNear && QInside)
continue;
// 9. Compute the intersections I and J of PQ
// with ABC in 2D.
// If, in 3D, such an intersection lies in front of
// ABC, this triangle does not obscure PQ.
// Otherwise, the intersections lie behind ABC and
// this triangle obscures part of PQ:
double lambdaMin = 1.0, lambdaMax = 0.0;
for (int ii=0; ii<3; ii++)
{ double v1 = BScr.x - AScr.x, v2 = BScr.y - AScr.y,
w1 = AScr.x - PScr.x, w2 = AScr.y - PScr.y,
denom = u2 * v1 - u1 * v2;
if (denom != 0)
{ double mu = (u1 * w2 - u2 * w1)/denom;
// mu = 0 gives A and mu = 1 gives B.
if (mu > -0.0001 && mu < 1.0001)
{ double lambda = (v1 * w2 - v2 * w1)/denom;
// lambda = PI/PQ
// (I is point of intersection)
if (lambda > -0.0001 && lambda < 1.0001)
{ if (PInside != QInside &&
lambda > 0.0001 && lambda < 0.9999)
{ lambdaMin = lambdaMax = lambda;
break;
// Only one point of intersection
}
if (lambda < lambdaMin) lambdaMin = lambda;
if (lambda > lambdaMax) lambdaMax = lambda;
}
}
}
Point2D temp = AScr; AScr = BScr;
BScr = CScr; CScr = temp;
}
float d = obj.getD();
if (!PInside && lambdaMin > 0.001)
{ double IScrx = PScr.x + lambdaMin * u1,
IScry = PScr.y + lambdaMin * u2;
// Back from screen to eye coordinates:
double zI = 1/(lambdaMin/zQ + (1 - lambdaMin)/zP),
xI = -zI * IScrx / d, yI = -zI * IScry / d;
if (a * xI + b * yI + c * zI > h1) continue;
Point2D IScr = new Point2D((float)IScrx, (float)IScry);
if (Tools2D.distance2(IScr, PScr) >= 1.0)
lineSegment(g, Pe, new Point3D(xI, yI, zI), PScr,
IScr, iP, -1, i + 1);
}
if (!QInside && lambdaMax < 0.999)
{ double JScrx = PScr.x + lambdaMax * u1,
JScry = PScr.y + lambdaMax * u2;
double zJ =
1/(lambdaMax/zQ + (1 - lambdaMax)/zP),
xJ = -zJ * JScrx / d, yJ = -zJ * JScry / d;
if (a * xJ + b * yJ + c * zJ > h1) continue;
Point2D JScr = new Point2D((float)JScrx, (float)JScry);
if (Tools2D.distance2(JScr, QScr) >= 1.0)
lineSegment(g, Qe, new Point3D(xJ, yJ, zJ),
QScr, JScr, iQ, -1, i + 1);
}
return;
// if no continue-statement has been executed
}
drawLine(g, PScr.x, PScr.y, QScr.x, QScr.y);
}
}

Estimating Area Between Shapes

In my class, we are given the task as follows:
For this assignment you will attempt to make a program for computing the overlapping area of a set of shapes, implementing Monte Carlo integration, as discussed in class.
Make AreaEstimator.java, a program that estimates the area of overlap of an arbitrary number of circles and triangles using randomized estimation. The program's arguments will be the number of randomly-generated points to be used in this trial, followed by the coordinates of the points that define the shapes. For example,
java AreaEstimator 1000000 circle 2.0 2.0 1.0 triangle 1.0 1.0 2.5 3.0 2.0 -3.0 circle 2.5 1.0 3.0
would generate one million random points to estimate the overlap of a triangle whose vertices are ( 1.0, 1.0 ), ( 2.5, 3.0 ), ( 2.0, -3.0 ), with two circles whose centers are at ( 2.0, 2.0 ) and ( 2.5, 1.0 ), and whose radii are 1.0 and 3.0, respectively.
Here is my code for the Circle class:
public class Circle {
private double xcenter;
private double ycenter;
private double radius;
private double xcmax;
private double xcmin;
private double ycmax;
private double ycmin;
public Circle ( double xcenter, double ycenter, double radius){
if(radius <= 0){
throw new IllegalArgumentException();
}
this.xcenter = xcenter;
this.ycenter = ycenter;
this.radius = radius;
}
public void maxAndMinCircle (){ //find the minimun and maximum for the plane according to this circle
xcmax = (this.xcenter + this.radius);
ycmax = (this.ycenter + this.radius);
xcmin = (this.xcenter - this.radius);
ycmin = (this.ycenter - this.radius);
}
public double getXCMax (){
return xcmax;
}
public double getYCMax () {
return ycmax;
}
public double getXCMin() {
return xcmin;
}
public double getYCMin(){
return ycmin;
}
public boolean outsideCircle(double randX, double randY){ // find if the random point passed thru is in this circle
double distance = Math.sqrt((randX-this.xcenter)*(randX-this.xcenter) + (randY-this.ycenter) * (randY - this.ycenter));
return distance >= radius;
}}
The Triangle Class:
public class Triangle {
private double cornerx1;
private double cornery1;
private double cornerx2;
private double cornery2;
private double cornerx3;
private double cornery3;
private double xtmax;
private double xtmin;
private double ytmax;
private double ytmin;
private Double[] corners;
public Triangle (double cornerx1, double cornery1, double cornerx2, double cornery2, double cornerx3, double cornery3){
corners = new Double [6];
corners[0] = cornerx1;
corners[1] = cornery1;
corners[2] = cornerx2;
corners[3] = cornery2;
corners[4] = cornerx3;
corners[5] = cornery3;
}
public void maxAndMinTriangle (){ // find the minimum and maximum of the plane according to this triangle
xtmax = corners[0];
for(int i=1;i < corners.length;i += 2){
if(corners[i] > xtmax){
xtmax = corners[i];
}
}
xtmin = corners[0];
for(int i=1;i < corners.length;i += 2){
if(corners[i] < xtmin){
xtmin = corners[i];
}
}
ytmax = corners[1];
for(int i=1;i < corners.length;i += 2){
if(corners[i] > ytmax){
ytmax = corners[i];
}
}
ytmin = corners[1];
for(int i=1;i < corners.length;i += 2){
if(corners[i] < ytmin){
ytmin = corners[i];
}
}
}
public double getXTMax (){
return xtmax;
}
public double getYTMax () {
return ytmax;
}
public double getXTMin() {
return xtmin;
}
public double getYTMin(){
return ytmin;
}
//public static boolean isLeft (double x1, double y1, double x2, double y2, double x3, double y3){
//return ( 0 <= ( ( x2 - x1 ) * ( y - y1) )- (( y2 - y1) * ( x - x1)));
//}
public boolean isLeft1 (double randX, double randY){ // find if this point is to the left of the first line
return ( 0 <= ( ( corners[2] - corners[0] ) * ( randY - corners[1]) )- (( corners[3] - corners[1]) * ( randX - corners[0])));
}
public boolean isLeft2 (double randX, double randY){ // find if this point is to the left of the second line
return ( 0 <= ( ( corners[4] - corners[0]) * ( randY - corners[1]) )- (( corners[5] - corners[1]) * ( randX - corners[0])));
}
public boolean isLeft3 (double randX, double randY){ // find if this point is to the left of the third line
return ( 0 <= ( ( corners[4] - corners[2] ) * ( randY - corners[3]) )- (( corners[5] - corners[3]) * ( randX - corners[2])));
}
public boolean outsideTriangle ( double randX, double randY ){ // find if this point is inside of the triangle
int counter = 0;
if (isLeft1(randX,randY)){
counter++;
}
if (isLeft2(randX,randY)){
counter++;
}
if (isLeft3(randX,randY)){
counter++;
}
return counter == 2; // must be to the left of exactly 2 of the lines
}}
And then the AreaEstimator class:
public class AreaEstimator{
public static double[] maxAndMinValues (Circle[] circles,Triangle[] triangles){
// find maximum and minimum values according to all of the triangles and circles
double xmax = -100;
double ymax = -100;
double xmin = 100;
double ymin = 100;
for (int l=0; l < circles.length; l++){
if (xmax < circles[l].getXCMax()){
xmax = circles[l].getXCMax();
}
if (ymax < circles[l].getYCMax()){
ymax = circles[l].getYCMax();
}
if (xmin > circles[l].getXCMin()){
xmin = circles[l].getXCMin();
}
if (ymin > circles[l].getYCMin()){
ymin = circles[l].getYCMin();
}
}
for ( int m = 0; m < triangles.length; m++){
if(xmax < triangles[m].getXTMax()){
xmax = triangles[m].getXTMax();
}
if(ymax < triangles[m].getYTMax()){
ymax = triangles[m].getYTMax();
}
if(xmin > triangles[m].getXTMin()){
xmin = triangles[m].getXTMin();
}
if(ymin > triangles[m].getYTMin()){
ymin = triangles[m].getYTMin();
}
}
double[] result = new double [4];
result[0] = xmax;
result[1] = ymax;
result[2] = xmin;
result[3] = ymin;
return result;
}
public static void main (String[] args) {
double numThrows = Integer.parseInt(args[0]); // initialize amount of throws
if (numThrows <= 0){
throw new IllegalArgumentException();
}
int countCircles = 0; // find the amount of circles given
for ( int i = 1; i<args.length; i++){
if(args[i].equals("circle")){
countCircles++;
}
}
Circle[] circles = new Circle [countCircles];
for ( int i = 1; i<args.length; i++){
if (args[i].equals("circle")){
for ( int k = 0; k< countCircles; k++){
double xcenter = Double.parseDouble(args[i+1]);
double ycenter = Double.parseDouble(args[i+2]);
double radius = Double.parseDouble(args[i+3]);
circles[k] = new Circle (xcenter, ycenter, radius); //values associated with this circle
circles[k].maxAndMinCircle();//max and min value of the circle itself
}
}
}
int countTriangles = 0; // find the amount of the triangles given
for ( int i = 1; i < args.length; i++){
if(args[i].equals("triangle")){
countTriangles++;
}
}
Triangle[] triangles = new Triangle [countTriangles];
for ( int i = 1; i<args.length; i++){
if (args[i].equals("triangle")){
for ( int p = 0; p< countTriangles; p++){
double cornerx1 = Double.parseDouble(args[i+1]);
double cornery1 = Double.parseDouble(args[i+2]);
double cornerx2 = Double.parseDouble(args[i+3]);
double cornery2 = Double.parseDouble(args[i+4]);
double cornerx3 = Double.parseDouble(args[i+5]);
double cornery3 = Double.parseDouble(args[i+6]);
triangles[p] = new Triangle (cornerx1, cornery1, cornerx2, cornery2, cornerx3, cornery3);
//values associated with this triangle
triangles[p].maxAndMinTriangle(); //max and min value of the triangle itself
}
}
}
boolean dartsInOverlap = true;
double countInOverlap = 0; // initialize amount of darts in the overlapping shape
double[]result = maxAndMinValues(circles,triangles);
for(int i= 0;i < numThrows;i++){
double randX= (Math.random() * (result[0]-result[2]) + result[2]) ; // generate a random x value
double randY= (Math.random() * (result[1]-result[3])+ result[3]); // generate a random y value
for ( int h = 0; h < circles.length && dartsInOverlap; h++){
if (circles[h].outsideCircle(randX, randY)){
dartsInOverlap = false; // if the point is outside of the circle, it returns false
}
}
for ( int q = 0; q < triangles.length && dartsInOverlap; q++){
if (triangles[q].outsideTriangle(randX, randY)){
dartsInOverlap = false; // if the point is outside of the triangle, it returns false
}
}
if (dartsInOverlap){
countInOverlap++; // counts up the amount of points in the overlapping shape
}
dartsInOverlap = true;
}
System.out.println("This many darts were in the overlap between the shapes:" + countInOverlap);
// counts up the amount of points in the overlapping shape
System.out.println("The estimated overlapped areas is" + (result[0]-result[2])*(result[1]-result[3]) *(countInOverlap/numThrows));
//finds estimated area
}}
My code has worked for a few test cases, if in the command line there is only a circle and triangle entered, or only a sole circle. A triangle by itself or any other combination will give me answers far from the desired area estimation. I have looked and reviewed my code, and it all seems logical. So, where in my code could the problem persist? Any help would be appreciated.
There is at least a typo in maxAndMinTriangle. You wrote a 1 where you need a 0
xtmax = corners[0];
for(int i=1;i < corners.length;i += 2){
...
xtmin = corners[0];
for(int i=1;i < corners.length;i += 2){
it should be
xtmax = corners[0];
for(int i=0;i < corners.length;i += 2){
...
xtmin = corners[0];
for(int i=0;i < corners.length;i += 2){

Can anyone help me understand how to simulate fluids?

I'm trying to make a program that simulates the physics of fluids in Processing. In the IDE there's an included example:
/**
* Fluid
* by Glen Murphy.
*
* Click and drag the mouse to move the simulated fluid.
* Adjust the "res" variable below to change resolution.
* Code has not been optimised, and will run fairly slowly.
*/
int res = 2;
int penSize = 30;
int lwidth;
int lheight;
int pnum = 30000;
vsquare[][] v;
vbuffer[][] vbuf;
particle[] p = new particle[pnum];
int pcount = 0;
int mouseXvel = 0;
int mouseYvel = 0;
void setup()
{
size(200, 200);
noStroke();
frameRate(30);
lwidth = width/res;
lheight = height/res;
v = new vsquare[lwidth+1][lheight+1];
vbuf = new vbuffer[lwidth+1][lheight+1];
for (int i = 0; i < pnum; i++) {
p[i] = new particle(random(res,width-res),random(res,height-res));
}
for (int i = 0; i <= lwidth; i++) {
for (int u = 0; u <= lheight; u++) {
v[i][u] = new vsquare(i*res,u*res);
vbuf[i][u] = new vbuffer(i*res,u*res);
}
}
}
void draw()
{
background(#666666);
int axvel = mouseX-pmouseX;
int ayvel = mouseY-pmouseY;
mouseXvel = (axvel != mouseXvel) ? axvel : 0;
mouseYvel = (ayvel != mouseYvel) ? ayvel : 0;
for (int i = 0; i < lwidth; i++) {
for (int u = 0; u < lheight; u++) {
vbuf[i][u].updatebuf(i,u);
v[i][u].col = 32;
}
}
for (int i = 0; i < pnum-1; i++) {
p[i].updatepos();
}
for (int i = 0; i < lwidth; i++) {
for (int u = 0; u < lheight; u++) {
v[i][u].addbuffer(i, u);
v[i][u].updatevels(mouseXvel, mouseYvel);
v[i][u].display(i, u);
}
}
}
class particle {
float x;
float y;
float xvel;
float yvel;
int pos;
particle(float xIn, float yIn) {
x = xIn;
y = yIn;
}
void updatepos() {
float col1;
if (x > 0 && x < width && y > 0 && y < height) {
int vi = (int)(x/res);
int vu = (int)(y/res);
vsquare o = v[vi][vu];
float ax = (x%res)/res;
float ay = (y%res)/res;
xvel += (1-ax)*v[vi][vu].xvel*0.05;
yvel += (1-ay)*v[vi][vu].yvel*0.05;
xvel += ax*v[vi+1][vu].xvel*0.05;
yvel += ax*v[vi+1][vu].yvel*0.05;
xvel += ay*v[vi][vu+1].xvel*0.05;
yvel += ay*v[vi][vu+1].yvel*0.05;
o.col += 4;
x += xvel;
y += yvel;
}
else {
x = random(0,width);
y = random(0,height);
xvel = 0;
yvel = 0;
}
xvel *= 0.5;
yvel *= 0.5;
}
}
class vbuffer {
int x;
int y;
float xvel;
float yvel;
float pressurex = 0;
float pressurey = 0;
float pressure = 0;
vbuffer(int xIn,int yIn) {
x = xIn;
y = yIn;
pressurex = 0;
pressurey = 0;
}
void updatebuf(int i, int u) {
if (i>0 && i<lwidth && u>0 && u<lheight) {
pressurex = (v[i-1][u-1].xvel*0.5 + v[i-1][u].xvel + v[i-1][u+1].xvel*0.5 - v[i+1][u-1].xvel*0.5 - v[i+1][u].xvel - v[i+1][u+1].xvel*0.5);
pressurey = (v[i-1][u-1].yvel*0.5 + v[i][u-1].yvel + v[i+1][u-1].yvel*0.5 - v[i-1][u+1].yvel*0.5 - v[i][u+1].yvel - v[i+1][u+1].yvel*0.5);
pressure = (pressurex + pressurey)*0.25;
}
}
}
class vsquare {
int x;
int y;
float xvel;
float yvel;
float col;
vsquare(int xIn,int yIn) {
x = xIn;
y = yIn;
}
void addbuffer(int i, int u) {
if (i>0 && i<lwidth && u>0 && u<lheight) {
xvel += (vbuf[i-1][u-1].pressure*0.5
+vbuf[i-1][u].pressure
+vbuf[i-1][u+1].pressure*0.5
-vbuf[i+1][u-1].pressure*0.5
-vbuf[i+1][u].pressure
-vbuf[i+1][u+1].pressure*0.5
)*0.25;
yvel += (vbuf[i-1][u-1].pressure*0.5
+vbuf[i][u-1].pressure
+vbuf[i+1][u-1].pressure*0.5
-vbuf[i-1][u+1].pressure*0.5
-vbuf[i][u+1].pressure
-vbuf[i+1][u+1].pressure*0.5
)*0.25;
}
}
void updatevels(int mvelX, int mvelY) {
if (mousePressed) {
float adj = x - mouseX;
float opp = y - mouseY;
float dist = sqrt(opp*opp + adj*adj);
if (dist < penSize) {
if (dist < 4) dist = penSize;
float mod = penSize/dist;
xvel += mvelX*mod;
yvel += mvelY*mod;
}
}
xvel *= 0.99;
yvel *= 0.99;
}
void display(int i, int u) {
float tcol = 0;
if (col > 255) col = 255;
if (i>0 && i<lwidth-1 && u>0 && u<lheight-1) {
tcol = (+ v[i][u+1].col
+ v[i+1][u].col
+ v[i+1][u+1].col*0.5
)*0.4;
tcol = (int)(tcol+col*0.5);
}
else {
tcol = (int)col;
}
fill(tcol, tcol, tcol);
rect(x,y,res,res);
}
}
It's not really commented and I'm somewhat new to programming, so I have no idea where to start as far as understanding it. Is there any good reading on fluid physics? I'm more interesting in the visual effect than the accuracy of the simulation.
A good starting point could be the paper Stable Fluids, it will show you the math behind the fluid simulation, and in the third chapter it describe the implementation of a fluid solver. There is also an open source implementation available in sourceforge (you will need to checkout the source with cvs).

Categories