I am trying to generate a graph with vertices having random coordinates and very low degree distribution. This network must look similar to road networks. The drawing etc is done automatically I just need to create very random numbers for the coordinates and make sure they do not overlap. How can I achieve this? Currently I have:
public void graphGenerator(int size) {
Point test = new Point();
Random random = new Random();
for (int i = 0; i < size; i++) {
test.x = random.nextInt(1000);
test.y = random.nextInt(700);
String name = Integer.toString(i);
Vertex v = new Vertex(name, test.x, test.y);
vertices.add(v);
}
}
My graph class has a list of vertices and edges: List vertices; and private List edges;
My edge class stores: vertex source, vertex target, vertex weight.
My vertex class stores: string name, int x, int y, List of adjacent edges.
Related
I have a use case where I need to generate GPS coordinates to cover an specific area (marked by a list og GPS coordinates).
So I need to generate coordinates. I have the following functions tested and implemented:
//determines wether a Waypoint is inside the specified area
public boolean isInsideArea(Waypoint waypoint)
public double distanceInKmBetweenGPSCoordinates(Waypoint from, Waypoint to)
public double[] calculateCoordinatesAfterMove(Waypoint waypoint, double dx, double dy)
Here is my naive implementation of how to generate coordinates for a square (or approximately a square):
public static List<drone.Waypoint> addAutoGeneratedWaypoints(List<Waypoint> polygon_lat_long_pairs) {
List<Waypoint> waypoints = new ArrayList<>();
AreaTester tester = new GPSPolygonTester(polygon_lat_long_pairs);
GPSCoordinateCalculator coordinateCalculator = new GPSCoordinateCalculator();
CustomGPSMapper mapper = new CustomGPSMapper();
boolean finish = false;
String mode = "r";
Waypoint prev = polygon_lat_long_pairs.get(0);
int count = 0;
double distanceDown = mapper.distanceInKmBetweenGPSCoordinates(polygon_lat_long_pairs.get(2), polygon_lat_long_pairs.get(3));
double travelledDown = 0;
while (!finish) {
if (mode.equals("r")) {
double[] nextA = coordinateCalculator.calculateCoordinatesAfterMove(prev.getPosition().getLatitude(), prev.getPosition().getLongitude(), 5.0, 0.0);
Waypoint next = new DefaultWaypoint(nextA[0], nextA[1]);
if (tester.isInsideArea(next)) {
System.out.println("Waypoint was in area");
waypoints.add(next);
prev = next;
} else {
System.err.println("Left area, switching position");
mode = "l";
double[] nextB = coordinateCalculator.calculateCoordinatesAfterMove(prev.getPosition().getLatitude(), prev.getPosition().getLongitude(), 0.0, -3.0);
Waypoint next2 = new DefaultWaypoint(nextB[0], nextB[1]);
waypoints.add(next2);
travelledDown += mapper.distanceInKmBetweenGPSCoordinates(prev, next);
prev = next2;
}
count++;
} else {
double[] nextA = coordinateCalculator.calculateCoordinatesAfterMove(prev.getPosition().getLatitude(), prev.getPosition().getLongitude(), -5.0, 0.0);
Waypoint next = new DefaultWaypoint(nextA[0], nextA[1]);
if (tester.isInsideArea(next)) {
waypoints.add(next);
prev = next;
} else {
System.out.println("Left are, switching");
mode = "r";
double[] nextB = coordinateCalculator.calculateCoordinatesAfterMove(prev.getPosition().getLatitude(), prev.getPosition().getLongitude(), 0.0, -3.0);
Waypoint next2 = new DefaultWaypoint(nextB[0], nextB[1]);
waypoints.add(next2);
travelledDown += mapper.distanceInKmBetweenGPSCoordinates(prev, next);
prev = next2;
}
count++;
}
if (travelledDown >= distanceDown) {
finish = true;
}
}
List<de.dhbw.drone.waypoints.Waypoint> mapped = waypoints.stream().map(p -> new de.dhbw.drone.waypoints.Waypoint(p)).collect(Collectors.toList());
return mapped;
I stop the algorithm when it has travelled down the right/left side of the square.
However, I am struggeling if the shape of the marked area is no square and has sloped lines.
Therefore I would have to move with a bearing, like shown in this image:
When I could add this angle to my movement, I could use this algorithm for each shape of area, resulting in the following path:
Can someone help me how to move a distance in meters in this specific angle and how to calculate this angle between two GPS coordinates and how to calculate the angle after turning the side? (right to left instead of left to right and vice versa). Or could this be solved by calculating angle(point1, point2) and angle(point2, point1) ?
To calculate azimuth from one coordinate to another and point at given distancem you can use formulas from latlong page (bearing and destination point sections)
You can use the same approach as usually implemented in 2d polygon rasterization.
Horizontal picture lines are continous in memory, so filling horizontal lines is the most reliable way.
In your case you can use, for example, lines at constant latitude.
Sort vertices of your earth polygon by latitude and separate ranges between vertex latitude values, then fill resulting "trapezoids" with point sequences (plane example)
Sometimes (complex polygon etc) it would be simpler to use rejection method - generate grid points in escribed rectangle and ignore those outside of polygon.
I want to check if a given point on a map (with its latitude and longitude) is inside a certain polygon. I have the vertex coords (in lat/long) of the polygon.
I thought of creating a Polygon and check if point is inside, but it gives me that the point is always outside... Maybe the polygon does not work with georeferential coords?
Double[] xCoords = {40.842226, 40.829498, 40.833394, 40.84768, 40.858716}
Double[] yCoords = {14.211753, 14.229262, 14.26617, 14.278701, 14.27715}
Double[] myPoint = {40.86141, 14.279932};
Path2D myPolygon = new Path2D.Double();
myPolygon.moveTo(xCoords[0], yCoords[0]); //first point
for(int i = 1; i < xCoords.length; i ++) {
myPolygon.lineTo(xCoords[i], yCoords[i]); //draw lines
}
myPolygon.closePath(); //draw last line
if(myPolygon.contains(myPoint{0}, myPoint{1})) {
//it's inside;
}
This is how it looks like in google maps
It always return false... but the point it's inside the polygon...
That point can't possibly be contained in that polygon, no matter what shape the polygon has.
Your right-most coordinate is at 40.858716 while the point has an x value of 40.86141, this means that the point lies on the right of your polygon. Same for y, max y coordinate in the polygon is 14.278701 while the point is at 14.279932. This means that the point is outside.
Also, you're inverting the coordinates, the coordinates of our beloved city are 40.8518° N, 14.2681° E, this means that 40 is the y and 14 the x.
Path2D will do just fine. My observation just tells you that the point is not in the polygon but checking the extremes is not a general solution for verifying that a point is inside a polygon.
public class CoordinatesDTO {
private Long id;
private double latitude;
private double longnitude;
}
public static boolean isLocationInsideTheFencing(CoordinatesDTO location, List<CoordinatesDTO> fencingCoordinates) { //this is important method for Checking the point exist inside the fence or not.
boolean blnIsinside = false;
List<CoordinatesDTO> lstCoordinatesDTO = fencingCoordinates;
Path2D myPolygon = new Path2D.Double();
myPolygon.moveTo(lstCoordinatesDTO.get(0).getLatitude(), lstCoordinatesDTO.get(0).getLongnitude()); // first
// point
for (int i = 1; i < lstCoordinatesDTO.size(); i++) {
myPolygon.lineTo(lstCoordinatesDTO.get(i).getLatitude(), lstCoordinatesDTO.get(i).getLongnitude()); // draw
// lines
}
myPolygon.closePath(); // draw last line
// myPolygon.contains(p);
Point2D P2D2 = new Point2D.Double();
P2D2.setLocation(location.getLatitude(), location.getLongnitude());
if (myPolygon.contains(P2D2)) {
blnIsinside = true;
} else {
blnIsinside = false;
}
return blnIsinside;
}
I want to generate a random spline across my screen.
Here is what I have so far:
public class CurvedPath {
Random rn;
CatmullRomSpline<Vector2> curve;
float[] xPts;
float[] yPts;
Vector2[] points;
public CurvedPath(){
points = new Vector2[10];
rn = new Random();
curve = new CatmullRomSpline<Vector2>(points,false);
for(int i = 0 ; i < 10; i++){
xPts[i] = rn.nextFloat()*SampleGame.WIDTH;
yPts[i] = SampleGame.HEIGHT*i/10;
}
}
}
I'm pretty confused on the documentation that has been provided on how to use the CatmullRomSpline object ( https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines )
Basically what I am trying to do here is generate 10 random points equally distributed across the height of my screen, and randomly placed along the width of the screen to create a randomized curved path.
So within the constructor's for loop you can see that I generate the x and y values of each control point for the spline.
How can I give input these points into the spline object and render it on the screen?
-thanks
update
Let me reword my question to be a little more specific..
I have my control points represented by xPts and yPts. Now I want to get the points that fall along the spline, how do I do this using these two vectors? The constructor for a CatmullRomSpline takes a Vector2, not two float[] 's
what you did. Fill with points:
curve = new CatmullRomSpline<Vector2>(points,false);
To get a point on the curve:
Vector2 point = new Vector2();
curve.valueAt(point, 0.5f);
valueAt() Parameter explanation:
1 (point) the point you are looking for is stored in the Vector2 object.
float between 0 and 1, 0 is the first point, 1 the last one. 0.5f is middle. This float represents the hole distance from first to last point.
Getting and render 100 points can look like this:
Vector2 point = new Vector2();
for (int i = 0; i <= 100; i++) {
curve.valueAt(point, i * 0.01f);
// draw using point.x and point.y
}
answer to you edited question:
for(int i = 0 ; i < 10; i++){
points[i].x = rn.nextFloat()*SampleGame.WIDTH;
points[i].y = SampleGame.HEIGHT*i/10;
}
curve = new CatmullRomSpline<Vector2>(points,false);
The process is also detailed here: https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines
/*members*/
int k = 100; //increase k for more fidelity to the spline
Vector2[] points = new Vector2[k];
/*init()*/
CatmullRomSpline<Vector2> myCatmull = new CatmullRomSpline<Vector2>(dataSet, true);
for(int i = 0; i < k; ++i)
{
points[i] = new Vector2();
myCatmull.valueAt(points[i], ((float)i)/((float)k-1));
}
I have a feeling this question is going to be something really common sense that I am overcomplicating. I am working on a random maze generation program, so given a width, height, and maximum path length, it will randomly select a start point and generate a path until the max path length is reached or it dead ends/gets stuck, then it will pick a new start point for another path and repeat until the whole grid is filled. I am just creating it for the practice.
I have 3 classes, but I guess I do not really understand how they should interact, or how I should make them interact for the best performance and such. One thing in particular, I just know is terrible practice. Since my Path and Point classes have to operate on the grid of Points that is created in the Maze class, I pass the constructors for Path and Point that Array of Points. It "works"... but I just realized that in doing that, I get a seemingly infinite loop where I create a grid, and create all the points for that grid, and in those points I pass an Array of Points, and each of those Points gets passed an Array of Points, forever.
I thought about making Path and Point extend Maze, but I do not think that is the right relationship. I googled interfaces and abstract classes to see if maybe that is what I wanted, but those did not seem right either.
Maze constructor:
public class Maze
{
private int fileNum = 0;
private Random rand = new Random();
private Point[] grid;
private int width, height;
private int pathLength;
private int curLoc;
private boolean debug, toTxt, toPng, hasValidNewHead = true;
public int frameNum = 0;
public int lastPercent = 0;
public Maze(int iWidth, int iHeight, int iPathLength, boolean d, boolean txt, boolean png)
{
width = iWidth;
height = iHeight;
pathLength = iPathLength;
grid = new Point[width * height];
debug = d;
toTxt = txt;
toPng = png;
}
Path constructor:
public class Path
{
private Random rand = new Random();
private Maze maze;
private int length, maxLength, lastDir, height, width;
private int curLoc;
private boolean generating;
private Point[] grid;
private boolean debug, toTxt, toPng;
public Path(int head, int gridWidth, int gridHeight, int ml, Point[] iGrid, Maze m, boolean d, boolean txt, boolean png)
{
maze = m;
generating = true;
lastDir = -1;
length = 1;
grid = iGrid;
curLoc = head;
height = gridHeight;
width = gridWidth;
maxLength = ml;
debug = d;
toTxt = txt;
toPng = png;
}
Point constructor:
public class Point
{
private int x, y, width, height;
private Point[] grid;
private int type, curLoc;
public Point(int iX, int iY, int w, int h, Point[] iGrid)
{
x = iX;
y = iY;
width = w;
height = h;
grid = iGrid;
curLoc = Arrays.asList(grid).indexOf(this);
type = 0;
}
Mazes are annoying to model because they're either structured around rooms or walls, you need different ones at different times, and either way, you'll end up with tricky code or redundant data and awkward record keeping.
Thad said, Paths are sequences/Lists of moves (North, South, East West), a Maze is an array (or Map) from a coordinate to a Cell/Room, and Cells have boolean walls keyed on moves, so { East: true, North: false, South, false, West: true}.
Or you could just make it an undirected graph.
All I had to do was make the Path and Point classes inner-classes in my Maze Class. That way they have all of the instance data from Maze that they need without needing to pass it through their constructors.
How can I mirror the fixture of a body in one axis(x or y), because when I want to mirror it only in one, an assertion error occurs, but when i mirror it in the two axis, no problem occur.
public Vector2[][] getPolygons(String bodyName, float scaleX, float scaleY)
{
Vector2[][] vectors = null;
Element fixture;
Element semiPolygon;
float auxX, auxY;
this.element = reader.parse(xml);
fixture = this.element.getChildByName(bodyName);
vectors = new Vector2[fixture.getChildCount()][];
for(int child = 0; child < fixture.getChildCount(); child++)
{
semiPolygon = fixture.getChild(child);
vectors[child] = new Vector2[semiPolygon.getChildCount()];
for(int part = 0; part < semiPolygon.getChildCount(); part++)
{
auxX = semiPolygon.getChild(part).getFloatAttribute("x")*-scaleX;
auxY = semiPolygon.getChild(part).getFloatAttribute("y")*-scaleY;
vectors[child][part] = World.toGameCoordinates(auxX, auxY);
}
}
return vectors;
}
Polygon vertices must be specified in counter clockwise order. Each time the shape is mirrored the winding order is reversed, so with only one mirror the order will be backwards, then if you mirror it again it will be ok, as you have discovered. So if you only mirror over one axis, you'll need to reverse the order of the vertices.