Re-using getX() getY() in a mouseclick-event handler - java

This is a long question. I've tried to make it more concise but I think you need all the info to assist.
Here's a summary:
I'm trying to capture consecutive clicks as endpoints. I'll draw line2D objects between these points. I have a listener that sends x and y values from click events to a helper class. I'll never have more than two points, so the helper class only has firstPoint and secondPoint members. I get the clicks and send the co-ordinates to the helper class using evt.getX() and evt.getY(). The helper creates the points, but firstPoint ends up with the same co-ords as secondPoint. My detail on what's going on can be found below the code blocks.
Here's the code in my mouse click handler:
public class Dashboard extends javax.swing.JFrame {
public static ClickMaster myClicks = new ClickMaster();
public static boolean drawing = false;
private MyPoint firstPoint = new MyPoint();
private MyPoint secondPoint = new MyPoint();
.
.
.
private void MyDrawingPanelMouseClicked(java.awt.event.MouseEvent evt) {
if (firstPoint.getPointType().equals(MyPoint.PointType.NULL)) {
drawing = !drawing;
firstPoint = myClicks.parseClick(evt.getX(), evt.getY(), drawing);
} else if (drawing){
drawing = !drawing;
secondPoint = myClicks.parseClick(evt.getX(), evt.getY(), drawing);
myClicks.parsePoints(firstPoint, secondPoint);
}
}
Here's the helper class that returns points:
public class ClickMaster {
MyPoint anyPoint = new MyPoint();
public ClickMaster() {
anyPoint.setPointType(MyPoint.PointType.NULL);
}
public MyPoint parseClick(double x, double y, boolean firstClick) {
if (firstClick) {
anyPoint.setPointType(MyPoint.PointType.ANCHOR);
} else {
anyPoint.setPointType(MyPoint.PointType.END);
}
anyPoint.setX(x);
anyPoint.setY(y);
return anyPoint;
}
And here's my implementation of Point2D objects, in case it's relevant:
public class MyPoint extends Point2D {
public enum PointType {
ANCHOR, END, SOLO, NULL
};
double x;
double y;
PointType pointType;
public MyPoint(PointType pType, double x, double y) {
this.x = x;
this.y = y;
this.pointType = pType;
}
public MyPoint() {
this.x = 0.0;
this.y = 0.0;
this.pointType = PointType.NULL;
}
+ standard getters/setters as you would expect.
debugging shows that
firstPoint = myClicks.parseClick(firstX, firstY, drawing);
results in a point with the x and y values of the mouse event. This is expected.
Likewise,
secondPoint = myClicks.parseClick(evt.getX(), evt.getY(), drawing);
Results in a point with the x and y values of the second click. Also expected.
However, when I call
myClicks.parsePoints(firstPoint, secondPoint);
I see that firstPoint and secondPoint have the same x,y values.
I'm not sure but I believe it's because both firstPoint and secondPoint are getting their x and y values from the mouse evt. I think I need to put values of type double for x's and y's in to firstPoint and secondPoint as opposed to a reference to the double value returned from the mouse event by getX() and getY().
I just don't know how to make it happen.
Also, if there's a much better way to capture consecutive clicks and translate them to endpoints for shapes, I would welcome the feedback.

Actually, your problem is anyPoint. Since you only have one instance of ClickMaster, and anyPoint is only initialized once, you're returning a reference to the same object no matter how many times you call parseClick. ParseClick needs to create a new MyPoint every time it's called and return that.

Related

Cubic Bézier formula returning wrong result

I've created a very simple form of a Cubic Bézier in Java in order to retrieve the Y value of the point retrieved given the time (t). In my implementation My first (P1) and last (P4) points are always (0, 0) and (1, 1) respectively, and I'm only going to be manipulating P1 and P2. The purpose of this is to create a modifiable curve used to retrieve a value that will be used to multiply and manipulate other values, like a difficulty ramp in video games.
I've tested my implementation using P2=(0.1, 0.1) and P3=(0.9,0.9), so the curve should effectively be a straight line, and whatever my input value (t) is, the output should mimic:
Here is my CubicBezier class:
#AllArgsConstructor
public class CubicBezier {
private static final Point P1 = new Point(0, 0);
private static final Point P4 = new Point(1, 1);
private Point p2;
private Point p3;
public double getValue(double t) {
double dt = 1d - t;
double dt2 = dt*dt;
double t2 = t*t;
Point temp = p2.copy();
return P1.copy()
.scale(dt2 * dt)
.add(temp.scale(3 * dt2 * t))
.add(temp.set(p3).scale(3 * dt * t2))
.add(temp.set(P4).scale(t2 * t))
.getY();
}
}
And my Point class:
#Data
#AllArgsConstructor
public class Point {
private double x;
private double y;
public Point(Point point) {
this.x = point.x;
this.y = point.y;
}
public Point copy() {
return new Point(this);
}
public Point set(Point point) {
this.x = point.x;
this.y = point.y;
return this;
}
public Point add(double scalar) {
this.x += scalar;
this.y += scalar;
return this;
}
public Point add(double x, double y) {
this.x += x;
this.y += y;
return this;
}
public Point add(Point point) {
return add(point.x, point.y);
}
public Point scale(double scalar) {
this.x *= scalar;
this.y *= scalar;
return this;
}
public Point scale(double x, double y) {
this.x *= x;
this.y *= y;
return this;
}
public Point scale(Point point) {
return scale(point.x, point.y);
}
}
My main method:
public static void main(String[] args) {
CubicBezier bezier = new CubicBezier(new Point(0.1d, 0.1d), new Point(0.9d, 0.9d));
double value = 0.4;
System.out.println(value + ": " + bezier.getValue(value));
}
Expected output should be:
0.4: 0.4
However, the output I receive is:
0.4: 0.36640000000000006
And I can't understand why. My getValue method is modelled using the Cubic Bézier explicit form specified on Wikipedia. Am I missing something?
Note: I'm using Lombok to remove some boilerplate. I can specify this boilerplate if necessary.
EDIT:
So it appears that my bezier curve is actually working as it should, and that I've been mistaking t as a value on the x axis, assuming that the y value of the calculated bezier curve will be in relation to the x axis. The functionality I want is that, with the resulting curve, given a value x, return the y value in relation. So in the screenshot above, where the curve is a straight line, x should equal y.
I figured out the answer to my question. There was never anything wrong with my code, the error was a lack of understanding. I had assumed that because P1, p2, p3 and P4 were all points that lay on a straight line between 0 and 1 on both the x and y axes, that no matter where they were positioned on that line, time would reflect progression identically, i.e. x would equal y.
However, because p2 and p3 are closer to P0 and P4 respectively, the progression along the curve is stretched out relative to the time.
In order for a Cubic Bézier curve to have the same progression (y) value as the time (t) value where P1 = (0, 0) and P4 = (1, 1), both inside points must be spread evenly along the curve on both axes. So p2 must be (0.33333, 0.33333) and p3 must be (0.66666, 0.66666).
An example of this problem is shown in this video here. When the points are spread apart, the resulting value is affected.

Java how to have two variables point to the same primitive object

I am writing a platform game in Java in which there are various game objects such as platforms, the player, and (eventually) enemies. I describe the position of these game objects with rectangles: x position, y position, width, and height. However, I would also like to add in other variables to describe the position: left, top, right, and bottom. For the last two I know I will need to change them whenever x, y, width, or height gets modified, but as left and top are the same as x and y, I was wondering how I could get them to point to the same value as x and y. I think this can be done in C with the #define function, but sadly this is Java, not C.
How can I get two different variable names to point to the same value in Java such that if one changes, the other changes as well?
Edit: Here is the basics of my GameObject class:
public abstract class GameObject {
protected float x;
protected float y;
protected float right;
protected float bottom;
protected float width;
protected float height;
public float getX() {
return x;
}
public float getY() {
return y;
}
public void setX(float x) {
this.x = x;
right=this.x+width;
}
public void setY(float y) {
this.y = y;
bottom=this.y+height;
}
//A bunch of other getters/setters
//Subclasses must have render (for displaying graphics) and tick (mainly for updating position) functions.
public abstract void render(Graphics g);
public abstract void tick();
}
What I would like to do is add in two more variables:
protected float left = x;
protected float top = y;
and have these refer to the same primitive as x and y (not copy the primitives). This, apparently, does not seem possible. Thanks for your answers!
This can't be done in Java in the sense that you mean it. You can have two object references that point to the same object, but if you have a normal primitive variable, those are always distinct and don't refer to each other. You can make an object to hold a primitive, have two different references to that same object, and a change to the contents of that object through one reference will be reflected in the other, but you cannot have an int x and and int y where writing x = 10 will make y == 10.
If you really need something behaving like a reference to a primitive, you need to create an object holding that primitive value and then share the "holder" object.
However, I don't think this is the best way to tackle your problem.
As I understand your game objects, they can be entirely described with x, y, height and width variable. left, top, right and bottom on the other hand, are values that can derived from the four basic ones.
In fact, it would be possible to have a game object containing only x, y, height and width and to compute the other four values outside of the object whenever they are needed. Such an object could look like this :
public class GameObject {
private int x, y, height, width;
public int getX() { return x; }
public int getY() { return y; }
public int getHeight() { return height; }
public int getWidth() { return width; }
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
public void setHeight(int height) { this.height = height; }
public void setwidth(int width) { this.width = width; }
}
Notice that the actual variables are private and only readable through getters. This helps to avoid the use of a variable reference later on.
Now, to have an easy and unique way to access to left, top, right and bottom, while you could add four variables and keep them in sync with the four other variable already present, I think it is not the best way to do it.
I suggest that you just compute them on the fly inside slightly smarter-than-average getters. It would look like that :
public class GameObject {
// getters and setters omitted for brevity
private int x, y, height, width;
public int getLeft() {
return x;
}
public int getRight() {
// assuming x increase toward the right
return x + width;
}
public int getTop() {
return y
}
public int getBottom() {
// assuming y increase toward the bottom
return y + height;
}
}
This will also help if you need to create some special update methods, like moveRight(int delta), scale(double factor) since you will only need to apply changes to the basic variables and not the values that are derived from them.
int/integer is passed by value, not by reference in java.
You can define a new class, For example,
public class Position {
int x;
int y;
}
Let two variables point to the same instance of Position.
In java there are two types of variables.
1.Primitive types
2.Reference types
You need to use reference type variable if you want to refer the same object through different variables.
In your case for gaming application those parameters might change frequently.
So if all the time values, left and top are same as x and y, you can use use one variable to represent the both parameters which saves memory.
e.g : for left and x use one variable.
Or else using java OOP concepts,
you can make those x, y, left, top parameters private and assign getters and setters for those.
public int setX(int x){
this.x =x;
}
public setLeft(int left){
this.left = left;
}
public int setY(int y){
this.y =y;
}
public setTop(int top){
this.top= top;
}
public setXnLeft(int xnleft){
setX(xnleft);
setleft(xnleft);
}
public setYnTop(int yntop){
setY(yntop);
setTop(yntop);
}
This can easily be done by creating a new Class. Java is object-oriented, so, basically, everything is about classes and it's instances. Take a look at an example below:
class GameObject
{
//Instance variables
//(all objects of this class will have their own)
int x;
int y;
int width;
int height;
//Constructor
//(you call a constructor when creating a new object)
GameObject(int x, int y, int width, int height)
{
//Here you are assigning the values received to the instance variables (marked with "this", that represents the current object)
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
//This method will return the ordinate ("y") of the object's top position (assuming the "y axis" points down)
int getTop() {
return (y - height/2);
}
}
After creating the class GameObject, you can create instances (objects) of it. Look below:
GameObject player = new GameObject(0, 0, 50, 50); //creates a new object with coordinates (0,0), width = 50 and height = 50
GameObject enemy1 = new GameObject(30, 50, 100, 100);
//Getting the "x" position of the player and the monster
System.out.println("Player X = " + player.x);
System.out.println("Enemy1 X = " + enemy1.x);
//Get the top position "y"
System.out.println("Player top = " + player.getTop());
//Change player's "y"
player.y = 10;
//Get player's top position again
System.out.println("Player top = " + player.getTop()); //it will have changed, since "y" was changed.
Oracle has a really good lesson about Object-Oriented Programming, you should check it out here. The C language is structured, while Java is Object-Oriented, these are two different paradigms. I hope this was of help. Cheers!

Initializing an object without new operator in java

Whats the difference between these two constructors.
Circle (Point2D center, double radius) {
this.center = center;
this.radius = radius;
}
Circle (Point2D center, double radius) {
this.center = new Point2D(center.getX(), center.getY());
this.radius = radius;
}
Heres the Point2D class. Both versions of the constructors are working just fine. I am just confused whats the difference.
class Point2D {
double x;
double y;
Point2D () {
x = 0;
y = 0;
}
Point2D (double x, double y) {
this.x = x;
this.y = y;
}
void setX (double x) {
this.x = x;
}
void setY (double y) {
this.y = y;
}
void setXY (double x, double y) {
this.x = x;
this.y = y;
}
double getX () {
return x;
}
double getY () {
return y;
}
double distance (Point2D p) {
double x1 = p.getX();
double y1 = p.getY();
return Math.sqrt(Math.pow(x1 - x, 2) + Math.pow(y1 - y, 2));
}
double distance (double x, double y) {
return Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y - this.y, 2));
}
}
Also the Circle class has 2 fields center and radius. center is type Point2D and radius is type double. I tried compiling and running both versions of the constructor. Both works well. So i am confused which one will be better to use and why, also the difference because in first one i havent used the new operation to initialize the center object.
second constructor uses defensive copy (witch is produced by Point2D constructor call) of the original center instance to prevent further mutation (changes) of the input instance that may be very confusing and produce bugs
So i am confused which one will be better to use and why
the second approach is more safe because your Point2D class is mutable. It uses more memory (to hold additional defensive copy) but in real complex projects there are more pros for this design practice than cons.
If you can make Point2D class immutable then it will be ok to use the first constructor.
The second constructor creates a new Point instance - this.center = new Point2D(center.getX(), center.getY()); instead of keeping a reference to the instance passed to it. This means that if the passed center is later modified, the changes doesn't affect the Circle instance.
The second constructor is usually safer, since it has a truly private Point instance as the center of the Circle, while the first constructor shares the center with the caller of the constructor.
You can see the difference with this code :
Point2D point = new Point2D(10.0, 20.0);
Circle circle = new Circle (point, 4.0);
point.setX (5.0);
System.out.println(circle); // assuming you override toString to display the properties
// of the Circle
If you use the first constructor, after this code is executed, your circle will have a center of (5.0,20.0), while if you use the second constructor, the circle will have a center of (10.0,20.0);
Point2D is not immutable, i.e. has properties which can be changed after the point was constructed.
The first constructor of Circle just uses the Point2D object - now the caller could change the point object which would also affect the circle.
The second constructor of Circle makes a copy of the Point2D object. If the circle keeps the point object private it cannot be changed from outside.
this.center = center, you using parameter of center object.
this.center = new Point2D(center.getX(), center.getY()), you create new object of Point2D with parameter center value.

How to use OOP to branch from a point class into lines and triangles (Java) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to create simple objects, branching out from a single point object, into a line object (two points), and then into a triangle object (three points). I understood how to create the point class, though when trying to branch into the line class, I got a bit confused with how to actually go into writing a line class or triangle class using the initial point class. I need some help with going from a single point class into
I can post some code that I have done so far.
I also have read that there are already java geometry classes out there, but I want to actually create these classes to practice with OOP.
edit --- Added code below
class Point
{
private double x;
private double y;
public Point()
{
x = 0.0;
y = 0.0;
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public double getX()
{
return this.x;
}
public double getY()
{
return this.y;
}
public void setX(double x)
{
this.x = x;
}
public void setY(double y)
{
this.y = y;
}
public double distance(Point p)
{
return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y)
* (this.y - p.y));
}
public String toString()
{
String s = "(" + x + ", " + y + ")";
return s;
}
public boolean equals(Point p)
{
double delta = 1.0e-18;
return (Math.abs(this.x - p.x) < delta)
&& (Math.abs(this.y - p.y) < delta);
}
//-----------------Line Class--------------------//
class Line
{
private Point p1;
private Point p2;
public Line()
{
p1 = new Point (0,0);
p2 = new Point (1,1);
}
public Line(double x1, double y1, double x2, double y2)
{
p1 = new Point (x1, y1);
p2 = new Point (x2, y2);
}
public Line(Point p, Point q)
{
p1 = new Point(p.getX(), p.getY());
p2 = new Point(q.getX(), q.getY());
}
public Point getP1()
{
return this.p1;
}
public Point getP2()
{
return this.p2;
}
public void setP1(double x, double y)
{
Point p1 = new Point(x, y);
this.p1 = p1;
}
public void setP2(double x, double y)
{
Point p2 = new Point(x, y);
this.p2 = p2;
}
public boolean isParallelY()
{
double delta = 1.0e-18;
return (Math.abs(p1.getX() - p2.getX()) < delta);
}
public boolean isParallelX()
{
double delta = 1.0e-18;
return (Math.abs(p1.getY() - p2.getY()) < delta);
}
public boolean isParallel (Line line)
{
if (this.Slope() == line.Slope())
return true;
else
return false;
}
public double Slope()
{
double inf = Double.POSITIVE_INFINITY;
if(isParallelY())
return inf;
return ((p2.getY() - p1.getY()) / (p2.getX() - p1.getX()));
}
public double xIntercept()
{
return -(p1.getY() / Slope() - p1.getX());
}
public double yIntercept()
{
return p1.getY() - (Slope() * p1.getX());
}
I am still adding methods to the line class right now and have not started on the triangle class (though I was thinking of creating a triangle with 3 points rather than 3 lines. And sorry about the branching confusion, I am relatively new.
A Line has 2 Points, so any Line class will have 2 Point-attributes
Any Triangle has 3 Points, so any Triangle class will have 3 Point-attributes
You can create the constructor of these classes to ensure correct objects.
public Line(Point point1, Point point2)
{
this.point1 = point1;
this.point2 = point2;
}
and for the Triangle class
public Triangle(Line line1, Line line2, Line line3)
{
this.point1 = line1.firstpoint();
this.point2 = line2.firstpoint();
this.point3 = line3.firstpoint();
}
or
public Triangle(Point point1, Point point2, Point point3)
{
this.point1 = point1;
this.point2 = point2;
this.point3 = point3;
}
Since each class contains the right attributes you can calculate with them.
If you really want to do OOP, think about what objects exist in your domain, and what messages they understand - that's all Mr Kay ever talked about :)
In your case, you've found Points. Seems you are thinking in a 2D point, and that's why you've just used x and y coordinates. In a 2D world, what would we like to ask to a Point? It's position/coordinates, right - we already have them. What else? A distance to another Point, right. That seems to be pretty much everything a Point can do by now.
Wait - we can ask it to join another Point, creating a Line. So, maybe, doing aPoint.lineTo(anotherPoint) isn't that bad. But, hey, the important thing is we are actually creating Lines.
They consist in a pair of dots. What would we like to ask to a Line? It's lenght, of course. It's clearly the same as the distance between its points. We can ask it the distance to a Point (some mathematicians already defined it, yeah). We can ask a Line if it's parallel with another one, or if they cross. We can ask it at which point they cross. We can ask the angle formed by two lines. And, then, again, we can ask it to join with a third point, to create a Triangle.
Then we'll have a convex shape, so new fun things as area, perimeter, internal angles, external angles.
Try to think of things, concepts and definitions, and implement them as simply as you can. Try to make code as nearly as possible to the colloquial definitions of the concepts it represents. And construct new abstractions based on the previous ones.
Besides all of this, there's one thing you shall not forget: programming is modeling. Models are abstractions. OOP is about using objects to model the portion of the reality we are interested in. If you don't define the scope of what things you wish to model (as this case is just an educational activity, with no real requirements), you can spend your hole life adding methods to your objects, without much sense. Think in advance what things you would like to be able to do with your Points, Lines, Triangles, etc, and limit yourself to them.
Happy hacking :)

Method takes another object as a parameter

I am doing homework for java programming. I am asked to write a method that returns a distance between two points. I should use given formula that distance = square root((x2 - x1)*(x2 - x1) +(y2 - y1)*(y2 - y1)).
In the below codes, an object a will be contained current coordinate x1 and y1 and b will be coordinate x2 and y2, passed to move at some where.
How can I write the method in this class without having other classes and other elements such as x2, y2? In the objects there are two values but how can I assign each to x1 and x2, and y1 and y2? I found definition of vector for java but I am not sure it is applicable for this. Does anybody have an idea?
public class MyPoint{
private int x;
private int y;
}
public MyPoint(int x, int y){
this.x = x;
this.y = y;
}
public int distanceTo(MyPoint a, MyPoint b){
MyPoint.x1 = a;
MyPoint.y1 = a;
MyPoint.x2 = b;
MyPoint.y2 = b;
double distance = Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
return distance;
}
}
The distanceTo method should only take one parameter, a MyPoint object, not two parameters:
public double distanceTo(MyPoint other) {
// ...
}
The first object of the comparison will be the current object, the one whose method is being called.
Then in the method body you compare the current object's fields, the this.x and this.y with the x and y values of the object passed in to the method's parameter, other.x and other.y.
Also, the method probably should return a double, not an int as you have it defined.
Regarding,
How can I write the method in this class without having other classes and other elements such as x2, y2?
I'm not sure exactly what you mean by this.
You don't need to declare MyPoint.x1 = a. That isn't really doing anything. Instead you can reference the points such as a.x or b.y.
Additionally you should make sure that your return type is what you want.
EDIT: Hovercraft has essentially said the same as I did but a little nicer.
public class Point
{
int x,y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public static double distance(Point a, Point b)
{
return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
public static void main(String[] args)
{
Point a = new Point(0,0);
Point b = new Point(3,5);
System.out.println(distance(a,b));
}
}

Categories