My last question involved getting the syntax right, this question is:
How should I best go about showing a 3D representation of a line between 2 points? I've calculated the slope, now I simply want to make a window appear and display a cube like this: http://www.wolframalpha.com/input/?i=slope+between+%282%2C6%2C1%29+and+%283%2C5%2C0%29
public static double calcSlope(Point p1, Point p2){
//math to calculate the slope
double slope1 = (p2.getY()- p1.getY())/(p2.getX()-p1.getX());
double angle1 = Math.atan(slope1);
double distance1 = (p2.getY()-p1.getY())/Math.sin(angle1);
System.out.println("distance: " + distance1);
double slopeFinal = 1/distance1;
return slopeFinal;
}
public static void main(String[]args){
double x1, x2, y1, y2, z1, z2;
x1 = 5;
x2 = 7.5;
y1 = 3.25;
y2 = 4;
z1 = 0;
z2 = 1;
Point point1 = new Point(x1, y1, z1);
//declaring new variables of class Point
Point point2 = new Point(x2, y2, z2);
//in Point y2 is = y, but y1 is also = y Point (x,y,z) serves as a placeholder where "x" is just
//a placeholder
double slope = calcSlope(point1, point2);
double angle = Math.atan(slope);
System.out.println("Your Slope is " + slope);
System.out.println("Angle of entry is " + angle);
}
Thats a BIG question, you're going to have to use some 3rd party library for 3D graphics as java doesn't natively support it*. I would suggest you look at jmonkey engine but thats just my personal preference: http://jmonkeyengine.com/.
*technically java3D does exist but it still doesn't come with java as standard and it is a largely abandoned project
Related
After looking at the answers provided in this question, I created the following method:
private int angleOf(float x1, float x2, float y1, float y2) {
final double deltaY = (y1 - y2);
final double deltaX = (x2 - x1);
final double result = Math.toDegrees(Math.atan2(deltaY, deltaX));
return (int) ((result < 0) ? (360d + result) : result);
}
by using the above I will get the angle of each line , then I draw the text to my canvas, as shown below:
int topLine = angleOf(this.mPoints[5].x, this.mPoints[4].x, this.mPoints[5].y, this.mPoints[4].y);
int bottomLine = angleOf(this.mPoints[5].x, this.mPoints[6].x, this.mPoints[5].y, this.mPoints[6].y);
canvas.drawText(String.valueOf(360 - bottomLine + topLine)+"°", this.mPoints[5].x - 80.0f, this.mPoints[5].y, this.mTextPaint);
The above works fine, here is a example of my result:
The problem I have is that the angle is measured from the x-axis and increasing anti-clockwise, as shown below:
When the bottom line or the top line "crosses" the 0° (parallel to the x-axis), I would then get an incorrect angle.
Here is another image to demonstrate this issue:
The angle between the blue lines are 90°, but instead I get 450°. This happens because of the calculation I used 360 - bottomLine + topLine.
Can someone please suggest a solution to this issue.
Thank you.
You can use like this,out put value is radian
coordinate point (0,0) other points (x1,y1) ,(x2,y2)
atan() = tan invers
private double angleOfRadian(float x1, float x2, float y1, float y2) {
return java.lang.Math.atan(y2/x2)-java.lang.Math.atan(y1/x1);
}
Use this method to calculate it properly:
private double angleOfDegrees(float x0, float y0, float x1, float y1) {
double angle2 = Math.atan2(y1,x1);
double angle1 = Math.atan2(y0,x0);
return Math.toDegrees(angle2 - angle1) + 360) % 360;
}
Is there a way I can test if a Rectangle object collides with a line? Thanks!
EDIT :
public boolean overlapsLineNodes(Vector2 point1, Vector2 point2) {
boolean collide = false;
MapObjects mapObjects = play.getWorld().level.getCurrentLevel().getLayers().get("collidable").getObjects();
Tools.shapeRenderer.setAutoShapeType(true);
Tools.shapeRenderer.setProjectionMatrix(play.getCamera().combined);
Tools.shapeRenderer.begin();
for (RectangleMapObject rectangleObject : mapObjects.getByType(RectangleMapObject.class)) {
rectangle.setX(rectangleObject.getRectangle().x * 1/64f);
rectangle.setY(rectangleObject.getRectangle().y * 1/64f);
rectangle.setWidth(rectangleObject.getRectangle().width * 1/64f);
rectangle.setHeight(rectangleObject.getRectangle().height * 1/64f);
float x1 = rectangle.x, y1 = rectangle.y + rectangle.height,
x2 = rectangle.x + rectangle.width, y2 = rectangle.y + rectangle.height,
x3 = rectangle.x + rectangle.width, y3 = rectangle.y,
x4 = rectangle.x, y4 = rectangle.y;
Vector2 start = point1, end = point2;
float[] floatArray = new float[]{x1, y1, x2, y2, x3, y3, x4, y4};
polygon.setVertices(floatArray);
if (Intersector.intersectLinePolygon(start, end, polygon)) {
Tools.shapeRenderer.setColor(Color.GREEN);
collide = true;
}
Tools.shapeRenderer.line(point1.x, point1.y, point2.x, point2.y);
Tools.shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
Tools.shapeRenderer.setColor(Color.WHITE);
}
I do this, but it seems not to give me correct results. I am rending all of the rectanglemapobjects in white, and if one collides with the line, then I render it in green. It randomly renders some in green and I cant figure out why.
The problem was that intersectLinePolygon is the wrong method! I should have been using intersectSegmentPolygon.
Compute the intersection of the line with the line defining one edge of the rectangle, determine the whether the intersection point lies between the endpoints of the edge. Repeat with the opposite edge. If you get "yes" to either, they intersect.
You do not need to test all 4 edges; just two opposite edges.
If rectangle edges are parallel to the axis ... [x1,y1]-[x2,y1]-[x2,y2]-[x1,y2] ... and your line in question is y = m*x + b, then this becomes simply:
ya = m*x1 + b;
yb = m*x2 + b;
collision = ((ya < y1) ^ (ya < y2)) || ((yb < y1) ^ (yb < y2));
Or, if you order "ya < yb", you can get more precise over whether just touching a corner is considered a collision:
collision = ((ya <= y1) && (y1 <= yb)) || ((ya <= y2) && (y2 <= yb));
Assuming that you know start and end point of your line and also vertices of rectangle (which you must know to be honest :) ) you can use Intersector's intersectLinePolygon() method just like
//definition of variables - of course you can keep your x... y... in float[] array
float x1 = 0, x2 = 0, x3 = 0, x4 = 0, y1 = 0, y2 = 0, y3 = 0, y4 = 0;
Vector2 start = null, end = null;
//...
//updateing vertices and line start/end points
//...
Intersector.intersectLinePolygon(start, end, new Polygon(new float[]{x1, y1, x2, y2, x3, y3, x4, y4}));
If you are using this in render() method it is not good to create new Polygon() instance every time - better keep one instance somewhere
Polygon p = new Polygon();
and then just update it with vertices just before collision checking
p.setVertices(...);
The following code is called every 50ms.
// Start point
private double x;
private double y;
private double z;
private double y1;
#Override
public void run() {
double x1 = Math.cos(y1);
double z1 = Math.sin(y1);
double y2 = 4D - y1;
double x2 = Math.sin(y2);
double z2 = Math.cos(y2);
// First new point
double pX1 = x + x1;
double pY1 = y + y1;
double pZ1 = z + z1;
// Second new point
double pX2 = x + x2;
double pY2 = y + y2;
double pZ2 = z + z2;
if (y1 > 4D) {
y1 = 0D;
} else {
y1 = y1 + 0.1D;
}
}
Here is the output in a game. It generates two helices.
I cannot control more than the radius.
I am looking for code I can easily customize to fit my preferences.
How do I control the following aspects?
How fast the helix rises.
Where the helix begins.
helix is circular shape with 'linear' movement of the plane
you use plane xz as helix base and y axis as height
so you need:
r - radius
d - distance between two screws (the y movement after full circle)
t - parameter <0,1> determining the position on helix
h0,h1 - start end height of helix (y-axis)
a0 - angular start position [rad]
Now how to get the point on helix as function of parameter these parameters
aa=fabs(h1-h0)*2.0*M_PI/d; // angular speed coefficient
// if you need opposite angular direction then add aa=-aa;
x=r*cos(a0+aa*t);
z=r*sin(a0+aa*t);
y=h0+((h1-h0)*t);
aa can be precomputed once
now if t=0.0 then you get the start point of helix
if t=1.0 then you got the endpoint of helix
so speed is just how much you add to t during animation per timer cycle
d controls number of screw loops
h1-h0 is the helix height
code is in C++ (sorry I am not a JAVA coder)
One part of the helix begins at:
(x, y, z) = (1.0, 0.0, 0.0)
And the other at:
(x, y, z) = (-0.8, 4.0, -0.7)
And the particle rises at a rate of 0.1 (from y1 = y1 + 0.1D).
So, to control how fast the particles rise, just change this value.
To control where the helix begins you need to change the angle. For example, add some value to the sines and cosines. Like this:
Math.cos(y1 + dy);
To make more rotations before restarting from the ground you can multiply the angle. Make it twice as fast:
Math.cos(2 * y1);
Helix is circular shape with progressive Y value.
// Start point
private double x;
private double y;
private double z;
private double degree;
private double rY;
#Override
public void run() {
// We use the same formula that is used to find a point of a circumference
double rX = Math.cos(degree);
double rZ = Math.sin(degree);
// New point
double pX = x + rX;
double pY = y + rY;
double pZ = z + rZ;
if (degree > 2D * Math.PI) {
degree = 0D;
} else {
degree = degree + 0.2D;
}
if (pY > 2D) {
pY = 0D;
} else {
pY = pY + 0.02D;
}
}
I understand the concept of overloading and I'd like to think I have done it succesfully in this program; it runs fine but the output is not correct.
The program is supposed to calculate the area of a circle from two points, one being the radius and the other being a random point on the outside of the circle. The two points are given by the user, and each point consists of two numbers. So point one is x1, x2, while point two is y1, y2.
I did a test run by inputting the numbers 1, 2, 3, and 4, which should give me an answer of 3.1458....(pi). However, it gives me 25.132741228718352.
Any help on figuring out what is giving me this weird output would be much appreciated.
Here is the code
import java.util.Scanner;
public class AreaCircle {
static Scanner input = new Scanner(System.in);
public static double getDistance(double x1, double y1,
double x2, double y2) {
double dx = x2 - x1;
double dy = y2 - y1;
double distanceSquared = dx * dx + dy * dy;
double radius = Math.sqrt(distanceSquared);
return radius;
}
public static double areaCircle (double radius){
double area = (double)Math.PI * (radius * radius);
return area;
}
public static double areaCircle (double x1, double x2,
double y1, double y2) {
double radius = getDistance(x1, x2, y1, y2);
double area = areaCircle (radius);
return area;
}
public static void main(String[] args) {
System.out.print("Please input two points, with the first being \n"
+ "the middle of the circle and the other being \n"
+ "a point on the outside of the circle. These two points will \n"
+ "be used to find the area of your circle. \n\n"
+ "Input the first point here: ");
double x1 = input.nextDouble();
System.out.print("Input the second point here: ");
double x2 = input.nextDouble();
System.out.print("Input the third point here: ");
double y1 = input.nextDouble();
System.out.print("Input the fourth point here: ");
double y2 = input.nextDouble();
double result = areaCircle(x1, x2, y1, y2);
System.out.println("Your result is: " + result);
}
}
You're actually calculating the distance between (1, 2) and (3,4), since you've switched x2 with y1 in distance (compare it with the area function -- you'll see what I mean).
The distance between (1,2) and (3,4) is sqrt 8, when you substitute that into the formula, it gives an area of 8 * pi ~= 25.
So I finished up a program that recursively draws lines which takes an argument "n" to define the depth of the recursion. I have 2 functions, one which draws the relatively left line and another which draws the relatively right one. I tested it ant it seems to work for the first 4 levels, but then either the lines become too small to accurately represent or there's something wrong with my code because the breaks between the lines seem to become arbitrary. Was hoping somebody could test my code and see if they could find what the problem is.
The following image is of depth 10.
EDIT: fixed a part of code, still need help though
public class Art
{
//draws the relatively left line
public static void drawLeftLine(double x0, double y0, double x1, double y1)
{
//define new x coordinate for line
//double x2 = (1/3.0)*(x1 - x0);
//color of line
StdDraw.setPenColor(StdDraw.BLUE);
//draw line by adding new x coord to original
StdDraw.line(x0, y0, x1, y1);
}
//draw relatively right line
public static void drawRightLine(double x0, double y0, double x1, double y1)
{
//define new x coord for line
//double x2 = (2/3.0)*(x1 - x0);
//color of line
StdDraw.setPenColor(StdDraw.BLUE);
//draw line by adding new x coord to original
StdDraw.line(x0, y0, x1, y1);
}
public static void cantor(int n, double x0, double y0, double x1, double y1)
{
if (n == 0)
return;
drawLeftLine(x0, y0, x1, y1);
drawRightLine(x0, y0, x1, y1);
y0 = y0 - 0.1;
y1 = y1 - 0.1;
cantor(n-1, x0, y0, x0 + ((x1 - x0))/3.0, y1); //left
cantor(n-1, (2.0/ 3) * (x1 - x0) + x0, y0, x1, y1); //right
}
public static void main(String[] args)
{
//change n into integer (depth)
int n = Integer.parseInt(args[0]);
//specify inital values for line
double x0 = 0;
double y0 = 0.9;
double x1 = 0.9;
double y1 = 0.9;
//recursive function cantor
cantor(n, x0, y0, x1, y1);
}
}
I think that the drawing looks incorrect because the of the fact that all of the nice double values are being approximated with discrete pixels causing unwanted overlap between the line segments (see EDIT at the bottom). Some comments about your code however :
1) You don't need the drawLeftLine and drawRightLine methods since currently they are drawing exactly the same thing. Since at each step you are calling cantor twice (once for each side of the deleted inner third), you have one call to cantor for each line segment that has to be drawn. As such I would put all of the drawing directly into the cantor method.
2) Since y0 and y1 are both always the same, I would reduce them to just a single y variable.
3) I would simplify the math for computing the new x0 and x1 values down to
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
4) Instead of decrementing the y value by 0.1 every time, you should have a global variable that decides the amount by which this should be decremented (otherwise if you try n > 10 things will break). This value can just be set to 1.0 / n.
5) You don't need to set the color of the pen every time you paint. You can set it just once in the main method.
6) StdDraw already sets a border around the picture you are drawing so there is no need to start your coordinates from 0.9 - you can use 1 instead.
Following these suggestions the code would look like this :
private static double yIncrement;
public static void cantor(int n, double x0, double x1, double y) {
if (n == 0)
return;
StdDraw.line(x0, y, x1, y);
y = y - yIncrement;
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
}
public static void main(String[] args) {
//change n into integer (depth)
int n = Integer.parseInt(args[0]);
// specify inital values for line
double x0 = 0;
double x1 = 1;
double y = 1;
yIncrement = 1.0 / n;
StdDraw.setPenColor(Color.BLUE);
// recursive function cantor
cantor(n, x0, x1, y);
}
EDIT : Playing around with the StdDraw canvas size, canvas scaling settings, and line segment endpoint rounding mode you can get a slightly better picture (the code below produces a picture that looks mostly correct down to the 8th level)
private static double yIncrement;
public static void cantor(int n, double x0, double x1, double y) {
if (n == 0)
return;
x0 = Math.ceil(x0);
x1 = Math.floor(x1);
StdDraw.line(x0, y, x1, y);
y = y - yIncrement;
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
}
public static void main(String[] args) {
// change n into integer (depth)
int n = Integer.parseInt(args[0]);
int width = 1920;
int height = 1080;
StdDraw.setCanvasSize(width, height);
// specify inital values for line
double x0 = 0;
double x1 = width;
double y = 1;
yIncrement = 1.0 / n;
StdDraw.setPenColor(Color.BLUE);
StdDraw.setXscale(0, width);
// recursive function cantor
cantor(n, x0, x1, y);
}
To display everything down to the tenth level with absolute correctness you would need a width of 3^9 pixels (19K pixels). For level 9 that's 3^8 = 6K. For level 8 that's 3^7 = 2k, which is why it looks almost correct with 1.9K pixel width and integer rounding.