Java: Triangle rotation - unsuccessful concept - java

What do I do wrong? I get incorrect results (coordinates).
A triangle (see the picture below: blue is the original triangle, lime is the rotated one: a clone. Edge A is a fixed point).
The classes I use:
A Point class:
public class Point {
private final double x;
private final double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
#Override
public String toString() {
return "[(" + x + ") (" + y + ")]";
}
}
An abstract Object2D class:
public abstract class Object2D {
Point[] point;
public Point getPoint(int i) {
return point[i];
}
public double getLowestX() {
return Arrays.asList(point).stream()
.mapToDouble(Point::getX)
.min().getAsDouble();
}
public double getHighestX() {
return Arrays.asList(point).stream()
.mapToDouble(Point::getX)
.max().getAsDouble();
}
public double getLowestY() {
return Arrays.asList(point).stream()
.mapToDouble(Point::getY)
.min().getAsDouble();
}
public double getHighestY() {
return Arrays.asList(point).stream()
.mapToDouble(Point::getY)
.max().getAsDouble();
}
public double getLength() {
return getSide(getLowestX(), getHighestX());
}
public double getHeight() {
return getSide(getLowestY(), getHighestY());
}
private double getSide(double v1, double v2) {
return (v1 < v2) ? (0 - v1) + v2 : (0 - v2) + v1;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Point pt : point) sb.append(pt).append("\n");
return sb.toString();
}
}
A Line class:
public class Line extends Object2D {
public Line(Point point0, Point point1) {
point = new Point[2];
point[0] = point0;
point[1] = point1;
}
public double getLineLength() {
return Math.sqrt(Math.pow(getLength(), 2) + Math.pow(getHeight(), 2));
}
}
My Triangle class:
public class Triangle extends Object2D {
public Triangle(Point point0, Point point1, Point point2) {
point = new Point[3];
point[0] = point0;
point[1] = point1;
point[2] = point2;
}
public static Triangle getRotatedTriangle(Triangle triangle) {
Point point0 = triangle.getPoint(0);
Point point1 = triangle.getPoint(1);
Point point2 = triangle.getPoint(2);
Line baseLine = new Line(point0, point1);
double rotationHeight = baseLine.getHeight();
double baseLength = baseLine.getLineLength();
double sinA = rotationHeight / baseLength;
double angle = Math.asin(sinA);
double cosA = Math.cos(angle);
point1 = new Point(
(point1.getX() * cosA - point1.getY() * sinA),
(point1.getX() * sinA + point1.getY() * cosA));
point2 = new Point(
(point2.getX() * cosA - point2.getY() * sinA),
(point2.getX() * sinA + point2.getY() * cosA));
return new Triangle(point0, point1, point2);
}
}
And, of course, my main class:
public class TestDrive {
public static void main(String[] args) {
Triangle triangle = new Triangle (
new Point(-6.5, -1.5),
new Point(2.5, 7.5),
new Point(6.5, -5.5)
);
System.out.println(triangle);
System.out.println(Triangle.getRotatedTriangle(triangle));
}
}

You made 2 mistakes in your code:
You are trying to rotate with the angle α when you should be rotating with the angle -α (since you are rotating clockwise).
Your multiplication matrix is incorrect: your code will perform a rotation around the origin of the XY plane instead of rotating around the point A. For the point (x, y) rotated by the rotation matrix R around the center (a, b), the correct formula for the new rotated point (x', y') would be (x', y') = R * (x - a, y - b) + (a, b).
This should be enough for you to correct your code. As reference, here's the solution I get for the rotated triangle:
[(-6.5) (-1.5)]
[(6.227922061357855) (-1.5000000000000009)]
[(-0.1360389693210724) (-13.520815280171309)]

Related

How to call non-static method from another class? [duplicate]

This question already has answers here:
Non-static method requires a target
(8 answers)
Closed 6 years ago.
I have 3 classes: Point, Polygon and ClientePolygon. Point creates an object, Point(double x, double y) with many nonstatic methods. Polygon creates an array of Point with non-static methods, i.e., write, move, and return the Point closest to the origin in the array. ClientePolygon executes Polygon. The problem is that when I run ClientePolygon it gives me Point class executed... and I want to run Polygon. Any suggestions? Thanks a lot.
ClientePolygon:
package k;
public class ClientePolygon {
public void main(String [] args){
Point origem = new Point (0,0);
Point [] vertices = new Point[4];
vertices[0] = new Point (1.0,1.0);
vertices[1] = new Point (1.0,5.0);
vertices[2] = new Point (2.0,5.0);
vertices[3] = new Point (2.0,1.0);
for (int i = 0; i < vertices.length; i++) {
vertices[i].translate(5.0,7.5);
}
}
}
Point:
package k;
public class Point {
private double x;
private double y;
public Point(double x, double y){
this.x = x;
this.y = y;
}
public double getX(){
return x;
}
public String toString(){
return "("+ this.x+", "+this.y+")";
}
public Point copy(){
Point copia = new Point(x, y);
return copia;
}
public static double distance(Point ponto1, Point ponto2){
double distX = ponto1.x + ponto2.x;
double distY = ponto1.y + ponto2.y;
return Math.sqrt(distX*distX + distY*distY);
}
public void translate(double dx, double dy){
double transX = this.x + dx;
double transY = this.y + dy;
System.out.println(toString()+" fica "+ transX +" e "+ transY);
}
public static void main(String[] args) {
Point ponto1 = new Point(2,1);
Point ponto2 = new Point(3,9);
System.out.println(ponto1.toString());
System.out.println(ponto2.toString());
System.out.println("A distancia entre os pontos eh: " +distance(ponto1, ponto2));
System.out.println("O ponto copiado eh: "+ponto2.copy());
ponto2.copy().translate(2, 3);
}
}
Polygon:
package k;
public class Polygon {
private Point [] vertices;
public Polygon(Point [] vertices){
this.vertices = vertices;
}
public String toString(){
return "Ponto 1 em: "+vertices;
}
public Point closestToOrigin(){
Point proximo = new Point(0, 0);
Point origem = new Point(0,0);
for (int i = 0; i < vertices.length; i++) {
double distancia = Point.distance(vertices[i], origem);
if(distancia<Point.distance(vertices[i-1], origem)){
proximo = vertices[i];
}
}
return proximo;
}
public void translate(double dx, double dy){
Point Trans = new Point(dx, dy);
System.out.println("Ponto 1 fica: "+vertices[0]+Trans+", Ponto 2 fica: "+vertices[1]+Trans+" e Ponto 3 fica: "+vertices[2]+Trans);
}
}
To call a nonstatic method you need to instantiate the other class by doing
Class object = new Class(parameters);
and then call the method on that object:
object.method();
You must instantiate the Polygon class before calling a nonstatic method:
Polygon poly = new Polygon(vertices);
Then you can do:
poly.translate(5.0,7.5);

Using methods I have created in a program - Java

Alright so I have created 2 methods called Point and LineSegment (they both work).
Point is this:
public class Point {
private double x;
private double y;
public Point(){
x=0;
y=0;
}
public Point(double a, double b){
x=a;
y=b;
}
public double getY(){
return y;
}
public double getX(){
return x;
}
public void setX(double newX){
x= newX;
}
public void sety(double newY){
y= newY;
}
public void setXY(double newX, double newY){
x = newX;
y = newY;
}
public String toString(){
return "("+x+" , "+y+")";
}
}
LineSegment is this :
public class LineSegment {
private Point A;
private Point B;
public LineSegment (){
A = new Point();
B = new Point();
}
public LineSegment (int x1, int y1, int x2, int y2){
A = new Point(x1, y1);
B = new Point(x2, y2);
}
public LineSegment(Point P, Point Q){
A = new Point(P.getX(), P.getY());
B = new Point(Q.getX(), Q.getY());
}
public double Length(){
double length = Math.sqrt(Math.pow( (B.getX() - A.getX()), 2) + Math.pow((B.getY() - A.getY()),2));
return length;
}
public double Slope(){
double slope = (B.getY() - A.getY() )/ (B.getX() - A.getX());
return slope;
}
public String toString(){
return "("+A.getX()+" , "+A.getY()+") + ("+B.getX()+" , "+B.getY()+") ";
}
}
As I said both of these codes work but now my task is to use Linesegment to create 2 line segments called AB and CD, and to output the slope of both of them, I am not sure how to do this, can anybody help?
They are called classes, not methods.
And you've already made class instances in your LineSegment class at
A = new Point();
B = new Point();
So now, in some other class,
public static void main(String[] args) {
Point A = new Point();
Point B = new Point();
Point C = new Point();
Point D = new Point();
LineSegment AB = new LineSegment(A, B);
LineSegment CD = new LineSegment(C, D);
// output the slope
System.out.println(AB.Slope());
}
Also, note that your Slope method will return a divide-by-zero error if you run this code as-is.
Create a class, regardless of its name, and put the main method.
The method called main is essentially your starting point, where your code will start running.
public static void main(String[]args){
LineSegment segment1 = new LineSegment(1,2,3,4);
LineSegment segment2 = new LineSegment(5,6,7,8);
System.out.println("The first slope is: " + segment1.Slope());
System.out.println("The second slope is: " + segment2.Slope());
}

Succinct class for rotational transforms (reducing redundancy)

I wrote this Java class for doing rotational transforms about the x,y,z axes.
public class Coord {
private double x,y,z;
public Coord(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Coord M(Coord[] M) {
return new Coord(
x*M[0].x + y*M[0].y + z*M[0].z,
x*M[1].x + y*M[1].y + z*M[1].z,
x*M[2].x + y*M[2].y + z*M[2].z);
}
public Coord xR(double theta) {
double s = Math.sin(theta);
double c = Math.cos(theta);
return M(new Coord[]{V(1,0,0), V(0,c,-s), V(0,s,c)});
}
public Coord yR(double theta) {
double s = Math.sin(theta);
double c = Math.cos(theta);
return M(new Coord[]{V(c,0,s), V(0,1,0), V(-s,0,c)});
}
public Coord zR(double theta) {
double s = Math.sin(theta);
double c = Math.cos(theta);
return M(new Coord[]{V(c,-s,0), V(s,c,0), V(0,0,1)});
}
public Coord V(double x, double y, double z) {
return new Coord(x,y,z);
}
}
It transforms a x,y,z coordinate, as given by the class Coord, to a new coord by the matrix multiplication M. It works OK, such as Coord c = new Coord(1,1,0).xR(0.1);, try System.out.printf("%f,%f,%f", c.x, c.y, c.z); will show a small rotation (theta=0.1 radians) about x, while keeping x constant.
Anyway, I want to know if there's any way of getting rid of all the Math.sin, Math.cos while still maintaining readability (preferably) - but just getting rid of them would be good!. They are annoying to look at, and, seem to be asking to be reduced somehow
As per Paul's comment, turns out to be pretty good
import static java.lang.Math.sin;
import static java.lang.Math.cos;
public class Coord {
private double x,y,z;
public Coord(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Coord M(Coord[] M) {
return new Coord(
x*M[0].x + y*M[0].y + z*M[0].z,
x*M[1].x + y*M[1].y + z*M[1].z,
x*M[2].x + y*M[2].y + z*M[2].z);
}
public Coord xR(double t) {
return M(new Coord[]{V(1,0,0), V(0,cos(t),-sin(t)), V(0,sin(t),cos(t))});
}
public Coord yR(double t) {
return M(new Coord[]{V(cos(t),0,sin(t)), V(0,1,0), V(-sin(t),0,cos(t))});
}
public Coord zR(double t) {
return M(new Coord[]{V(cos(t),-sin(t),0), V(sin(t),cos(t),0), V(0,0,1)});
}
public Coord V(double x, double y, double z) {
return new Coord(x,y,z);
}
}
Answering my own Q .. happy to know of other ways, looks pretty syntax bare now though .... I think I can live with this

How to project 3D on a 2D plane?

I created a simple Application which is meant to display, in 2D, dots which are hypothetically on a 3D plane (these points are of type Vector, written below). The class uses the XYZ Coordinates of the Camera and the XYZ Coordinates of the Vector, and uses that information to quickly translate the Vector XYZ Coordinates into XY Coordinates.
The only class needed in this question is the Vector class given below. All other classes used are omitted because they essentially fire mouse movements and redraw the frame.
--My concern is that, as the camera moves, the Vector points jump around as if the formula that I'm using is totally unreliable. Are these formulas (found under Perspective Projection) completely incorrect? The use of those formulas can be found within my set2D method. Am I doing something completely wrong, skipping steps, or perhaps have I translated the formula into code incorrectly?
Thanks!
import java.awt.Color;
import java.awt.Graphics;
public class Vector
{
private int cX, cY, cZ; //Camera Coordinates
private int aX, aY, aZ; //Object Coordinates
private double bX, bY; //3D to 2D Plane Coordinates
public Vector(int aX, int aY, int aZ, int cX, int cY, int cZ)
{
this.aX = aX;
this.aY = aY;
this.aZ = aZ;
this.cX = cX;
this.cY = cY;
this.cY = cZ;
set2D();
}
//SETS
public void setCameraX(int cX)
{
this.cX = cX;
set2D();
}
public void setCameraY(int cY)
{
this.cY = cY;
set2D();
}
public void setCameraZ(int cZ)
{
this.cZ = cZ;
set2D();
}
public void setCameraXYZ(int cX, int cY, int cZ)
{
setCameraX(cX);
setCameraY(cY);
setCameraZ(cZ);
}
public void setObjX(int x)
{
this.aX = x;
}
public void setObjY(int y)
{
this.aY = y;
}
public void setObjZ(int z)
{
this.aZ = z;
}
public void setObjXYZ(int x, int y, int z)
{
this.aX = x;
this.aY = y;
this.aZ = z;
}
public void set2D()
{
//---
//the viewer's position relative to the display surface which goes through point C representing the camera.
double eX = aX - cX;
double eY = aY - cY;
double eZ = aZ - cZ;
//----
double cosX = Math.cos(eX);
double cosY = Math.cos(eY);
double cosZ = Math.cos(eZ);
double sinX = Math.sin(eX);
double sinY = Math.sin(eY);
double sinZ = Math.sin(eZ);
//---
//The position of point A with respect to a coordinate system defined by the camera, with origin in C and rotated by Theta with respect to the initial coordinate system.
double dX = ((cosY*sinZ*eY) + (cosY*cosZ*eX)) - (sinY * eZ);
double dY = ((sinX*cosY*eZ) + (sinX*sinY*sinZ*eY) + (sinX*sinY*cosZ*eX)) + ((cosX*cosZ*eY) - (cosX*sinZ*eX));
double dZ = ((cosX*cosY*eZ) + (cosX*sinY*sinZ*eY) + (cosX*sinY*cosZ*eX)) - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX));
//---
//---
//The 2D projection coordinates of the 3D object
bX = (int)(((eZ / dZ) * dX) - eX);
bY = (int)(((eZ / dZ) * dY) - eY);
//---
System.out.println(bX + " " + bY);
}
//GETS
public int getCameraX()
{
return cX;
}
public int getCameraY()
{
return cY;
}
public int getCameraZ()
{
return cZ;
}
public int getObjX()
{
return aX;
}
public int getObjY()
{
return aY;
}
public int getObjZ()
{
return aY;
}
public int get2DX()
{
return (int)bX;
}
public int get2DY()
{
return (int)bY;
}
//DRAW
public void draw(Graphics g)
{
g.setColor(Color.red);
g.fillOval((int)bX, (int)bY, 3, 3);
}
//TO STRING
public String toString()
{
return (aX + " " + aY + " " + aZ);
}
}
The following line of your code does not match with the formula you are using:
double dZ = ((cosX*cosY*eZ) + (cosX*sinY*sinZ*eY) + (cosX*sinY*cosZ*eX)) - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX));
Notice the part - ((-sinX*cosZ*eY) - (-sinX*sinZ*eX))
This should be - ((sinX*cosZ*eY) - (sinX*sinZ*eX))
Since if you take sinX and multiply it, the -ve sign stays outside. If however you multiple -sinX then the sign outside the brackets should become +ve.

Trouble finding area of triangle

I have a method that gets the area of a triangle, however it is returning 0.0.
public double getArea() {
//Find the length of sides
double side1 = p1.findLength(p2);
double side2 = p2.findLength(p3);
double side3 = p3.findLength(p1);
//Get area
double s = (side1 + side2 + side3) / 2;
return Math.sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
My Point class with findLength(). This function works as intended in my testing:
public double findLength(Point another) {
return Math.sqrt(((another.getX() - this.getX()) * (another.getX() - this.getX()) )+
((another.getY() - this.getY()) * (another.getY() - this.getY())));
}
I can't seem to figure out why it isn't working.
Entire Point class:
/**
* Created by wilson on 9/8/2014.
*/
import java.math.*;
public class Point {
private double x, y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double findLength(Point another) {
return Math.sqrt(((another.getX() - this.getX()) * (another.getX() - this.getX()) )+
((another.getY() - this.getY()) * (another.getY() - this.getY())));
}
}
My Test Program:
Point p1 = new Point(0,0);
Point p2 = new Point(3,3);
Point p3 = new Point(-3,-3);
Triangle2D t1 = new Triangle2D(p1, p2, p3);
System.out.println("Area of triangle: " + t1.getArea());
The "triangle" you tested:
Point p1 = new Point(0,0);
Point p2 = new Point(3,3);
Point p3 = new Point(-3,-3);
actually consists of three points all on the same line (the line x = y). Therefore, 0 is the correct answer. As far as I can tell, the code is correct.
Side note: I recommend using Math.hypot, which computes sqrt(x2 + y2) in the findLength function. Besides making findLength easier to read, it has the advantage that it won't overflow if x or y is so large that x2 or y2 won't fit in a floating-point number. (Not that it's likely you'll run into that problem, but why not do things right?)

Categories