Calculating the Angle Between Two Lines Without Having to Calculate the Slope (Java)

Calculating the angle between a line and the x-axis

Assumptions: x is the horizontal axis, and increases when moving from left to right.
y is the vertical axis, and increases from bottom to top. (touch_x, touch_y) is the
point selected by the user. (center_x, center_y) is the point at the center of the
screen. theta is measured counter-clockwise from the +x axis. Then:

delta_x = touch_x - center_x
delta_y = touch_y - center_y
theta_radians = atan2(delta_y, delta_x)

Edit: you mentioned in a comment that y increases from top to bottom. In that
case,

delta_y = center_y - touch_y

But it would be more correct to describe this as expressing (touch_x, touch_y)
in polar coordinates relative to (center_x, center_y). As ChrisF mentioned,
the idea of taking an "angle between two points" is not well defined.

How to compute angle between two intersecting lines by having latitude/longitude points in Java?

You want to get angle between two bearings.

Bearing at the Earth might be calculated using formula from latlong page

Formula:    θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )

where φ1,λ1 is the start point, φ2,λ2 the end point (Δλ is the difference in longitude)

JavaScript: (all angles in radians)

var y = Math.sin(λ2-λ1) * Math.cos(φ2);
var x = Math.cos(φ1)*Math.sin(φ2) - Math.sin(φ1)*Math.cos(φ2)*Math.cos(λ2-λ1);
var brng = Math.atan2(y, x).toDegrees();

After finding bearings from P3 to P1 and from P3 to P2 (note that order is significant - P3P1 and P1P3 give different results) calculate difference.

Java: Calculating the angle between two points in degrees

you could add the following:

public float getAngle(Point target) {
float angle = (float) Math.toDegrees(Math.atan2(target.y - y, target.x - x));

if(angle < 0){
angle += 360;
}

return angle;
}

by the way, why do you want to not use a double here?

Calculate angle between two lines (which are represent human arm) using Kinect data set in Java

Thank you all for your help.
Finally I found the mistake in my java code. I use System.out.println("3D angle: "+Math.acos(cosTheata)); to print the angle between two vectors in 3D space. When i read the documentation of acos() method, it says this method returns the angle in radian . In 2D plane result I used Math.toDegrees() method to convert the angles into degrees. So all my 3D coordinates angle values are in radian.

Finding angle of a line between two revolving points in two orbits, from one pont to other and not viceversa in JavaFX

You essentially have a vector from Earth to Jupiter and you want to find the angle (i.e. direction) of this vector. You also want the angle measured counterclockwise from the positive x-axis. What that means is you can measure the same angle using two vectors—your vector and the unit vector in the positive x direction. This is important because it can simplify the implementation since:

  1. JavaFX has the Point2D class which can represent vectors and provides convenient methods (e.g. angle).
  2. The angle between two vectors uses inverse cosine. That will give us a value between 0 and 180 degrees which I personally find easier to work with than inverse tangent's range of -90 to 90 degrees.

For example, if you have two points then you can calculate the angle between the implicit vector and the positive x-axis using the following:

/**
* Computes the angle (in degrees) of the vector from {@code p1} to {@code p2}. The angle
* will be in the range {@code 0} (inclusive) to {@code 360} (exclusive) as measured
* counterclockwise from the positive x-axis.
*
* @param p1 the start point of the vector
* @param p2 the end point of the vector
* @return the angle, in degrees, of the vector from {@code p1} to {@code p2} measured
* counterclockwise from the positive x-axis
*/
public static double computeAngleOfVector(Point2D p1, Point2D p2) {
Point2D vector = new Point2D(p2.getX() - p1.getX(), p2.getY() - p1.getY());
double angle = vector.angle(1.0, 0.0);
if (vector.getY() > 0) {
// vector pointing downwards and thus is in the 3rd or 4th quadrant
return 360.0 - angle;
}
// vector pointing upwards and thus is in the 1st or 2nd quadrant
return angle;
}

Note the reason I use vector.getY() > 0 rather than vector.getY() < 0 is because JavaFX, like most(?) GUI frameworks, has the positive y direction pointing down the screen. Depending on how you represent the coordinate system in your model you may have to modify the code slightly.


Here's an application demonstrating the above in a way I believe matches what you want:

import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.value.ObservableDoubleValue;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

private static final double SCENE_WIDTH = 1000;
private static final double SCENE_HEIGHT = 700;

@Override
public void start(Stage primaryStage) {
Circle sun = createCelestialBody(50, Color.YELLOW);

Circle earth = createCelestialBody(20, Color.BLUE);
Circle earthOrbitIndicator = createOrbitIndicator(150);

Circle jupiter = createCelestialBody(35, Color.BROWN);
Circle jupiterOrbitIndicator = createOrbitIndicator(300);

Line earthJupiterVector = createBodyToBodyVector(earth, jupiter);
DoubleBinding angleObservable = createAngleBinding(earthJupiterVector);
Line xAxisIndicator = createXAxisIndicator(earth);
Arc angleIndicator = createAngleIndicator(earth, angleObservable);

Pane root =
new Pane(
createAngleLabel(angleObservable),
earthOrbitIndicator,
jupiterOrbitIndicator,
sun,
earth,
jupiter,
earthJupiterVector,
xAxisIndicator,
angleIndicator);
primaryStage.setScene(new Scene(root, SCENE_WIDTH, SCENE_HEIGHT));
primaryStage.setTitle("Earth-Jupiter Vector Angle");
primaryStage.setResizable(false);
primaryStage.show();

animateOrbit(Duration.seconds(7), earth, earthOrbitIndicator.getRadius());
animateOrbit(Duration.seconds(16), jupiter, jupiterOrbitIndicator.getRadius());
}

private Label createAngleLabel(ObservableDoubleValue angleObservable) {
Label label = new Label();
label.setPadding(new Insets(10));
label.setUnderline(true);
label.setFont(Font.font("Monospaced", FontWeight.BOLD, 18));
label
.textProperty()
.bind(
Bindings.createStringBinding(
() -> String.format("Angle: %06.2f", angleObservable.get()), angleObservable));
return label;
}

private Circle createCelestialBody(double radius, Color fill) {
Circle body = new Circle(radius, fill);
body.setCenterX(SCENE_WIDTH / 2);
body.setCenterY(SCENE_HEIGHT / 2);
return body;
}

private Circle createOrbitIndicator(double radius) {
Circle indicator = new Circle(radius, Color.TRANSPARENT);
indicator.setStroke(Color.DARKGRAY);
indicator.getStrokeDashArray().add(5.0);
indicator.setCenterX(SCENE_WIDTH / 2);
indicator.setCenterY(SCENE_HEIGHT / 2);
return indicator;
}

private void animateOrbit(Duration duration, Circle celestialBody, double orbitRadius) {
Circle path = new Circle(SCENE_WIDTH / 2, SCENE_HEIGHT / 2, orbitRadius);
PathTransition animation = new PathTransition(duration, path, celestialBody);
animation.setCycleCount(Animation.INDEFINITE);
animation.setInterpolator(Interpolator.LINEAR);
animation.playFromStart();
}

private Line createBodyToBodyVector(Circle firstBody, Circle secondBody) {
Line vectorLine = new Line();
vectorLine.setStroke(Color.BLACK);
vectorLine.setStrokeWidth(2);
vectorLine.getStrokeDashArray().add(5.0);
vectorLine.startXProperty().bind(centerXInParentOf(firstBody));
vectorLine.startYProperty().bind(centerYInParentOf(firstBody));
vectorLine.endXProperty().bind(centerXInParentOf(secondBody));
vectorLine.endYProperty().bind(centerYInParentOf(secondBody));
return vectorLine;
}

private Line createXAxisIndicator(Circle anchor) {
Line xAxisIndicator = new Line();
xAxisIndicator.setStroke(Color.GREEN);
xAxisIndicator.setStrokeWidth(2);
xAxisIndicator.startXProperty().bind(centerXInParentOf(anchor));
xAxisIndicator.startYProperty().bind(centerYInParentOf(anchor));
xAxisIndicator.endXProperty().bind(xAxisIndicator.startXProperty().add(75));
xAxisIndicator.endYProperty().bind(xAxisIndicator.startYProperty());
return xAxisIndicator;
}

private Arc createAngleIndicator(Circle anchor, ObservableDoubleValue angleObservable) {
Arc arc = new Arc();
arc.setFill(Color.TRANSPARENT);
arc.setStroke(Color.RED);
arc.setStrokeWidth(2);
arc.getStrokeDashArray().add(5.0);
arc.centerXProperty().bind(centerXInParentOf(anchor));
arc.centerYProperty().bind(centerYInParentOf(anchor));
arc.setRadiusX(50);
arc.setRadiusY(50);
arc.setStartAngle(0);
arc.lengthProperty().bind(angleObservable);
return arc;
}

// NOTE: getCenterX() and getCenterY() were added in JavaFX 11. The calculations
// are simple, however. It's just (minX + maxX) / 2 and similar for y.

private DoubleBinding centerXInParentOf(Node node) {
return Bindings.createDoubleBinding(
() -> node.getBoundsInParent().getCenterX(), node.boundsInParentProperty());
}

private DoubleBinding centerYInParentOf(Node node) {
return Bindings.createDoubleBinding(
() -> node.getBoundsInParent().getCenterY(), node.boundsInParentProperty());
}

private DoubleBinding createAngleBinding(Line line) {
return Bindings.createDoubleBinding(
() -> {
Point2D vector =
new Point2D(line.getEndX() - line.getStartX(), line.getEndY() - line.getStartY());
double angle = vector.angle(1, 0);
if (vector.getY() > 0) {
return 360 - angle;
}
return angle;
},
line.startXProperty(),
line.endXProperty(),
line.startYProperty(),
line.endYProperty());
}
}

And here's what the example looks like:

GIF of demo application

How to calculate slope of line if lines are perpendicular?

The explicit form of a line equation, y = mx + p does not allow to represent verticals, as the slope is infinite.

For your purposes, you can use the implicit form, ax + by + c = 0, which does not have this problem. An orthogonal line can be given the equation bx - ay + d = 0.



Related Topics



Leave a reply



Submit