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
Related
I have the following code in Java
I am able to print the calculated values in printDistance method.
Output:
4.0
3.0
But I need the output in below format(Expected Output).Please help
3D Distance = 4.0
2D Distance = 3.0
public class Point2D {
double x;
double y;
public double getX() {
return x;
}
public double getY() {
return y;
}
public Point2D(double x, double y) {
this.x = x;
this.y = y;
}
public double dist2D(Point2D p) {
x = (int) Math.ceil(Math.sqrt(Math.pow((p.getX() - x), 2) + Math.pow((p.getY() - y), 2)));
return x;
}
public static void printDistance(double d) {
System.out.println(d);
}
static public void main(String args[]) {
Point3D obj1 = new Point3D(1.0, 2.0, 3.0);
Point3D obj2 = new Point3D(3.0, 4.0,5.0);
printDistance(obj1.dist3D(obj2));
printDistance(obj1.dist2D(obj2));
}
}
class Point3D extends Point2D {
double z;
public double getZ() {
return z;
}
public Point3D(double x, double y, double z) {
super(x, y);
this.z = z;
}
public double dist3D(Point3D p) {
return (int) Math.ceil(Math.sqrt(Math.pow((p.getX() - x), 2) + Math.pow((p.getY() - y), 2) + +Math.pow((p.getZ() - z), 2)));
}
}
You can do it as follows:
public class Point2D {
double x;
double y;
public double getX() {
return x;
}
public double getY() {
return y;
}
public Point2D(double x, double y) {
this.x = x;
this.y = y;
}
public String dist2D(Point2D p) {
x = (int) Math.ceil(Math.sqrt(Math.pow((p.getX() - x), 2) + Math.pow((p.getY() - y), 2)));
return "2D Distance = "+x;
}
public static void printDistance(String d) {
System.out.println(d);
}
static public void main(String args[]) {
Point3D obj1 = new Point3D(1.0, 2.0, 3.0);
Point3D obj2 = new Point3D(3.0, 4.0,5.0);
printDistance(obj1.dist3D(obj2));
printDistance(obj1.dist2D(obj2));
}
}
class Point3D extends Point2D {
double z;
public double getZ() {
return z;
}
public Point3D(double x, double y, double z) {
super(x, y);
this.z = z;
}
public String dist3D(Point3D p) {
return "3D Distance = "+ Math.ceil(Math.sqrt(Math.pow((p.getX() - x), 2) + Math.pow((p.getY() - y), 2) + +Math.pow((p.getZ() - z), 2)));
}
}
Output:
3D Distance = 4.0
2D Distance = 3.0
I'm stuck on this question for a couple of days now and would really like to get some help.
I am given a 2 dimensional point in the range of (0-1 not including 1), such as (0.5,0.2), and N other points (also in the range of 0-1).
The first part of the question is to implement the "dumb" algorithm, which when given a certain point will find the point with the shortest distance from it, which has a complexity of O(N).
The part I'm stuck at, requires to build a Matrix K on K, where each "cell" will contain the points that belong to that cell. Once done, when given the original point I will need to search for the point with the shortest distance to it only in some of the cells and not the entire Matrix, which should result better complexity.
My original thought is to devide the points so that each block will have an arraylist of points that belong to him, and then to somehow go through the main block(the one that the original point belongs to) and continue by going through it's neighbors, however implementing it hasn't been very successful.
I would highly appreciate any help/ advice.
Below is what I currently have:
public class Point {
private double x;
private double y;
private Block b;
public Point(double x, double y)
{
this.x=x;
this.y=y;
}
public Point(double x, double y, Block b) //consrtuctor for complex case
{
this.x=x;
this.y=y;
b.points.add(this);
}
public double getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public double distance(Point p)
{
double res=0;
res = Math.sqrt(Math.pow(this.x-p.getX(),2)+Math.pow(this.y-p.getY(),2));
return res;
}
}
import java.util.ArrayList;
public class Block {
private int x;
private int y;
public ArrayList<Point> points;
public Block(int x, int y) {
points = new ArrayList<Point>();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
import java.util.Random;
public class ComplexCase {
private Block[][] blockMat;
public ComplexCase(int k, int n)
{
Random generator = new Random();
Point p1;
Block b1;
double x,y;
int bx1,by1;
int t;
t = 1/k;
blockMat = new Block[k][k];
for (int i =0;i<n;i++)
{
x = generator.nextDouble();
y = generator.nextDouble();
bx1 = (int) (x/t);
by1 = (int) (y/t);
b1 = new Block(bx1,by1);
p1 = new Point(x,y,b1);
}
}
public Block[][] getBlockMat() {
return blockMat;
}
public void setBlockMat(Block[][] blockMat) {
this.blockMat = blockMat;
}
}
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)]
It's been difficult to Google for a solution, because I'm not interested in the vector data strucutre. I'm interested in the phytsics vector. I'm trying to create a generic class to wrap any number type for a Vector. This is my original double vector:
public class Vector2D {
private double x, y;
Vector2D (double x, double y){
this.x = x;
this.y = y;
}
public static Vector2D random() {
return new Vector2D(Math.random() * 2 - 1, Math.random() * 2 - 1);
}
public double magnitude(){
return Math.sqrt(this.x * this.x + this.y * this.y);
}
public Vector2D add(Vector2D other) {
return new Vector2D(this.x + other.x, this.y + other.y);
}
//etc...
}
However, I'm coming across some dificulites in porting this to a generic class. This is what I have so far:
public class Vector2D<T extends Number> {
private T x, y;
Vector2D (T x, T y){
this.x = x;
this.y = y;
}
public static Vector2D random() {
return new Vector2D(Math.random() * 2 - 1, Math.random() * 2 - 1);
}
public T magnitude(){
//this gives an error: cannot cast from double to T
return (T)Math.sqrt(this.x.doubleValue() * this.x.doubleValue() + this.y.doubleValue() * this.y.doubleValue());
}
}
I'm stuck on magnitude and random. I'm really stumped. Any guidance as to how I can complete those methods?
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.