How can i display the distance of a line drawing randomly? - java

I'm trying to draw to filled circles, centered at random locations, with a line connecting the circles. The distance between the to centers is displayed on the line and whenever your resize the frame, the circles are redisplayed in new random locations.
I'm stuck in how to display the distance?
Any help is appreciated and thx for advance.
This's the code (what i managed to do):
public class Test extends JFrame {
public Test() {
add(new LineConnectingTheTwoCircles());
}
// Panel class
class LineConnectingTheTwoCircles extends JPanel {
//Default constructor
LineConnectingTheTwoCircles() {
}
/* Override paintComponent (getting access to the panel's Graphics
class) */
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int radius = 15;
// getting coordinates of circle 1
int x1 = (int) (Math.random() * (getWidth()));
int y1 = (int) (Math.random() * (getHeight()));
// getting coordinates of circle 2
int x2 = (int) (Math.random() * (getWidth()));
int y2 = (int) (Math.random() * (getWidth()));
// Setting color and drawing a filled circles (1 & 2)
g.setColor(Color.BLUE);
g.fillOval(x1 - radius, y1 - radius, 2 * radius, 2 * radius);
g.drawString("1", x1 - 25, y1);
g.setColor(Color.RED);
g.fillOval(x2 - radius, y2 - radius, 2 * radius, 2 * radius);
g.drawString("2", x2 - 25, y2);
connectingTheTwoCircles(g, x1, y1, x2, y2);
}
// Connecting the two circles from the center
private void connectingTheTwoCircles(Graphics g, int x1, int y1,
int x2, int y2) {
//Distance between the circles centered
double D = Math.sqrt((Math.pow((y2 - y1), 2))
+ (Math.pow((x2 - x1), 2)));
//Getting the coordinates for the line l
int x11 = x1;
int y11 = y1;
int x21 = x2;
int y21 = y2;
g.setColor(Color.BLACK);
g.drawLine(x11, y11, x21, y21);
}
public double getDistance(double x1, double y1, double x2, double y2) {
return Math.sqrt((Math.pow((y2 - y1), 2))
+ (Math.pow((x2 - x1), 2)));
}
}
public static void main(String[] args) {
// Frame declaration
Test frame = new Test();
/*
* Invoking some methods, to set a title on the title bar, to specifier
* the size of the frame to centre it on the screen, to tell the program
* to terminate when the frame is closed and finally to display it
*/
frame.setTitle("This is a test");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

Try next code draws distance at line center
double distance = getDistance(x11, y11, x21, y21);
g.drawString(distance+" ",
x11> x21 ? x21 + (x11-x21)/2 : x11 + (x21 - x11)/2 ,
y11> y21 ? y21 + (y11-y21)/2 : y11 + (y21 - y11)/2 );

Related

Astroid Draw Java Program Problems

I'm trying to generate an astroid (Not asteroid) graphic similar to this:
This graphic output is generated on a 400x400 DrawingPanel. And the math is based on making curves from straight lines. However, I'm having a problem with my x,y coordinates. instead of making the astroid, I'm generating this:
Here is the code:
import java.awt.*;
public class GraphicsProject
{
//main method
public static void main (String[]args){
//Initialize the variable
//The Window is 400 x 400 pixels in size
DrawingPanel panel = new DrawingPanel (400,400);
Graphics g = panel.getGraphics();
drawAstroid(g,0,0, 400);
}
public static void drawAstroid(Graphics g, int x, int y, int size){
int scale = size/40;
int x1, x2,x3, x4, y1, y2, y3, y4;
y1 = y;
y2 = y + size;
y3 = y + 1/2 * size;
y4 = y + 1/2 * size;
x1 = x + 1/2 * size;
x2 = x + 1/2 * size;
x3 = x + 1/2 * size;
x4 = x + 1/2 * size;
for (int i = 0; i < 21; i++ ){
//Draws Upper Left
g.drawLine(x4 - scale * i, y4, x1, y1 + scale * i);
//Draws Upper Right
g.drawLine(x4 + scale * i, y4, x2, y2 - scale * i);
//Draws Lower Left
g.drawLine(x3 - scale * i, y3, x4, y4 + scale * i);
//Draws Lower Right
g.drawLine(x3 + scale * i, y3, x2, y2 - scale * i);
}
}
}
Any insight into how to resolve this would be appreciated.

how to rotate a wheel in java without using swing?

I'm working on a java applet where i want move or rotate a wheel..so I take a circle and 3 lines which are placed at 60 degrees to each other on the circle...and the length of the lines are the diameter of the circle..
So I use a Line constructor which has initial positions of the lines and a degree with respect to x-axis i.e. after a certain time (here 1sec) it will rotate 5 degree.
This code works fine for line1, which is horizontal to x-axis..but cant work for line2 and line3..need some suggestion
import java.awt.*;
import java.applet.*;
import java.lang.*;
class Line
{
int x1, x2, y1, y2, xChange=0, yChange=0;
double degree;
Line(int x1, int y1, int x2, int y2, double degree)
{
this.x1=x1;
this.y1=y1;
this.x2=x2;
this.y2=y2;
this.degree=degree;
}
public void rotate(float radius)
{
degree+=5;
double rads = Math.toRadians(degree);
x1+=5;
x2+=5;
if(degree==0)
degree=360;
xChange=(int) (radius - ((Math.cos(rads)) * radius));
yChange=(int) ((Math.sin(rads)) * radius);
}
}
public class Wheeler extends Applet implements Runnable
{
Thread t1;
int xCircle=40, yCircle=100, diameter=100;
Line line1, line2, line3;
int degree;
float radius=diameter/2;
public void init()
{
xCircle=40; yCircle=100; diameter=100;
line1=new Line(xCircle, yCircle+(diameter/2), xCircle+diameter, yCircle+(diameter/2), 0);
line2=new Line(xCircle+(int) (radius - ((Math.cos(Math.toRadians(60)) * radius))), yCircle+(diameter/2)+(int) ((Math.sin(Math.toRadians(60)) * radius)), xCircle+diameter-(int) (radius - ((Math.cos(Math.toRadians(60)) * radius))), yCircle+(diameter/2)-(int) ((Math.sin(Math.toRadians(60)) * radius)), 60);
line3=new Line(xCircle+(int) (radius - ((Math.cos(Math.toRadians(120)) * radius))), yCircle+(diameter/2)+(int) ((Math.sin(Math.toRadians(120)) * radius)), xCircle+diameter-(int) (radius - ((Math.cos(Math.toRadians(120)) * radius))), yCircle+(diameter/2)-(int) ((Math.sin(Math.toRadians(120)) * radius)), 120);
t1 = new Thread(this);
t1.start();
}
public void run ()
{
while(true)
{
try
{
repaint();
Thread.sleep(1000);
line1.rotate(radius);
line2.rotate(radius);
line3.rotate(radius);
xCircle+=5;
if(xCircle==1000)
{
xCircle=40;
line1.x1=xCircle;
line1.x2=xCircle+diameter;
line2.x1=xCircle+(int) (radius - ((Math.cos(Math.toRadians(60))) * radius));
line2.x2=xCircle+diameter-(int) (radius - ((Math.cos(Math.toRadians(60)) * radius)));
line3.x1=xCircle+(int) (radius - ((Math.cos(Math.toRadians(120)) * radius)));
line3.x2=xCircle+diameter-(int) (radius - ((Math.cos(Math.toRadians(120)) * radius)));
}
}
catch(InterruptedException e) {}
}
}
public void paint(Graphics g)
{
g.setColor(Color.GREEN);
g.drawOval(xCircle, yCircle, diameter, diameter);
g.setColor(Color.RED);
g.drawLine(line1.x1+line1.xChange, line1.y1-line1.yChange, line1.x2-line1.xChange, line1.y2+line1.yChange);
g.setColor(Color.RED);
g.drawLine(line2.x1+line2.xChange, line2.y1-line2.yChange, line2.x2-line2.xChange, line2.y2+line2.yChange);
g.setColor(Color.RED);
g.drawLine(line3.x1+line3.xChange, line3.y1-line3.yChange, line3.x2-line3.xChange, line3.y2+line3.yChange);
}
}

JPanel paintComponent in a Thread

I found a nice code on the web for drawing a binary tree. I created the binary search tree algorithm for it, now if I pass the root node for the function, it draws out my tree. I want to make it draw step by step, by running it in a thread, and making it sleep after inserting an element. Now the problem is, I guess, the JPanel itself won't be returned until the drawing is complete, so even if it runs on a different thread, it won't be added to my split pane ( I have many sorting algorithms implemented, and already being painted, and all can be accessed from the same tabbed pane. Every tabbed pane contains a split pane and every split pane contains the controlling buttons, and a jpanel, where I draw the algorithms, but the others do not extend from JPanel! ). Could you please help me find a way to run this in a totally different thread then the main program, and be able to see how it draws the tree?
Please do not judge me on this code, I just put it together fast, trying to make it work, this is not the way I code.
public class BinaryTree extends JPanel implements Runnable {
private int radius = 20;
private int vGap = 45, hGap = 150;
private int x = 350, y = 25;
private GraphNode root;
private BinarySearchTreeSort binaryTreeSort;
private int latency = 270;
private boolean isManual = false;
//Stores the sorting algorithm's instance
public BinaryTree(BinarySearchTreeSort binaryTreeSort) {
this.binaryTreeSort = binaryTreeSort;
}
#Override
public void run() {
//Maybe i should put here the paintComponent somehow???
root = binaryTreeSort.binaryTreeSort();
}
#Override
public void paintComponent(final Graphics g) {
displayTree(g, root, x, y, hGap);
}
private void displayTree(Graphics g, GraphNode root, int x, int y, int hGap) {
// Display the root
while (!isStarted) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(BinaryTreeFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
g.drawOval(x - radius, y - radius, 2 * radius, 2 * radius);
if (root.getValue() != 0) {
g.drawString(root.getValue() + "", x - 13, y + 4);
}
sleep();
if (root.getLeftChild() != null) {
// Draw a line to the left node
g.setColor(Color.black);
leftChild(g, x - hGap, y + vGap, x, y);
//Draw the left subtree
displayTree(g, root.getLeftChild(), x - hGap, y + vGap, hGap / 2);
}
if (root.getRightChild() != null) {
// Draw a line to the right node
g.setColor(Color.black);
rightChild(g, x + hGap, y + vGap, x, y);
// Draw the right subtree recursively
displayTree(g, root.getRightChild(), x + hGap, y + vGap, hGap / 2);
}
}
/* Draw left child */
private void leftChild(Graphics g, int x1, int y1, int x2, int y2) {
double d = Math.sqrt(vGap * vGap + (x2 - x1) * (x2 - x1));
int x11 = (int) (x1 + radius * (x2 - x1) / d);
int y11 = (int) (y1 - radius * vGap / d);
int x21 = (int) (x2 - radius * (x2 - x1) / d);
int y21 = (int) (y2 + radius * vGap / d);
g.drawLine(x11, y11, x21, y21);
//g.drawString("0", ((x21 + x11) - 20) / 2, (y21 + y11) / 2);
}
/*Draw right child */
private void rightChild(Graphics g, int x1, int y1, int x2, int y2) {
double d = Math.sqrt(vGap * vGap + (x2 - x1) * (x2 - x1));
int x11 = (int) (x1 - radius * (x1 - x2) / d);
int y11 = (int) (y1 - radius * vGap / d);
int x21 = (int) (x2 + radius * (x1 - x2) / d);
int y21 = (int) (y2 + radius * vGap / d);
g.drawLine(x11, y11, x21, y21);
//g.drawString("1", (x21 + x11) / 2, (y21 + y11) / 2);
}
public void sleep() {
if (!isManual) {
try {
Thread.sleep(latency);
} catch (InterruptedException ex) {
Logger.getLogger(BinaryTree.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

Line crosses Rectangle - how to find the cross points?

I'm drawing a rectangle onto a canvas and a line from the center of the rectangle to some random point in the coordinate space.
Now, I want to truncate the line by the length that is inside the rectangle so that the line starts at the rectangle edge.
How could I do this?
Example
The rectangle could be defined by 2 points: Pstart(1, 3), Pend(3,
1)
The center point can be computed to : P(2, 2)
Now draw the line from P(2, 2) to Q(10, 2).
As I know the width of the rectangle is 2, I could tell the line to start at P(4, 2) instead of P(2, 2).
This gets more complicated when the point is not parallel to one of the XY axis. Moreover the length inside the rectangle will be different amount for diagonal lines.
How can I calculate the start offset for the line point with respect to the center of the rectangle and the end point of the line?
Probably I'd have to find the point where the line would cross the rectangle, and then just let the line start at the cross point. But how could I get this point?
Honestly, I don't understand the maths, but...
Essentially, you have 5 lines. The original line and the 4 lines of the rectangle. So if you break it down to a simple line intersection of line problem it should become a little easier...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class IntersectPoint {
public static void main(String[] args) {
new IntersectPoint();
}
public IntersectPoint() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = (int) (getWidth() * 0.2f);
int y = (int) (getHeight() * 0.2f);
int width = (int) (getWidth() * 0.6f);
int height = (int) (getHeight() * 0.6f);
int x1 = x;
int y1 = 0;
int x2 = x + width;
int y2 = getHeight();
Line2D line = new Line2D.Double(x1, y1, x2, y2);
Rectangle2D rect = new Rectangle2D.Double(x, y, width, height);
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(rect);
g2d.draw(line);
g2d.setColor(Color.RED);
Point2D[] ps = getIntersectionPoint(line, rect);
for (Point2D p : ps) {
if (p != null) {
g2d.fill(new Ellipse2D.Double(p.getX() - 4, p.getY() - 4, 8, 8));
}
}
g2d.dispose();
}
public Point2D[] getIntersectionPoint(Line2D line, Rectangle2D rectangle) {
Point2D[] p = new Point2D[4];
// Top line
p[0] = getIntersectionPoint(line,
new Line2D.Double(
rectangle.getX(),
rectangle.getY(),
rectangle.getX() + rectangle.getWidth(),
rectangle.getY()));
// Bottom line
p[1] = getIntersectionPoint(line,
new Line2D.Double(
rectangle.getX(),
rectangle.getY() + rectangle.getHeight(),
rectangle.getX() + rectangle.getWidth(),
rectangle.getY() + rectangle.getHeight()));
// Left side...
p[2] = getIntersectionPoint(line,
new Line2D.Double(
rectangle.getX(),
rectangle.getY(),
rectangle.getX(),
rectangle.getY() + rectangle.getHeight()));
// Right side
p[3] = getIntersectionPoint(line,
new Line2D.Double(
rectangle.getX() + rectangle.getWidth(),
rectangle.getY(),
rectangle.getX() + rectangle.getWidth(),
rectangle.getY() + rectangle.getHeight()));
return p;
}
public Point2D getIntersectionPoint(Line2D lineA, Line2D lineB) {
double x1 = lineA.getX1();
double y1 = lineA.getY1();
double x2 = lineA.getX2();
double y2 = lineA.getY2();
double x3 = lineB.getX1();
double y3 = lineB.getY1();
double x4 = lineB.getX2();
double y4 = lineB.getY2();
Point2D p = null;
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (d != 0) {
double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
p = new Point2D.Double(xi, yi);
}
return p;
}
}
}
Look at Liang-Barsky algorithm used for line clipping by rectangle.
Vertices of the rectangle: a, b, c, d. Represent the x and y coord of each one like ax, ay, etc.
endpoints of the line: x, y
The line follows y = mx + b, and goes either up or down, right or left. That narrows down your possible rectangle edges for crossing to 2.
Use y = mx + b to determine the vertical coordinate at which it crosses the horizontal line, and the horizontal component at which it crosses the vertical line. Either only one of these will actually be on your rectangle (i.e., contained within one of the rectangle edges), or it will intersect at a corner.

Lines don't overlap when they should Java Swing

I'm drawing lines in a JFrame on a self made gridPanel.
Problem is, I draw the lines between 2 points. When I have a line that is between point 1 and point 2 and a line between point 2 and point 3, the lines should connect. This however isn,t the case, there is a small gap in between, no idea why. But it isn't drawing till the end of the specified point. (start point is correct.)
Here is the code of the JFrame:
public void initialize(){
this.setLayout(new BorderLayout());
this.setPreferredSize(new Dimension(500, 400));
gridPane = new GridPane();
gridPane.setBackground(Color.WHITE);
gridPane.setSize(this.getPreferredSize());
gridPane.setLocation(0, 0);
this.add(gridPane,BorderLayout.CENTER);
//createSampleLabyrinth();
drawWall(0,5,40,5); //These are the 2 lines that don't connect.
drawWall(40,5,80,5);
this.pack();
}
drawWall calls a method that calls a method in GridPane.
The relevant code in gridPane:
/**
* Draws a wall on this pane. With the starting point being x1, y1 and its end x2,y2.
* #param x1
* #param y1
* #param x2
* #param y2
*/
public void drawWall(int x1, int y1, int x2, int y2) {
Wall wall = new Wall(x1,y1,x2,y2, true);
wall.drawGraphic();
wall.setLocation(x1, y1);
wall.setSize(10000,10000);
this.add(wall, JLayeredPane.DEFAULT_LAYER);
this.repaint();
}
This method creates a wall and puts it in the Jframe.
The relevant code of the wall:
public class Wall extends JPanel {
private int x1;
private int x2;
private int y1;
private int y2;
private boolean black;
/**
* x1,y1 is the start point of the wall (line) end is x2,y2
*
* #param x1
* #param y1
* #param x2
* #param y2
*/
public Wall(int x1, int y1, int x2, int y2, boolean black) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.black = black;
setOpaque(false);
}
private static final long serialVersionUID = 1L;
public void drawGraphic() {
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if(black){
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(8));
} else {
g2.setColor(Color.YELLOW);
g2.setStroke(new BasicStroke(3));
}
g2.drawLine(x1, y1, x2, y2);
}
}
So, where am I going wrong? The true/false is to determine if the wall should be black or yellow, nothing to be concerned about.
You've set the main layout as BorderLayout using this.setLayout(new BorderLayout());
You then add the GridPane to the center position this.add(gridPane,BorderLayout.CENTER);
You then try and add the walls to the main layout using this.add(wall, JLayeredPane.DEFAULT_LAYER); ... But the main layout is a BorderLayout
This is going to cause you some issues
UPDATED
The other problem you have is in the Wall#paintComponent method.
You are drawing the lines offset from the x1 and y1 positions, but the component has already being positioned at this point.
The top, left corner of any component is always 0x0
The line g2.drawLine(x1, y1, x2, y2); should read more like...
int x = x2 - x1;
int y = y2 - y1;
g2.drawLine(0, 0, x, y);
UPDATED
You should also avoid setting the size of your components to some arbitary value (such 1000x1000) and rely more on the ability for your components to give you feedback...
public Dimension getPreferredSize() {
int width = Math.max(x1, x2) - Math.min(x1, x2);
int height = Math.max(y1, y2) - Math.min(y1, y2);
if (black) {
width += 8;
height += 8;
} else {
width += 3;
height += 3;
}
return new Dimension(width, height);
}
Then when adding the Wall, you can use wall.setSize(wall.getPreferredSize()) instead...

Categories