How to trigger multiple MouseEvent events - java

I have a class that when clicked draws one point, when clicked again it draws another point and draws the line between them.
public class SlopeComponent extends JComponent
{
private static final long serialVersionUID = 1L;
public SlopeComponent()
{
point1 = null;
point2 = null;
class MouseSpy extends MouseAdapter
{
public void mousePressed(MouseEvent event)
{
double x1 = rxPixel(event.getX());
double y1 = ryPixel(event.getY());
point1 = new Point2D.Double(x1, y1);
double x2 = rxPixel(event.getX());
double y2 = ryPixel(event.getY());
point2 = new Point2D.Double(x2, y2);
repaint();
}
}
MouseSpy listener = new MouseSpy ();
addMouseListener(listener);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Axes axes = new Axes(xPixel(XMIN), xPixel(XMAX), yPixel(YMIN), yPixel(YMAX),
xPixel(0), yPixel(0), sWidth(1), sHeight(1));
axes.drawAxes(g2); //draw the axes
axes.drawTicks(g2);
if(point1 != null || point2 != null)
{
plotPoint(g2, point1);
plotPoint(g2, point2);
double x1 = point1.getX();
double y1 = point1.getY();
double x2 = point2.getX();
double y2 = point2.getY();
drawSlope(g2, x1, y1, x2, y2);
}
}
public void drawSlope(Graphics2D g2, double x1, double y1, double x2, double y2) //draw the lines
{
Point2D.Double p1 = new Point2D.Double(xPixel(x1), yPixel(y1));
Point2D.Double p2 = new Point2D.Double(xPixel(x2), yPixel(y2));
Line2D.Double line = new Line2D.Double(p1, p2);
g2.draw(line);
}
public void plotPoint(Graphics2D g2, Point2D.Double p) //plot the point
{
double x = p.getX();
double y = p.getY();
double radius = 5 * (XMAX - XMIN) / getWidth();
Ellipse2D.Double point = new Ellipse2D.Double(xPixel(x - radius), yPixel(y + radius),
sWidth(2 * radius), sHeight(2 * radius));
g2.fill(point);
double xR = Rounding.round(x, 1);
double yR = Rounding.round(y, 1);
double gap = 6 * (XMAX - XMIN) / getWidth();
g2.drawString("(" + xR + ", " + yR + ")", (float)xPixel(x + gap), (float)yPixel(y + gap));
}
public double rxPixel(double x)
{
return x * (XMAX - XMIN) / (getWidth() - 1) + XMIN;
}
public double ryPixel(double y)
{
return y * (YMIN - YMAX) / (getHeight() - 1) + YMAX;
}
public double xPixel(double xuser)
{
return (xuser - XMIN) * (getWidth() - 1) / (XMAX - XMIN);
}
public double yPixel(double yuser)
{
return (yuser - YMAX) * (getHeight() - 1) / (YMIN - YMAX);
}
public double sHeight(double yuser)
{
return yuser * (getHeight() - 1) / (YMAX - YMIN);
}
public double sWidth(double xuser)
{
return xuser * (getWidth() - 1) / (XMAX - XMIN);
}
private static final double XMIN = -10;
private static final double XMAX = 10;
private static final double YMIN = -10;
private static final double YMAX = 10;
private Point2D.Double point1;
private Point2D.Double point2;
}
However, when I try to run this, it draws both points on top of each other, then the line on top of that. I know that in my constructor I am calling getX() and getY() on the same event so that point1 and point2 have the coordinates. How do I call multiple events so that this does not happen.

You can count the clicks, you can do something like this
int count = 0;
public void mousePressed(MouseEvent event)
{
if(count == 0){
double x1 = rxPixel(event.getX());
double y1 = ryPixel(event.getY());
point1 = new Point2D.Double(x1, y1);
count++;
}
if(count == 1){
double x2 = rxPixel(event.getX());
double y2 = ryPixel(event.getY());
point2 = new Point2D.Double(x2, y2);
repaint();
}
}

Related

JAVA: mouseDragged getX and getY raw data erratic

I am trying to code a paint like program (for fun), but to challenge myself I tried to do it using setRGB method, but I see that when I move the mouse fast the behavior of the stroke gets erratic, do you know how to "soft" the data get from methods getX and getY? or why I am getting random points colored
Thank you in advance and sorry for my english. :)
public class Canvas extends JPanel implements ActionListener, MouseMotionListener, MouseListener {
int canvasW;
int canvasH;
BufferedImage imgCanvas;
int X1;
int Y1;
int X0;
int Y0;
int sizeCanvas = 10;
int expCanvas = 2 * sizeCanvas - 1;
public Canvas(int width, int height) {
canvasH = height;
canvasW = width;
setPreferredSize(new Dimension(width, height));
setBorder(BorderFactory.createLineBorder(Color.black));
setBackground(Color.white);
CanvasImage(width, height);
addMouseListener(this);
addMouseMotionListener(this);
}
public BufferedImage CanvasImage(int width, int height) {
imgCanvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
return imgCanvas;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(imgCanvas, null, null);
}
#Override
public void actionPerformed(ActionEvent e) {
}
public void drawer() {
int deltaX = abs(X1 - X0);
int deltaY = abs(Y1 - Y0);
double m;
double b;
if (deltaX >= deltaY) {
if (deltaY == 0) {
m = 0;
} else {
m = (X0 - X1) / (Y0 - Y1);
}
b = Y0 - m * X0;
if (X1 > X0) {
for (int i = X0; i <= X1; i++) {
imgCanvas.setRGB(i, (int) (m * i + b), Color.BLACK.getRGB());
System.out.println(i + " ; " + (int) (m * i + b));
}
} else {
for (int i = X0; i >= X1; i--) {
imgCanvas.setRGB(i, (int) (m * i + b), Color.BLACK.getRGB());
System.out.println(i + " ; " + (int) (m * i + b));
}
}
} else {
if (deltaX == 0) {
m = 0;
} else {
m = (Y0 - Y1) / (X0 - X1);
}
b = X0 - m * Y0;
if (Y1 > Y0) {
for (int i = Y0; i <= Y1; i++) {
imgCanvas.setRGB((int) (m * i + b), i, Color.BLACK.getRGB());
}
} else {
for (int i = Y0; i >= Y1; i--) {
imgCanvas.setRGB((int) (m * i + b), i, Color.BLACK.getRGB());
}
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
X1 = e.getX();
Y1 = e.getY();
drawer();
repaint();
X0 = X1;
Y0 = Y1;
}
#Override
public void mousePressed(MouseEvent e) {
X0 = e.getX();
Y0 = e.getY();
}

Moving ball at an Angle

I am a newbie and trying to move a ball at a slope. Here is the code where I am giving coordinates (100,300,300,600) to move the ball in a slope but it's getting away from the the slope line. Here's the code: -
import javax.swing.*;
import java.awt.*;
public class AgentMotion extends JPanel implements Runnable
{
Color color = Color.red;
int dia = 0;
long delay = 40;
private double x;
private double y;
private double x1;
private double y1;
private int dx = 1;
private int dy = 1;
private int dv = 1;
private double direction;
double a;
double b;
double a1;
double b1;
public void abc(double x, double y, double x2, double y2) {
this.x = x;
this.y = y;
this.x1 = x2;
this.y1 = y2;
this.direction=Math.toRadians(Math.atan2(x1-x,y1-y));
System.out.println("segfewg"+direction);
this.a = x;
this.b = y;
this.a1 = x1;
this.b1 = y1;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
//int x=100;
//int y=200;
int x3=(int)this.x;
int y3=(int)this.y;
g.fillOval(x3,y3,5,5); // adds color to circle
g.setColor(Color.black);
g2.drawOval(x3,y3,5,5); // draws circle
g2.drawLine(100, 300, 300, 600);
}
public void run() {
if(direction<0)
{
System.out.println("refregreg");
while(dy!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
else
{
while(dx!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
}
public void move() {
if(direction>0)
{
if(x + dv*Math.cos(direction) <a ||x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x += dx;
}
else
{
System.out.println(x + dia + dv * Math.cos(direction));
if(x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x -= dx;
}
}
public void move2() {
if(direction>0)
{
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y > b1) {
dy *= 0;
color = getColor();
}
y += dy;
}
else
{
System.out.println(dv * Math.sin(direction) + dia + y);
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y < b1) {
dy *= 0;
color = getColor();
}
y -= dy;
}
}
public Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
public void start() {
while(dx==0) {
try {
System.out.println("jiuj");
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("dwdwdwd");
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
A few suggestions
dx and dy should be double
atan is overkill as #Spektre says. What you want is much more simple to calculate direction.
this.direction = (y2 - y) / (x2 - x)
If we give (100,300,300,600) as the arguments to abc (which would presumably be a constructor for this class), the slope is 1.5. Therefore we could say:
dx = 1.0
dy = 1.5
and this would keep on the line perfectly. For the general case where you want to change the begin and the end point, you have to calculate the ratio. So you could set either dx or dy to 1.0 and then set the other one so that the ratio is maintained. Something like the following mathematical pseudocode:
dx = (x2 - x) / minimum(x2-x, y2-y)
dy = (y2 - y) / minimum(x2-x, y2-y)

Java OpenCV deskewing a contour

I have made some progress detecting a specific kind of object. Actually a card, just like any other in your wallet.
Now I'm stuck with deskewing the photo. See:
The blue (rounded) rectangle represents the detected contour.
The purple rotate rectangle represents a RotatedRect extracted from the detected contour.
The green line is just the bounding box.
Well I need neither of those rectangles. The rectangles both have 90 degree corners. Which won't get me the perspective.
My question:
How can I get as accurate as possible all quadrangle corners from a contour?
I have created a class Quadrangle which creates the quadrangle of the 4 most largest connected polygon vertices which will intersect each other at some point. This will work in nearly any case.
If you use this code, remember to adjust the width and height in Quadrangle.warp. Note that it isn't 100% complete, the first and last polygon vertices won't be connected if they may be connect for example.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
class Line {
public Point offset;
public double angle;
public Line(Point offset, double angle) {
this.offset = offset.clone();
this.angle = angle;
}
public Point get(int length) {
Point result = offset.clone();
result.x += Math.cos(angle) * length;
result.y += Math.sin(angle) * length;
return result;
}
public Point getStart() {
return get(-5000);
}
public Point getEnd() {
return get(5000);
}
public void scale(double factor) {
offset.x *= factor;
offset.y *= factor;
}
public static Point intersect(Line l1, Line l2) {
return getLineLineIntersection(l1.getStart().x, l1.getStart().y, l1.getEnd().x, l1.getEnd().y,
l2.getStart().x, l2.getStart().y, l2.getEnd().x, l2.getEnd().y
);
}
public static Point getLineLineIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
double det1And2 = det(x1, y1, x2, y2);
double det3And4 = det(x3, y3, x4, y4);
double x1LessX2 = x1 - x2;
double y1LessY2 = y1 - y2;
double x3LessX4 = x3 - x4;
double y3LessY4 = y3 - y4;
double det1Less2And3Less4 = det(x1LessX2, y1LessY2, x3LessX4, y3LessY4);
if (det1Less2And3Less4 == 0){
// the denominator is zero so the lines are parallel and there's either no solution (or multiple solutions if the lines overlap) so return null.
return null;
}
double x = (det(det1And2, x1LessX2,
det3And4, x3LessX4) /
det1Less2And3Less4);
double y = (det(det1And2, y1LessY2,
det3And4, y3LessY4) /
det1Less2And3Less4);
return new Point(x, y);
}
protected static double det(double a, double b, double c, double d) {
return a * d - b * c;
}
}
class LineSegment extends Line implements Comparable {
public double length;
public LineSegment(Point offset, double angle, double length) {
super(offset, angle);
this.length = length;
}
public void melt(LineSegment segment) {
Point point = new Point();
point.x += Math.cos(angle) * length;
point.y += Math.sin(angle) * length;
point.x += Math.cos(segment.angle) * segment.length;
point.y += Math.sin(segment.angle) * segment.length;
angle = Math.atan2(point.y, point.x);
offset.x = (offset.x * length + segment.offset.x * segment.length) / (length + segment.length);
offset.y = (offset.y * length + segment.offset.y * segment.length) / (length + segment.length);
length += segment.length;
}
#Override
public int compareTo(Object other) throws ClassCastException {
if (!(other instanceof LineSegment)) {
throw new ClassCastException("A LineSegment object expected.");
}
return (int) (((LineSegment) other).length - this.length);
}
}
class Quadrangle {
static int
TOP = 0,
RIGHT = 1,
BOTTOM = 2,
LEFT = 3;
public Line[] lines = new Line[4];
public Quadrangle() {
}
private static double getAngle(Point p1, Point p2) {
return Math.atan2(p2.y - p1.y, p2.x - p1.x);
}
private static double getLength(Point p1, Point p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
private static double roundAngle(double angle) {
return angle - (2*Math.PI) * Math.round(angle / (2 * Math.PI));
}
public static Quadrangle fromContour(MatOfPoint contour) {
List<Point> points = contour.toList();
List<LineSegment> segments = new ArrayList<>();
// Create line segments
for (int i = 0; i < points.size(); i++) {
double a = getAngle(points.get(i), points.get((i + 1) % points.size()));
double l = getLength(points.get(i), points.get((i + 1) % points.size()));
segments.add(new LineSegment(points.get(i), a, l));
}
// Connect line segments
double angleDiffMax = 2 * Math.PI / 100;
List<LineSegment> output = new ArrayList<>();
for (LineSegment segment : segments) {
if (output.isEmpty()) {
output.add(segment);
} else {
LineSegment top = output.get(output.size() - 1);
double d = roundAngle(segment.angle - top.angle);
if (Math.abs(d) < angleDiffMax) {
top.melt(segment);
} else {
output.add(segment);
}
}
}
Collections.sort(output);
Quadrangle quad = new Quadrangle();
for (int o = 0; o < 4; o += 1) {
for (int i = 0; i < 4; i++) {
if (Math.abs(roundAngle(output.get(i).angle - (2 * Math.PI * o / 4))) < Math.PI / 4) {
quad.lines[o] = output.get(i);
}
}
}
return quad;
}
public void scale(double factor) {
for (int i = 0; i < 4; i++) {
lines[i].scale(factor);
}
}
public Mat warp(Mat src) {
Mat result = src.clone();
Core.line(result, lines[TOP].get(-5000), lines[TOP].get(5000), new Scalar(200, 100, 100), 8);
Core.line(result, lines[RIGHT].get(-5000), lines[RIGHT].get(5000), new Scalar(0, 255, 0), 8);
Core.line(result, lines[BOTTOM].get(-5000), lines[BOTTOM].get(5000), new Scalar(255, 0, 0), 8);
Core.line(result, lines[LEFT].get(-5000), lines[LEFT].get(5000), new Scalar(0, 0, 255), 8);
Point p = Line.intersect(lines[TOP], lines[LEFT]);
System.out.println(p);
if (p != null) {
Core.circle(result, p, 30, new Scalar(0, 0, 255), 8);
}
double width = 1400;
double height = width / 2.15;
Point[] srcProjection = new Point[4], dstProjection = new Point[4];
srcProjection[0] = Line.intersect(lines[TOP], lines[LEFT]);
srcProjection[1] = Line.intersect(lines[TOP], lines[RIGHT]);
srcProjection[2] = Line.intersect(lines[BOTTOM], lines[LEFT]);
srcProjection[3] = Line.intersect(lines[BOTTOM], lines[RIGHT]);
dstProjection[0] = new Point(0, 0);
dstProjection[1] = new Point(width - 1, 0);
dstProjection[2] = new Point(0, height - 1);
dstProjection[3] = new Point(width - 1, height - 1);
Mat warp = Imgproc.getPerspectiveTransform(new MatOfPoint2f(srcProjection), new MatOfPoint2f(dstProjection));
Mat rotated = new Mat();
Size size = new Size(width, height);
Imgproc.warpPerspective(src, rotated, warp, size, Imgproc.INTER_LINEAR);
return rotated;
}
}

Triangle class using an abstract shape class

So I have this triangle class I need to create using an abstract class. It will also be drawn by a tester class. I am part of the way through it but I am having serious issues with the math portion. I have set the coordinates in the tester class, I have no idea of how to get the pen to turn a certain degree to draw the next side of the triangle. Attached is all the classes and I have so far. Any help will be appreciated.
Tester class
import TurtleGraphics.*;
public class TestShapes1 {
public static void main (String[] args) {
// Declare and instantiate a pen, a circle and a wheel
Pen p = new StandardPen();
//Shape s1 = new Circle1 (20, 20, 20);
//Shape s2 = new Wheel1 (-20, -20, 20, 6);
Shape1 t2 = new Triangle1 (0, 0, 50, 0, 0, 30);
// Draw the circle and wheel
//s1.draw (p);
t2.draw (p);
}
}
Shape Class
import TurtleGraphics.Pen;
public interface Shape1 {
public double area();
public void draw (Pen p);
public double getXPos();
public double getYPos();
public void move (double xLoc, double yLoc);
public void stretchBy (double factor);
public String toString();
}
Triangle Class
import TurtleGraphics.Pen;
public class Triangle1 implements Shape1 {
private double x1, y1, x2, y2, x3, y3;
private double s1, s2, s3;
private double d1, d2;
//private double height, width;
public Triangle1() {
x1 = 0;
y1 = 0;
x2 = 1;
y2 = 0;
x3 = 0;
y3 = 1;
//height = 1;
//width = 1;
}
public Triangle1 (double xLoc1, double yLoc1, double xLoc2, double yLoc2, double xLoc3, double yLoc3) {
x1 = xLoc1;
y1 = yLoc1;
x2 = xLoc2;
y2 = yLoc2;
x3 = xLoc3;
y3 = yLoc3;
//height = h;
//width = w;
}
public double area() {
return (Math.abs(x1*y2-x2*y1+x2*y3-x3*y2+x3*y1-x1*y3))/2.0;
}
public void draw (Pen p) {
s1 = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
s2 = Math.sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));
s3 = Math.sqrt((x3-x1)*(x3-x1)+(y3-y1)*(y3-y1));
p.up();
p.move (x1, y1);
p.down();
p.setDirection (0);
p.move (s1);
d1 = (Math.acos((s2*s2+s3*s3-s1*s1)/(2.0*s2*s3)))*180/Math.PI;
p.turn (180 - d1);
p.move (s2);
d2 = (Math.acos((s3*s3+s1*s1-s2*s2)/(2.0*s3*s1)))*180/Math.PI;
p.turn (180 - d2);
p.move (s3);
p.turn (-90);
//p.move ();
}
public double getXPos() {
return x1;
}
public double getYPos() {
return y1;
}
public void move (double xLoc, double yLoc) {
x1 = x1 + xLoc;
y1 = y1 + yLoc;
x2 = x2 + xLoc;
y2 = y2 + yLoc;
x3 = x3 + xLoc;
y3 = y3 + yLoc;
}
public void stretchBy (double factor) {
x1 *= factor;
y1 *= factor;
}
public String toString() {
String str = "TRIANGLE\n";
// + "Width & Height: " + width + " & " + height +"\n"
// + "(X,Y) Position: (" + xPos + "," + yPos + ")\n"
// + "Area: " + area();
return str;
}
}
You don't need any math. Just pass the degrees to p.turn(). So use
p.turn(180);
instead of
d1 = (Math.acos((s2*s2+s3*s3-s1*s1)/(2.0*s2*s3)))*180/Math.PI;
p.turn (180 - d1);
See the documentation for reference:
The degrees can be an integer or floating-point number. Example:
pen.turn(-45); Rotate the pen 45 degrees clockwise.

Graph and zoom function

I would like to add a zooming function in my graph.
For exemple, if the maxY of my graph is 5000, and i zoom a distance of 200 meters around the center, my axis should represent values from 2400 to 2600, the center at being 2500.
private class ZoomHandler implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
double distanceY = maxY;
double cursorY = maxY / 2.0;
int rotation = e.getWheelRotation();
if (rotation < 0) {
distanceY = 200 / 2;
} else {
distanceY = 200 * 2;
}
maxY = cursorY + distanceY;
repaint();
}
}
Can somebody help with math operation ?
Thank you.
The graph is draw this way:
private void drawAxis(Graphics2D g2) {
FontMetrics metrics = g2.getFontMetrics();
double axisH = yPositionToPixel(originY);
double axisV = xPositionToPixel(originX);
g2.drawLine(0 + V_BORDER, (int) axisH, getWidth(), (int) axisH);
g2.drawLine((int) axisV, (int) axisH, (int) axisV, getHeight() - H_BORDER);
}
protected double yPositionToPixel(double position) {
double height = (double) getHeight();
return pixelOriginY + (position) / (maxY) * (height - (pixelOriginY + H_BORDER));
}
protected double xPositionToPixel(double position) {
double width = getWidth();
return (width) - pixelOriginX - (position - minX) / (maxX - minX) * (width - (pixelOriginX + V_BORDER));
}
private void drawHorizontalLabels(Graphics2D g2) {
double axisV = xPositionToPixel(originX);
FontMetrics metrics = g2.getFontMetrics();
for (double y = originY + majorY; y < maxY + majorY; y += majorY) {
int position = (int) yPositionToPixel(y);
if (rightToLeft) {
g2.drawString(formatter.format(y), (int) axisV + 5, position);
}}
The constructor look like this :
public Graph(double originX, double originY, double pixelOriginX, double pixelOriginY,
double minX, double maxX,
double minY, double maxY,
double majorX, double majorY, String labelXaxis, String labelYaxis) {}
And this is how i initialise it :
new GraphDisplay(0.0, 0.0, 40, 100, -0.1, 120, -0.1, 5000, 20, 1000);
GraphDisplay extends Graph.
JFreeChart has this already built in.

Categories