I was wondering how I'd use different points in Java to draw a line. Here is the code I have so far. I would prefer to not get the x and y of each point and just have the program use the points from x, y on its own. I am still pretty new to programming and not very good at using javadoc at this point. The following is the code I have now:
//Create a Polygon class. A polygon is a closed shape with lines joining the corner points.
//You will keep the points in an array list. Use object of java.awt.Point for the point.
//Polygon will have as an instance variable an ArrayList of Points to hold the points
//The constructor takes no parameters but initializes the instance variable. The
//Polygon class also has the following methods:
// add: adds a Point to the polygon
// perimeter: returns the perimeter of the polygon
// draw: draws the polygon by connecting consecutive points and then
// connecting the last point to the first.
//
//No methods headers or javadoc is provided this time. You get to try your hand at writing
//a class almost from scratch
// Need help starting this question? In the lesson titled
// "Starting points: Problem Set Questions", go to the
// problem titled "Problem Set 6 - Question 3" for some tips on
// how to begin.
import java.util.ArrayList; import java.awt.Point;
public class Polygon {
ArrayList<Point> points;
/**
** a Polygon represents a shape with flat lines and several points.
*/
public Polygon(){
/**
* Constructs empty array of points.
*/
points = new ArrayList<Point>();
} /** ** Adds points to the polygon points Array. *#param = points x and y coordinates to add to class */
public void addPoints(Point point){
points.add(point);
}
/**
**gets distance between points in ArrayList
*/
public double perimeter(){
double perimeter = 0;
int i = 0;
while(i<points.size()){
if(i<points.size()-1){
perimeter = perimeter + points.get(i).distance(points.get(i+1));
}
else{
perimeter = perimeter + points.get(i).distance(points.get(0));
}
}
return perimeter;
}
/** * Draws Polygon using points from points ArrayList */
public void drawPolygon(){
int i = 0;
while(i < points.size()-1){
Line2D line = Line2D.Float(points.get(i), points.get(i+1));
line.draw();
}
Line2D lastLine = Line2D.Float(points.get(0), points.get(points.size()-1));
lastLine.draw();
} }
Let me understand this correctly, you want to implement the draw() method?
If so, what you need to do is search for Bresenham's Algorithm which draws a line based on two given points.
I know this exact question, because I encountered some MAJOR issues with it too.. I stumbled across this question during Udacity's Java Basics course.
I was so stuck, until I moved onto the proceeding lessons which go onto explain more about classes. I downloaded the Problem Set 6 zip file from https://www.udacity.com/wiki/cs046/code and navigated to the Polygon Project folder. In there, I opened the BlueJay project file and could see all the other classes available for use in my Polygon class.
Once I had initialised a Line in my Polygon draw method, the connection between the Polygon class & the Line class appeared (HOORAY).
You can open the Line class to see what its constructors & methods are. Obviously the Line class is working in with a few other classes to actually be able to draw the line, but we can't see any of this in the Udacity IDE and the question doesn't really tell us either..
Nonetheless, I have added my code, that worked in the Udacity IDE to get the correct output.
I see you have used a distance method on the Point class. I don't think this exists.. Hence the garbage in the middle of my code. I probably could have condensed this somehow, but I was just happy to get the right outputs.
public class Polygon
{
private ArrayList<Point> shape; //instance variable
public Polygon() //constructs a new ArrayList of points called shape
{
shape = new ArrayList<Point>();
}
public void add(Point point) //takes in a Point and adds it to the ArrayList "shape"
{
shape.add(point);
}
public double perimeter()
{
double total = 0;
if (shape.size() > 2) //a polygon must have more than 2 sides
{
for (int i = 0; i < shape.size() - 1; i++) //for every point in the list, except for the last
{
double x1 = shape.get(i).getX();
double y1 = shape.get(i).getY();
double x2 = shape.get(i + 1).getX();
double y2 = shape.get(i + 1).getY();
double dist = Math.sqrt(Math.abs(Math.pow((x2 - x1), 2) //get the distance between the point
+ Math.pow((y2 - y1), 2))); //and the following point
total = total + dist; //add this distance to the total
}
double firstX = shape.get(0).getX();
double firstY = shape.get(0).getY();
double lastX = shape.get(shape.size() - 1).getX();
double lastY = shape.get(shape.size() - 1).getY();
double finalDist = Math.sqrt(Math.abs(Math.pow((lastX - firstX), 2) //get the distance between
+ Math.pow((lastY - firstY), 2))); //the first & last points
total = total + finalDist; //add it to the total
}
return total;
}
public void draw()
{
for (int i = 0; i < shape.size() - 1; i++) //for every point in the list, except for the last
{
double x1 = shape.get(i).getX();
double y1 = shape.get(i).getY();
double x2 = shape.get(i + 1).getX();
double y2 = shape.get(i + 1).getY();
Line line = new Line(x1, y1, x2, y2); //create a new Line "line"
line.draw(); //draw the line
}
double firstX = shape.get(0).getX();
double firstY = shape.get(0).getY();
double lastX = shape.get(shape.size() - 1).getX();
double lastY = shape.get(shape.size() - 1).getY();
Line lastLine = new Line(lastX, lastY, firstX, firstY); //get the first & last points & create a line
lastLine.draw(); //draw this line too
}
}
Related
I am trying to get all positions in a radius from a 3 dimensional world(In this case the game Minecraft) this is the current code I use.
public static List<BlockPos> getBlocksInRadius(double radius) {
List<BlockPos> circleblocks = new ArrayList<>();
int centralx = mc.player.posX;
int centraly = mc.player.posY;
int centralz = mc.player.posZ;
for (int x = centralx - radius; x <= centralx + radius; x++) {
for (int z = centralz - radius; z <= centralz + radius; z++) {
for (int y = centraly - radius; y < centraly + radius; y++) {
double dist = mc.player.getDistance(x, y, z);
if (dist < radius) {
BlockPos l = new BlockPos(x, y, z);
circleblocks.add(l);
}
}
}
}
return circleblocks;
}
This method goes from the x coord farthest away and keeps coming closer to the player. I want it to iterate it by starting at central x,y,z and then increase distance from the player. This is to make it easier to find block x closest to player. Any help would be apreciated!
Depending on how large of a radius you have, you might try the static method BlockPos::getAllInBox. There doesn't seem to be any official documentation on it, but it looks like it takes two BlockPos parameters and returns an Iterable<BlockPos>. It finds all the blocks in a cube in between the two parameters, so you probably want to center it on the player.
Here's what I would do. This code hasn't been tested, and you might need to adapt it for all of the 1.14 and 1.13 changes, but the theory should be the same, with just name changes.
BlockPos playerPos = player.getPosition(); // Or some other method of getting a BlockPos of the player
positiveRadiusPosition = playerPos.add(radius, radius, radius); // Gets one corner of the cube in the positive X, Y, and Z direction
negativeRadiusPosition = playerPos.add(-1 * radius, -1 * radius, -1 * radius); // Gets the opposite corner
Iterable<BlockPos> cubeResult = BlockPos.getAllInBox(positiveRadiusPosition, negativeRadiusPosition);
for (BlockPos pos: cubeResult) {
// cubeResult will contain blocks that are outside of the sphere with the
// radius you want. If that's okay, cool! If that's not okay, you should
// check each pos' distance from the player. If it's outside of the radius,
// remove it from the list.
}
Now you need to figure out which block is closest. The method I would use would be to use a Comparator to sort the Iterable, which is copied into a List. For reference:
public static Iterator sortedIterator(Iterator it, Comparator comparator) {
List list = new ArrayList();
while (it.hasNext()) {
list.add(it.next());
}
Collections.sort(list, comparator);
return list.iterator();
}
In the Comparator, you should check the distance from the player to each block.
public static double getDistanceToEntity(Entity entity, BlockPos pos) {
double deltaX = entity.posX - pos.getX();
double deltaY = entity.posY - pos.getY();
double deltaZ = entity.posZ - pos.getZ();
return Math.sqrt((deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ));
}
Of course, this method doesn't actually start at the player and work outwards. It's just a cleaner and expanded version of your original method that should do what you want. If you are working with a very large radius, it's probably not a good idea to use this, as you'll have to work with the entire cube.
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;
}
Rotating Asteroids ( Polygons )
I am trying to rotate asteroids(polygons) so that they look nice. I am doing this through multiple mathematical equations. To start I give the individual asteroid a rotation velocity:
rotVel = ((Math.random()-0.5)*Math.PI/16);
Then I create the polygon shape,
this.shape = new Polygon();
Followed by generating the points,
for (j = 0; j < s; j++) {
theta = 2 * Math.PI / s * j;
r = MIN_ROCK_SIZE + (int) (Math.random() * (MAX_ROCK_SIZE - MIN_ROCK_SIZE));
x = (int) -Math.round(r * Math.sin(theta)) + asteroidData[0];
y = (int) Math.round(r * Math.cos(theta)) + asteroidData[1];
shape.addPoint(x, y);
}
Finally, in a loop a method is being called in which it attempts to move the polygon and its points down as well as rotating them. (I'm just pasting the rotating part as the other one is working)
for (int i = 0; i < shape.npoints; i++) {
// Subtract asteroid's x and y position
double x = shape.xpoints[i] - asteroidData[0];
double y = shape.ypoints[i] - asteroidData[1];
double temp_x = ((x * Math.cos(rotVel)) - (y * Math.sin(rotVel)));
double temp_y = ((x * Math.sin(rotVel)) + (y * Math.cos(rotVel)));
shape.xpoints[i] = (int) Math.round(temp_x + asteroidData[0]);
shape.ypoints[i] = (int) Math.round(temp_y + asteroidData[1]);
}
now, the problem is that when it prints to the screen the asteroids appear to 'warp' or rather the x and y positions on some of the polygon points 'float' off course.
I've noticed that when I make 'rotVel' be a whole number the problem is solved however the asteroid will rotate at mach speeds. So I've concluded that the problem has to be in the rounding but no matter what I do I can't seem to find a way to get it to work as the Polygon object requires an array of ints.
Does anyone know how to fix this?
Currently your asteroids rotate around (0 , 0) as far as i can see. Correct would be to rotate them around the center of the shape, which would be (n , m), where n is the average of all x-coordinates of the shape, and m is the average of all y-coordinates of the shape.
Your problem is definitely caused by rounding to int! The first improvement is to make all shape coordinates to be of type double. This will solve most of your unwanted 'effects'.
But even with double you might experience nasty rounding errors in case you do a lot of very small updates of the coordinates. The solution is simple: Just avoid iterative updates of the asteroid points. Every time, you update the coordinates based on the previous coordinates, the rounding error will get worse.
Instead, add a field for the rotation angle to the shape and increment it instead of the points themselves. Not until drawing the shape, you compute the final positions by applying the rotation to the points. Note that this will never change the points themselves.
You can extend this concept to other transformations (e.g. translation) too. What you get is some kind of local coordinate system for every shape/object. The points of the shape are defined in the local coordinate system. By moving and rotating this system, you can reposition the entire object anywhere in space.
public class Shape {
// rotation and position of the local coordinate system
private double rot, x, y;
// points of the shape in local coordinate system
private double[] xp, yp;
private int npoints;
// points of the shape in world coordinates
private int[][] wxp, wyp;
private boolean valid;
public void setRotation(double r) { this.rot = r; valid = false; }
public void setPosition(double x, double y) { this.x = x; this.y = y; valid = false; }
public void addPoint(double x, double y) {
// TODO: add point to xp, yp
valid = false;
}
public void draw(...) {
if (!valid) {
computeWorldCoordinates(wxp, wyp);
valid = true;
}
// TODO: draw shape at world coordaintes wxp and wyp
}
protected void computeWorldCoordinates(int[] xcoord, int[] ycoord) {
for (int i = 0; i < npoints; i++) {
double temp_x = xp[i] * Math.cos(rot) - yp[i] * Math.sin(rot);
double temp_y = xp[i] * Math.sin(rot) + yp[i] * Math.cos(rot);
xcoord[i] = (int) Math.round(x + temp_x);
ycoord[i] = (int) Math.round(y + temp_y);
}
}
}
This is my Lab class which contains a method called findNearest() which takes a single Point object as a parameter and an ArrayList of Points as a parameter and returns the nearest Point in the list to the single Point.
In my main method I created an ArrayList of 10 random Point objects. drawn on Points on the StdDraw canvas.
I want to connect the points closest to another point in the ArrayList but I don't know how...can anyone help me out?
import java.util.ArrayList;
public class Lab {
public static void main(String[] args){
//Create 10 random points and put them in a List
ArrayList<Point> thePoints = new ArrayList<Point>();
for(int i=0; i<10; i++){
Point p = new Point(600 * Math.random(), 600 * Math.random());
thePoints.add(p);
}
StdDraw.setCanvasSize(600,600);
StdDraw.setXscale(0.0 , 600.0);
StdDraw.setYscale(0.0 , 600.0);
//Draw the points in the List
for( Point p : thePoints){
p.draw();
}
//Draw lines to the nearestNeighbors
StdDraw.show();
}
public static Point findNearest(Point aPoint, ArrayList<Point> theList){
double minimumDistSoFar = Double.MAX_VALUE;
Point nearest = null;
for (Point p : theList) {
if (p.getMyX() == minimumDistSoFar && p.getMyY() == minimumDistSoFar) {
}
double pDistance = distance(p);
if (pDistance < minimumDistSoFar) {
minimumDistSoFar = pDistance;
nearest = p;
}
}
return nearest;
}
}
StdDraw has a line() method. Here's a link to the documentation: Documentation
This method takes four doubles, x and y of the start of the line, and x and y of the end of the line. You could draw a line beginning at one of the Point's x and y, and then set the x and y of the end of the line to the nearest Point's x and y.
I imagine you could do something like this:
for(Point p : thePoints)
{
Point p2 = findNearest(p, thePoints);
StdDraw.line(p.getX(), p.getY(), p2.getX(), p2.getY());
}
From my understanding this should draw a line from the point in the loop to the nearest point.
I am trying to figure out the proper way to call arrays from the area method, which are then supposed to calculate the area of the points given. Not sure what the proper way to select the specific x and y coordinates from each array is.
MyPolygon class
import java.util.ArrayList;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
/**
* A class that represents a geometric polygon. Methods are provided for adding
* a point to the polygon and for calculating the perimeter and area of the
* polygon.
*/
class MyPolygon {
// list of the points of the polygon
private ArrayList<Point2D.Double> points;
/**
* Constructs a polygon with no points in it.
*/
public MyPolygon() {
points = new ArrayList<Point2D.Double>();
}
/**
* Adds a point to the end of the list of points in the polygon.
*
* #param x
* The x coordinate of the point.
* #param y
* The y coordinate of the point.
*/
public void add(double x, double y) {
points.add(new Point2D.Double(x, y));
}
/**
* Calculates and returns the perimeter of the polygon.
*
* #return 0.0 if < 2 points in polygon, otherwise returns the sum of the
* lengths of the line segments.
*/
public double perimeter() {
if (points.size() < 2) {
return 0.0;
}
int i = 0;
double d = 0;
double total = points.get(0).distance(points.get(points.size() - 1));
while (i < points.size() - 1) {
Point2D.Double point1 = points.get(i);
// double x = point1.x;
// double y = point1.y;
Point2D.Double point2 = points.get(i + 1);
// double x1 = point2.x;
// double y1 = point2.y;
d = point1.distance(point2);
// d = Math.sqrt(Math.pow(x1 - x,2) + Math.pow(y1 - y, 2));
total = total + d;
i++;
}
return total;
}
/**
* Calculates and returns the area of the polygon.
*
* #return 0.0 if < 3 points in the polygon, otherwise returns the area of
* the polygon.
*/
public double area() {
int i = 0;
double a = 0;
double total = 0;
total = total + a;
if (points.size() < 3) {
return 0.0;
}
for (int m = 0; m < points.size(); m++) {
total = total + (points[m].x() * points[m + 1].y()) - (points[m].y() * points[m + 1].x());
}
return 0.5 * total;
}
}
Tester Class
class PolygonTester {
public static void main(String args[]) {
MyPolygon poly = new MyPolygon();
poly.add(1.0,1.0);
poly.add(3.0,1.0);
poly.add(1.0,3.0);
System.out.println(poly.perimeter());
System.out.println(poly.area());
}
}
Your headline is actually already the solution. You use points[m] which is array notation. But points ist not an array. It is a list. Use points.get(int i) instead, as you did in perimeter().
You're going to run out of bounds on the list. Your for loop continues while m < size(). However you access m+1 in your calculation. So if the list contains 5 elements and m = 4, (4 < 5) so keep looping, you will then access m + 1 which is 5. You don't have an index of 5 since these lists are 0 based.
Also the code is probably not compiling because you're using array syntax to access a list. You should say points.get(m)
The solution is quite simple, and is given away by your title (which I assume to be a compiler error.)
You are treating points as an array, which it is not. You access elements of an ArrayList slightly differently: you use points.get(m) instead of points[m]. If you make that change in area, it will work.
ArrayLists are not arrays. They are objects that are indexed with the get(int) method.
Wherever you have points[m], or something similar, replace it with points.get(m). The line would then become:
total = total + (points.get(m).x() * points.get(m + 1).y()) - (points.get(m).y() * points.get(m + 1).x());
That should clear up that issue, but you will still probably get an IndexOutOfBoundsException on the last iteration of the loop, because you will be trying to index m + 1 when m is the last index. You should change your code depending on how you want it to handle the last element.