I need to stream a video from an IP cam over a java applet form preferably and then draw a rectangle over it and get the four coordinates. I can stream a video over an applet and I can draw a polygon, but separately. What I want to do is I need to draw the polygon while the video is streaming and the polygon should be translucent.
This is the code which I used to draw a polygon.
package IntelligentCameraApp;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class SimplePolygons extends Applet implements MouseListener {
/* Variables for implementing polygon input. */
private int[] xCoord, yCoord; // Arrays containing the points of
// the polygon. Up to 500 points
// are allowed.
private int pointCt; // The number of points that have been input.
private final static int polygonColor = Color.TRANSLUCENT;
// Color that is used to draw the polygons.
public void init() {
// Initialize the applet. The applet listens for mouse events.
// Arrays are created to hold the points.
setBackground(Color.white);
addMouseListener(this);
xCoord = new int[500];
yCoord = new int[500];
pointCt = 0;
}
public void paint(Graphics g) {
// The paint() routine does nothing but draw a 1-pixel black
// border around the applet. Polygons drawn on the applet
// are not permanent.
g.setColor(Color.black);
g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
} // end paint()
private void putLine(int x1, int y1, int x2, int y2) {
// Draw a line from (x1,y1) to (x2,y2) directly onto the
// applet, without going through the paint() method.
Graphics g = getGraphics();
g.drawLine(x1,y1,x2,y2);
g.dispose();
}
private void putPolygon() {
// Draw the polygon described by the arrays xCoord and yCoord
// and the integer pointCt. A filled polygon with a black
// outline is drawn. If pointCt is 0 or 1, nothing is drawn.
// If pointCt is 2, only a black line is drawn.
if (pointCt < 2)
return;
Graphics g = getGraphics();
if (pointCt == 2) {
g.drawLine(xCoord[0], yCoord[0], xCoord[1], yCoord[1]);
}
else {
//g.setColor(Color.red);
g.fillPolygon(xCoord, yCoord, pointCt);
g.drawPolygon(xCoord, yCoord, pointCt);
}
g.dispose();
}
public void mousePressed(MouseEvent evt) {
// Process a user mouse-click.
if (evt.isShiftDown()) {
// Clear the applet. (This only requires a repaint.)
// Also, set pointCt to zero to start a new polygon.
pointCt = 0;
repaint();
}
else if ( pointCt > 0 && (Math.abs(xCoord[0] - evt.getX()) <= 2)
&& (Math.abs(yCoord[0] - evt.getY()) <= 2) ) {
// User has clicked near the starting point.
// Draw the polygon and reset pointCt so that the
// user can start a new polygon.
putPolygon();
pointCt = 0;
}
else if (evt.isMetaDown() || pointCt == 500) {
// Draw the polygon and reset pointCt so that the
// user can start a new polygon.
putPolygon();
pointCt = 0;
}
else {
// Add the point where the user clicked to the list of
// points in the polygon, and draw a line between the
// previous point and the current point.
xCoord[pointCt] = evt.getX();
yCoord[pointCt] = evt.getY();
pointCt++;
if (pointCt >= 2) {
putLine(xCoord[pointCt-2], yCoord[pointCt-2],
xCoord[pointCt-1], yCoord[pointCt-1]);
}
}
} // end mousePressed()
public void mouseReleased(MouseEvent evt) { }
public void mouseClicked(MouseEvent evt) { }
public void mouseEntered(MouseEvent evt) { }
public void mouseExited(MouseEvent evt) { }
}
Oh boy... I had to many problems when I had mixed the paint with logic... My boss/client must explicitly ask for that to do logic in paint method.
I would like to suggest at least a LayeredPanel. And do stuff with IP camera in layer 1 and do rectangle, whatever you want in layer2.
Related
I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}
I am trying to change the y position of the rectangle, however, whenever I try to, it expands/gets bigger vertically.
public class PlayerPaddle implements Paddle {
double yVelocity;
final double GRAVITY = 0.94;
//move up/down faster (if not accelerating = slow down)
boolean upAccel, downAccel;
//determines if player 1 or player 2 (on left or on right)
int player;
//position of actual paddle
int x;
double y;
Rectangle panel;
public PlayerPaddle(int player) {
upAccel = false;
downAccel = false;
y = 210; //not moving initially
yVelocity = 0;
if (player == 1) {
//left side
x = 20;
} else {
//right side
x = 660;
}
}
#Override
public void draw(Graphics g) {
//draw paddle
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
}
#Override
public void move() {
if (upAccel) {
yVelocity -= 2;
} else if (downAccel) {
yVelocity += 2;
} else if ((!upAccel) && (!downAccel)) {
yVelocity *= GRAVITY;
}
y += yVelocity; //changes y position of paddle
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
#Override
public int getY() {
return (int) y;
}
}
I want to know how to make the rectangle move up and down vertically. A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding. But even when I say g.clearRect(...) it still expands and does not move.
I am new to Swing and Awt but I am really committed to learning. Thanks for the help.
A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding
And that is still probably the problem here.
Somewhere, not in the code presented here, you need to invoke the draw(...) method of this class.
So in that code you need to make sure the background of the component is cleared before you draw the paddle. Since you should be overriding the paintComponent(...) method of a panel to do custom painting your code should look something like:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw the paddle
}
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
I am new to Swing and Awt but I am really committed to learning.
Then keep a link to the tutorial handy for all Swing basics.
I am making a program which draws circles in the clicked place.
For the first click it draws circle which is not exactly in the same place I have clicked.
But furthermore, for other clicks it just draws circles one on the other. as i find out it is because the coordinates of click won't change.
my main:
public static void main(String[] args)
{
JFrame frame = new JFrame();
//set window size
frame.setSize(1000, 1000);
//set the title
frame.setTitle("Oval Draw");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add panel to frame and make it visible
MouseComponent component = new MouseComponent();
frame.add(component);
frame.setVisible(true);
}
and the MouseComponent class:
public class MouseComponent extends JPanel implements MouseListener
{
boolean drawPoint = true;
boolean drawLine = false;
boolean drawOval = false;
public MouseComponent()
{
super();
pointX = 0;
pointY = 0;
lineX = 0;
lineY = 0;
addMouseListener(this);
}
int pointX, pointY, lineX, lineY;
int[] ArrayX,ArrayY;
#Override
public void paintComponent(Graphics g)
{
for(int i=0; i<10; i++)
{
super.paintComponent(g);
if(drawLine)
{
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color startrandomColor = new Color(red, green, blue);
red = (int) (Math.random() * 255);
green = (int) (Math.random() * 255);
blue = (int) (Math.random() * 255);
Color endrandomColor = new Color(red, green, blue);
Graphics2D g2d = (Graphics2D) g;
// this.addMouseListener(this);
GradientPaint gradient = new GradientPaint(70, 70, startrandomColor,
150, 150, endrandomColor);
g2d.setPaint(gradient);
g2d.translate( lineX, lineY);
g2d.fillOval(70, 70, 100, 100);
System.out.print(lineX);
System.out.print(" ");
System.out.print(lineY);
System.out.print(" ");
System.out.print(pointX);
System.out.print(" ");
System.out.print(pointY);
System.out.print(" ");
// repaint();
}
else if(drawPoint)
{
// g.drawOval(pointX-5,pointY-5,10,10);
}
}
}
public void mouseClicked(MouseEvent mouse)
{
if(!drawPoint)
{
pointX = mouse.getX();
pointY = mouse.getY();
drawPoint = true;
}
else if(!drawLine)
{
lineX = mouse.getX();
lineY = mouse.getY();
drawLine = true;
}
repaint();
}
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
}
This here:
if(!drawPoint)
{
pointX = mouse.getX();
pointY = mouse.getY();
drawPoint = true;
}
simply doesn't make too much sense. You init drawPoint to true ... so you will never enter the if block and collect the click coordinates.
And beyond that: when you look into your other method --- the code to draw points is commented out.
Suggestion: step back; don't try to do 5 things at the same time. Write the code it takes to
fetch mouse coordinates after a click
draw circles around that coordinate
and get that to work. Forget about drawing lines, shapes, whatever for now.
And when you have a class that does nothing but that click+draw circles; then create a new class, where you add more features. Your "real" problem right now is that you started working on various features; and that your attempts to "integrate" them into a single class left you with something that is confusing, and not surprising ... not working!
Long story short: forgot about that strange logic that you have in your code right now to "toggle" between drawing points and lines. Draw points. And then, when that works ... add some radio buttons; or a drop down menu and use that to control if you want to draw lines or points. Don't make that "implicit" by toggling booleans in your event handler code!
boolean drawPoint = true;
boolean drawLine = false; cause it to print the first time. After that both are set to true so it will not change coordinates.
This is my second post on Mandelbrot fractal conversion from Java to C#.
As per my assignment, I need to Draw a mandelbrot fractal on a form, and once it is drawn, allow the user to Zoom in using the mouse, while also drawing a rectangle from the initial click point to the point where the click is released. This is the part of code which i believe is responsible for the rectangle.
private static void Swap<T>(ref T t1, ref T t2)
{
T temp = t1;
t1 = t2;
t2 = t1;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g1 = e.Graphics;
g1.DrawImage(bitmap, 0, 0, x1, y1);
if (action)
{
//g.setColor(Color.White);
if (xe < xs)
{
Swap(ref xs, ref xe);
}
if (ye < ys)
{
Swap(ref ys, ref ye);
}
g1.DrawRectangle(Pens.White, xs, ys, (xe - xs), (ye - ys));
//g1.Dispose();
}
}
//load method here
private void Form1_Load(object sender, EventArgs e)
//while loading
{
init();
start();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (action)
{
xe = e.X;
ye = e.Y;
}
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
action = true;
// e.consume();
if (action)
{
xs = xe = e.X;
ys = ye = e.Y;
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
using (Graphics g = this.CreateGraphics())
{
Pen pen = new Pen(Color.White);
g.DrawRectangle(pen, xs, ys, Math.Abs(xs - xe), Math.Abs(ys - ye));
}
int z, w;
if (xs > xe)
{
z = xs;
xs = xe;
xe = z;
}
if (ys > ye)
{
z = ys;
ys = ye;
ye = z;
}
w = (xe - xs);
z = (ye - ys);
if ((w < 2) && (z < 2)) initvalues();
else
{
if (((float)w > (float)z * xy)) ye = (int)((float)ys + (float)w / xy);
else xe = (int)((float)xs + (float)z * xy);
xende = xstart + xzoom * (double)xe;
yende = ystart + yzoom * (double)ye;
xstart += xzoom * (double)xs;
ystart += yzoom * (double)ys;
}
xzoom = (xende - xstart) / (double)x1;
yzoom = (yende - ystart) / (double)y1;
mandelbrot();
this.Invalidate();
}
What the code does is, draw a rectangle AFTER the dragging is done, and then zoom in with the drawn rectangle still being displayed. What I needed is the rectangle to draw as the mouse is being dragged.
I referred to this question, and solution mentioned there did not help.
Java to C# conversion. How do i draw a rectangle on my bitmap?
Any help would be appreciated.
Drawing the Rectangle
First of all, it appears that the Graphics.DrawRectangle method is unable to draw a rectangle with negative widths or heights. You will therefore have to write a method that will take two points and produce a rectangle meeting the requirements (positive width and height).
private Rectangle CreateRectangle(Point pt1, Point pt2)
{
// we use this method to create the rectangle with positive width and height
int x1 = Math.Min(pt1.X, pt2.X);
int y1 = Math.Min(pt1.Y, pt2.Y);
return new Rectangle(x1, y1, Math.Abs(pt1.X - pt2.X), Math.Abs(pt1.Y - pt2.Y));
}
Second, in your event handler for the MouseDown event, record the position at which the mouse was held down.
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
this.startPoint = e.Location;// record the start position
}
Next, modify your mouse move method to update the variable that holds current location of the mouse. Additionally, make it invalidate the form so that the image is redrawn (along with the rectangle).
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// record the current position as the end point if the left button is down
this.endPoint = e.Location;
// force a redraw
this.Invalidate();
}
}
In the form's Paint event handler, make your code call the CreateRectangle method with the start and end points of the rectangle in order to draw the rectangle on the form.
private void Form1_Paint(object sender, PaintEventArgs e)
{
// draw the cached Mandelbrot image
e.Graphics.DrawImage(mandelbrotCache, new Point(0, 0));
// draw the current rectangle
e.Graphics.DrawRectangle(rectPen, CreateRectangle(startPoint, endPoint));
}
Finally, in order to remove the rectangle when the mouse button is no longer pressed, set startPoint and endPoint to a value that gets drawn outside the image. This should be done in the MouseUp event handler.
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// setting the point to -1,-1 makes them get drawn off the screen
startPoint = new Point(-1, -1);
endPoint = new Point(-1, -1);
// force an update so that the rectangle disappears
this.Invalidate();
}
}
Addressing the Flickering Issue
In order to stop the form from flickering while you're drawing to it, you will need to enable double buffering on the form. This is done by setting the DoubleBuffered property of the form to true. You can do this anywhere, but I prefer to do it right after the form is created, as below:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// this reduces the flickering
this.DoubleBuffered = true;
}
}
Complete Code:
Here is the complete code for all the steps I detailed above. You can plug in your methods in order to have a working solution.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Point startPoint;
private Point endPoint;
private Image mandelbrotCache;
private Pen rectPen;
public Form1()
{
InitializeComponent();
// this reduces the flickering
this.DoubleBuffered = true;
// initialize a dummy image. Cache a copy of your Mandelbrot fractal here
mandelbrotCache = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
using (var g = Graphics.FromImage(mandelbrotCache))
{
var imgRect = new Rectangle(0, 0,
mandelbrotCache.Width,
mandelbrotCache.Height);
g.FillRectangle(new HatchBrush(HatchStyle.Cross, Color.DarkBlue,
Color.LightBlue), imgRect);
}
// this is the pen to draw the rectangle with
rectPen = new Pen(Color.Red, 3);
}
private Rectangle CreateRectangle(Point pt1, Point pt2)
{
// we use this method to create a rectangle with positive width and height
int x1 = Math.Min(pt1.X, pt2.X);
int y1 = Math.Min(pt1.Y, pt2.Y);
return new Rectangle(x1, y1, Math.Abs(pt1.X - pt2.X), Math.Abs(pt1.Y - pt2.Y));
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
this.startPoint = e.Location;// record the start position
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// record the current position as the end point if the left button is down
this.endPoint = e.Location;
// force a redraw
this.Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// setting the point to -1,-1 makes them get drawn off the screen
startPoint = new Point(-1, -1);
endPoint = new Point(-1, -1);
// force an update so that the rectangle disappears
this.Invalidate();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// draw the cached Mandelbrot image
e.Graphics.DrawImage(mandelbrotCache, new Point(0, 0));
// draw the current rectangle
e.Graphics.DrawRectangle(rectPen, CreateRectangle(startPoint, endPoint));
}
}
}
Here is a screenshot of a rectangle being drawn.
Note: The left mouse button is still held down. The rectangle disappears immediately the button is released.
i'm trying to implement a function to calculate the area of the polygon. this code allows you yo draw a polygon but when it comes to display the area, i am not sure how to do that. i tried in a couple ways but i am still a beginner at programming, so i'd appreciate any help. here is the code:
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.Polygon;
public class DrawPolygons extends JApplet implements ActionListener, MouseListener
{
private static final int NUMPOINTS = 500; //Up to 500 points can be chosen
private JButton finish; //Button to indicate user is done entering points
private Polygon shape; //polygon object to be drawn
private boolean isDrawn; //boolean flag for when the user is finished drawing
private int count; //how many points the user has clicked
private Color color; //color of the polygon after user finalizes points
private int[] x; //x coordinates of each point user picks
private int[] y; //y coordinates of each point user picks
private float sum;
private double area;
public void init() //set up GUI
{
setLayout(new FlowLayout());
addMouseListener(this); //adds MouseListener for mouse clicks
isDrawn = false; //isDrawn is initially false
count = 0; //count starts as 0
x = new int[NUMPOINTS]; //allows for up to 500 points to be chosen
y = new int[NUMPOINTS]; //allows for up to 500 points to be chosen
finish = new JButton("Finalize points"); //creates finish button
finish.addActionListener(this); //adds finish button to ActionListener
add(finish); //adds finish button to GUI
color = Color.BLACK; //color is intially black, and will remain
// so if user cancels the color chooser
//JOptionPane.showMessageDialog(null, "Click points that will make up the polygon. After each" +
// "point is entered, press the Finalize Points button");
shape = new Polygon(); //creates the Polygon shape
}
public void paint(Graphics g) //draws the Polylines, Polygons, and sets the color
{
super.paint(g);
g.drawPolyline(x, y, count); //draws the polyline specified by user
// mouseclick
g.setColor(color); //sets the color to the user chosen color
if(isDrawn) //if finalize button is clicked
{
g.fillPolygon(x, y, count); //finalizes polylines into
} // polygon and fills shape
}
public void actionPerformed(ActionEvent a) //decides what to do when finalize button is pressed
{
if(a.getSource() == finish) //if the finalize button is pressed
{
isDrawn = true; //isDrawn is set to true, ending the users ability
// to add more points, and fills the polygon
color = Color.red;
//JColorChooser.showDialog(this, "Choose a color", color); //color is set to users choice
repaint();
JOptionPane.showMessageDialog(null, "The area is ");
}
}
public void mouseClicked(MouseEvent e) //save coordinates of clicks
{
if(isDrawn == false && count < NUMPOINTS) //if the finalize button is not pressed
{ // the user can add additional points
x[count] = e.getX(); //adds the x point at the current mouse x coordinate
y[count] = e.getY(); //adds the y point at the current mouse y coordinate
count++; //count increases with each mouse click
repaint();
}
else if (e.isShiftDown()) {
// Clear the applet. (This only requires a repaint.)
// Also, set count to zero to start a new polygon.
count = 0;
isDrawn = false;
repaint();
}
}
private float getPolygonArea(int[] x, int[] y, int count)
{
float sum_but_no_result=0;
for(int i=0;i<(count-1);i++) // count is point number of polygon
{
sum_but_no_result+=x[i]*y[i+1] + y[i]*x[i+1];
}
sum_but_no_result+=x[count-1]*y[0] + y[count-1]*x[0];
float sum = (float)Math.abs(sum_but_no_result) / 2.0f;
return sum;
}
//Empty Implementation provided here so we can implement MouseListener (needed because we must
// provide concrete forms of all methods of an interface to implement it
public void mousePressed(MouseEvent e){};
public void mouseReleased(MouseEvent e){};
public void mouseEntered(MouseEvent e){};
public void mouseExited(MouseEvent e){};
}
float x[N],y[N]; // point coordinates as x1,y1 x2,y2 ....
...
...
...
...
float sum_but_no_result=0;
for(int i=0;i<(N-1);i++) // N is point number of polygon
{
sum_but_no_result+=x[i]*y[i+1] + y[i]*x[i+1];
}
sum_but_no_result+=x[N-1]*y[0] + y[N-1]*x[0];
float sum= (float)Math.abs(sum_but_no_result) / 2.0f;
http://www.mathopenref.com/coordpolygonarea.html
For self-intersecting polygons, you may add an intersection-coord-finder and polygon-adder algorithm to find all sub-polygons produced by intersecting, recursively.
In Kotlin, using an extension on java.awt.Polygon :
import java.awt.Polygon
fun Polygon.area(): Float {
var sum = 0f
for (i in 0 until npoints - 1) {
sum += xpoints[i] * ypoints[i + 1] + ypoints[i] * xpoints[i + 1]
}
sum += xpoints[npoints - 1] * ypoints[0] + ypoints[npoints - 1] * xpoints[0]
return sum / 2.0f
}