Draw points as ovals using java swing - java

I have a point with [x, y] coordinate, for example
Point p = new Point(1, 2). I want to visualize it. However, I want this point to an oval, like in the picture below.
How can I do that using java Swing?

Determine the size of the oval you want, for example 10 px. Then draw the oval with the x and y points starting at the Point (x and y), minus half the size. Something like:
public class PointsPanel extends JPanel {
List<Point> points = new ArrayList<Point>();
int size = 10;
...
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point p : points) {
int x = p.x - size/2;
int y = p.y - size/2;
g.drawOval(x, y, size, size);
}
}
}
For more general details on painting, see Performing Custom Painting. Also see the Graphics API for other drawXxx and fillXxx methods.

From the image you posted, what you need is a graph layout library like JUNG(not sure about current status of this project). You can follow peeskillet's answer but need to take care of problems like overlapping ovals etc.

Related

How to merge 2D rectangles into larger polygons [Java]

I have a 2D polygon that only has lines that are perfectly horizontal or perfectly verticle. There are 2 other posts relating to this. However, one is merging multiple rectangles at once into a polygon, and the other is written in javascript.
I would like to take a rectangle of any size and add it to an existing 2D Polygon. Some examples are below.
In the diagram, each box represents 1 pixel. The navy boxes are the points that data exists for and the red and green boxes show how these points are connected. The points of both the red polygon and the green rectangle are held in a linked list (the order of points is what determines what point connects to what). Red and Green boxes don't exist in memory, they're used here only to show connections.
A point is defined as having an x and y coordinate.
How would I go about merging the green rectangle into the red polygon?
I really appreciate any help given thanks!
Edit: Here is some code that draws these shapes:
public class Core
{
private static Polygon polygon = new Polygon();
private static Rectangle rect = new Rectangle();
public static void main(String args[])
{
new Core();
}
public Core()
{
polygon = new Polygon(new int[] {0,12,12,24,24,32,32,12,12,5,5,0},new int[] {0,0,4,4,-3,-3,13,13,15,15,8,8},12);
rect = new Rectangle(18,14,7,6);
Draw2D drawing = new Draw2D();
drawing.setVisible(true);
}
public class Draw2D extends JFrame
{
private static final long serialVersionUID = -1033542824627245527L;
public Draw2D()
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(new DrawPane(), BorderLayout.CENTER);
pack();
}
}
class DrawPane extends JComponent
{
private static final long serialVersionUID = 5457330297413941626L;
public DrawPane() {
setPreferredSize(new Dimension(1280,720));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setBackground(Color.black);
g2.clearRect(0,0,1280,720);
g2.translate(getWidth() / 2, getHeight() / 2);
g2.setColor(Color.white);
g2.setStroke(new BasicStroke(0.001f));
g2.draw(polygon);
g2.draw(rect);
}
}
}
Edit 2:
A partial solution that I have is to inflate the rectangle by pushing each side out by 1 pixel/box, then checking if the entire side is inside one of the red polygon lines. By inside I mean collinear. A green rectangle side is sitting inside one of the red polygon sides.
If it does sit inside then leave the points there, if not move them back to where they originally were. Repeat this clockwise until all 4 sides have ha their points moved or not. Duplicate point objects that reference the same point as a point object that already exists will be deleted so that only 1 point object references 1 point.
This is only part of a solution as this method doesn't work when a rectangle is added on the edge of a polygon (shown in the first image, 2nd and 3rd examples from the top down).
You can simplify your problem by separating it in different parts. So the issue is based on lines.
Horizontal case
1.
R1------R2
xxxxxx (overlaps)
G1------------G2
2.
R1----------R2
xxxxxxx (overlaps)
G1------------G2
3.
R1---------------R2
no overlapping
G1-----G2
...
distance: abs(R_y1 - G_y1)
range of overlap: x1 = max(R_x1,G_x1), x2 = min(R_x2,G_x2),
if (distance <= 1 && x1-x2 > 0) {
// both lines are neighbours and has a valid overlapping range
}
Vertical case
Analogous to horizontal
As your boxes are stored in linked lists, you iterate both boxes and calculate distance and range of overlap.
List<Line> greenBox; // {Line((28,30),(60,30)) , Line((60,30),(60,50)), ...
List<Line> redBox; // ...
for (Line r : redBox) {
for (Line g : greenBox) {
if (distance(r,g) <= 1 && rangeOfOverlap(r,g) > 0) {
// both lines matches and can be merged over the range of overlaps
merge(r,g);
}
}
}
This is just an example to inspire you. You'll need to check if the picked green and red line are both horizontal or both vertical.
The complexity of the algorhythm would be around at m^n (without merging) where n is the number of green lines and m is the number of red lines.
lol

Java Graphics 2d avoid Polyline distorted corners

i'm working on a graphic interface for drawing subway maps. A line is represented with station as circles and a polyline to link them.You can move the stations with a mouseDrag and of course it updates the displaying map in real time. My problem is when stations comes to a certain angle, there is a polyline distortion and the corner created by the 2 lines is out of the station circle display, i'd like to know if there is a way to avoid this.
screenshots of the app with the polyline issue
here's my code for the polyline's draw
//x and y point array creation
xPoints = new int[this.stationViews.size()];
yPoints = new int[this.stationViews.size()];
for (int i=0;i<this.stationViews.size();i++) {
//fill arrays with the center point of circles representing stations
xPoints[i] = this.stationViews.get(i).getStation().getPosX()-this.stationViews.size()/2;
yPoints[i] = this.stationViews.get(i).getStation().getPosY()-this.stationViews.size();
}
//setting color
g2D.setColor(this.line.getColor());
//set stroke width relative to the zoom level
int strokeWidth=5;
if(!this.stationViews.isEmpty()) {
if (this.stationViews.get(0).getStationSize()>14) {
strokeWidth = this.stationViews.get(0).getStationSize()-13;
}else {
strokeWidth = 3;
}
}
g2D.setStroke(new BasicStroke(strokeWidth));
//draw the polyline
if (this.stationViews.size() >1) {
g2D.drawPolyline(xPoints, yPoints, this.stationViews.size());
}
//draw the station (g2D.drawCircle)
for (StationView stationView : stationViews) {
stationView.affiche(g2D,this.line.getColor());
}
thank you for your help
That is called the miter. You seem to be per default using JOIN_MITER, sharp joining of extended lines at the end, which can point far out of the join for small angles.
g2d.setStroke(new BasicStroke(strokeWidth,
BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 5));
miter a surface forming the beveled end or edge of a piece where a joint is made by cutting two pieces at an angle and fitting them together.
It is also a bishop's cap with a pointy top, hence the name.

Offset between click detection and button graphics in libgdx

I have a libgdx application that contains a class Button. The constructor of Button takes three arguements: Filename of graphics, position, and game (the latter being used for callbacks of various sorts).
The button scales itself based on the graphics provided, thus setting its width and height based on the properties of the graphics.
The main class, Game, when a click is detected compares the coordinates of the click up against the coordinates of the button combined with its width and height.
Now, the main issue is that there is a little bit of a horizontal offset between the button and the click coordinates, so the effect is that the graphics show up a few pixels to the right of the clickable area. I cannot for the life of me figure out the source of this discrepancy, so I would greatly appreciate some fresh eyes to see where I'm going wrong here.
Button, constructor and polling-method for clickable area.
public Rectangle getClickArea() {
return new Rectangle(pos.x - (img.getWidth() / 2), pos.y + (img.getHeight() / 2), w, h);
}
public Button(String assetfile, int x, int y, Game game) {
this.game = game;
img = new Pixmap(new FileHandle(assetfile));
pos = new Vector2(x, y);
this.w = img.getWidth();
this.h = img.getHeight();
}
A relevant snippet from InputHandler. It listens for input and passes on the event. Please note that the vertical click position is subtracted from the vertical size of the screen, as vertical 0 is opposite in InputHandler:
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
tracker.click(screenX, Settings.windowSize_Y - screenY);
return false;
}
ClickTracker (referenced as tracker in the above snippet), the Class that does the actual comparison between clicks and clickables:
public void click(int x, int y) {
Vector2 clickPos = new Vector2(x, y);
for (Tickable c : world.getPaintables())
{
if (!(c instanceof Unit))
continue;
if (((Clickable)c).getClickArea().contains(clickPos)) {
System.out.println("Clicked on unit");
}
}
for (Clickable c : clickables)
{
if (c.getClickArea().contains(clickPos)) {
c.clicked(x, y);
}
}
In short: The vertical alignment works as intended, but the horizontal is slightly off. The button graphics appear maybe around 10-20 pixels to the right of the clickable area.
I'll gladly post more info or code if needed, but I believe I have the relevant parts covered.
Edit:
As Maciej Dziuban requested, here's the snipped that draws the UI elements. batch is a SpriteBatch as provided by libgdx:
for (Paintable p : ui) {
batch.draw(new Texture(p.getImg()), p.getImgPos().x, p.getImgPos().y);
}
the getImgPos() is an interface method implemented by all drawable items:
public Vector2 getImgPos() {
return new Vector2(pos.x - (getImg().getWidth() / 2), pos.y);
}
It's worth noting that half of the horizontal image size is subtracted from the X pos, as X pos refers to the bottom center.
You have inconsistency in your position transformations:
Your clickArea's corner is pos translated by [-width/2, height/2] vector.
Your drawArea's corner is pos translated by [-width/2, 0] vector
They clearly should be the same, so if you want your pos to represent bottom-center of your entity (as you've explicitly stated) you have to change your getClickArea() method to, so it matches getImgPos().
public Rectangle getClickArea() {
return new Rectangle(pos.x - (img.getWidth() / 2), pos.y, w, h);
}
Side note: as Tenfour04 noticed, you create new texture each frame and this is huge memory leak. You should make it a field initialized in constructor or even a static variable given some buttons share the texture. Don't forget to call dispose() on resources. For more powerful asset management check out this article (note it may be an overkill in small projects).

How to add an image to an already drawn box using LWJGL & Slick2D

I am creating a simple 2D game for my computer class. I already have a box that moves around through a level. But, i want to change this box to instead display a stickman standing that I drew. Then, more specifically, i would like in my MovementInput class (where i assign movements to the buttons), I want when neither A(my moving left button) or D(my moving right button) OR when both A and D are held down to display this standing.png image. How would i go about doing this?!
This is my code for drawing the box
public class Man extends AbstractMoveableEntity {
public Man(double x, double y, double width, double height) {
super(x, y, width, height);
}
#Override
public void draw() {
glColor3d(0, 0, 255);
glRectd(x - width / 2, y, x + width / 2, y + height);
}
}
And in my MovementInput class, this is my code for the A&D thing
if ((Keyboard.isKeyDown(Keyboard.KEY_D) &&Keyboard.isKeyDown(Keyboard.KEY_A))||(!Keyboard.isKeyDown(Keyboard.KEY_D) && !Keyboard.isKeyDown(Keyboard.KEY_A))) {
man.setDX(0);
}
Use something called Texture Atlases for multiple frames of animation and a simple timer to loop through the frames. ThinMatrix on YouTube has a really good tutorial for this here as well as many other concepts.

How to draw a two dimensional graphic at Java?

I have 2 different lists. Each of them holds x and y value pairs(they have both positive and negative values). How can I draw them on a 2D axis? I want to put points for every value and they will blue for first list and red for second list.
My lists' type:
List<List<Double>>
List<Double> inside of List<...> has 2 variables, first of it for x value and the second one is for y value.
However just I need to how to draw a two dimensional graphic at Java(desktop application) and put points wherever I want, improving code for my variables is less important.
PS:
I want the more and more simple of that kind of graphic:
Something like:
you could use a library like http://www.jfree.org/jfreechart/ (LGPL-License) there are lots of examples around the web, and it's quite easy to use.
here's an example, that seems to match your requirements:
http://www.java2s.com/Code/Java/Chart/JFreeChartMarkerDemo1.htm
Assuming you are using Swing with a panel, you can use the following:
public class JImagePanelExample extends JPanel {
private BufferedImage image;
private Graphics2D drawingBoard;
private int x, y; // Image position in the panel
// Let's assume image is a chart and you need to draw lines
public JImagePanelExample(BufferedImage image, int x, int y) {
super();
this.image = image;
// Retrieving a mean to draw lines
drawingBoard = image.createGraphics();
// Draw what you need to draw (see other methods too)
drawingBoard.drawLine(0, 10, 35, 55);
}
// Called by Swing to draw the image in the panel
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, null);
}
}
If you don't want to use Swing and you just need to draw in 2D, focus on BufferedImage and Graphics2D only.
There is a Java 2D API: http://java.sun.com/products/java-media/2D/ and many charting libraries easily found with a web search.

Categories