drawing shapes on a grid - java

I need to draw random shapes on a grid such as lines squares etc. This part I'm able to do. My problem is the start and end point of the lines I'm drawing falls anywhere in a grid cell. I would like them to be only at intersection points. One cell in the grid is a 10x10 pixel grid. Do i have to write an algorithm to assign the pixel to its nearest intersection point on the grid or is there a easier way. I'm using a buffered image to draw the grid. Please Help. this is what i have so far
for (int i = 0; i < 61; i++) {
g2d.drawLine((imgDim.width + 2) / 40 * i, 0,
(imgDim.width + 2) / 40 * i, imgDim.height - 1);
g2d.drawLine(0, (imgDim.height + 2) / 60 * i,
imgDim.width - 1, (imgDim.height + 2) / 60 * i);
}
Thank you

How are you coming up with the random points? Making an adjustment there might be the easiest way. That is, just drop a 0 in the process you are using to come up with the points in the first place. Then when you are ready to draw it, add a 0 back.

Seriously? In order to make a random point (pixelX, pixelY) snap to the closest point of a grid.
int gridSize = 10;
int x = (pixelX + gridSize / 2) / gridSize * gridSize;
int y = (pixelY + gridSize / 2) / gridSize * gridSize;

Related

Speed up Simplex Noise

I want to make a Java program, in which moving sky is generated out of Simplex Noise, but I have performance issues (framerate is too low). I'm using https://github.com/KdotJPG/OpenSimplex2/blob/master/java/OpenSimplex2F.java noise class.
My function which generates the sky, generates it entirely again each frame:
private void generate() {
float y = offset;
for (int i = 0; i < frame.getHeight(); i++) {
float x = offset;
for (int j = 0; j < frame.getWidth(); j++) {
double a = noise.noise2(x, y) + 0.25f * noise.noise2(2 * x, 2 * y) + 0.125f * noise.noise2(4 * x, 4 * y);
a = a / (1 + 0.25 + 0.125);
a = (a + 1) / 2;
a *= 100;
Color color = Color.getHSBColor(220f / 360f, a / 100f, 1f);
background.setRGB(j, i, color.getRGB());
x += noiseResolution;
}
y += noiseResolution;
}
}
Where background is BufferedImage I'm drawing on and offset says how much noise is moved.
I have tried to save an array of pixels of background each frame and translate it by the number of pixels it should be moved, and then I generated only pixels that are new. Unfortunately, because it was rendered too fast then, the number of pixels it should be moved was e.g. 0.2, so I couldn't translate array indices by a fraction.
So I guess the only way is to somehow generate it in another way, but I totally have no idea how.
Thanks!
Not sure about Java, but in C++ with DirectX, OpenGL or any low level interface like that, this should be easily done on the GPU in either HLSL (DirectX), or GLSL (OpenGL). I implemented 5D Simplex noise and even zoomed in so it fills my large screen, and on my 9 year old computer with my old ho-hum graphics card it still does a couple hundred frames per second. Here's what it looks like.
https://www.youtube.com/watch?v=oRO1IGcWIwg
If you can run a fragment shader from Java, I would think that would be the way to go. I think there is some OpenGL interface in Java so you might want to look int that.

How to build a Triangle-based Grid in Java using Swing?

How to build a Triangle-based Grid in Java using Swing.
Context:
I've been searching this for quite a while;
I've seen many questions throughout my search of the internet.
How to Draw Triangles in Java
How do I draw a Triangle in Java
However, as you can see; a majority of them only focus on one Triangle. I am attempting to make a Grid.
The Problem:
Below is a screenshot of my current predicament. I have successfully made row's of triangles however, I have clearly done something wrong. The spacing between row's are offset.
First off, I Apologies for how dark this image is. As you can see, each row contains four Triangles. You can just about see the "Rows"between the Yellow and Green Triangles.
(I apologies for the link, This is my first question, I do not have the ability to post embedded imagery)
The Code Snippet
I apologies in advanced this code looks poorly written.
This is the code I've come up with thus far, for making a Triangle Grid.
for (int x = 0; x < board.width; x++) {
for (int y = 0; y < board.height; y++) {
int numberOfSides = 3;
double sideLength = cellSize;
if(y%2==0) {
if(x%2==0) {
Polygon triA = new Polygon();
for (int i = 0; i < numberOfSides; i++) {
triA.addPoint(
(int) ((cellSize) + (cellSize * x)
+ sideLength * Math.sin(i * 2 * Math.PI / numberOfSides)),
(int) ((cellSize) + (cellSize * y)
+ sideLength * Math.cos(i * 2 * Math.PI / numberOfSides))
);
}
g.setColor(Color.GREEN);
g.drawPolygon(triA);
} else {
Polygon triA = new Polygon();
for (int i = 0; i < numberOfSides; i++) {
triA.addPoint(
(int) ((cellSize) + (cellSize * x)
- sideLength * Math.sin(i * 2 * Math.PI / numberOfSides)),
(int) ((cellSize+sideLength/2) + (cellSize * y)
- sideLength * Math.cos(i * 2 * Math.PI / numberOfSides))
);
}
g.setColor(Color.RED);
g.drawPolygon(triA);
} else {
if(x%2==0) {
Polygon triA = new Polygon();
for (int i = 0; i < numberOfSides; i++) {
triA.addPoint(
(int) ((cellSize) + (cellSize * x)
- sideLength * Math.sin(i * 2 * Math.PI / numberOfSides)),
(int) ((cellSize+cellSize) + (cellSize * y)
- sideLength * Math.cos(i * 2 * Math.PI / numberOfSides))
);
}
g.setColor(Color.YELLOW);
g.drawPolygon(triA);
} else {
Polygon triA = new Polygon();
for (int i = 0; i < numberOfSides; i++) {
triA.addPoint(
(int) ((cellSize) + (cellSize * x)
+ sideLength * Math.sin(i * 2 * Math.PI / numberOfSides)),
(int) ((cellSize+cellSize/2) + (cellSize * y)
+ sideLength * Math.cos(i * 2 * Math.PI / numberOfSides))
);
}
g.setColor(Color.BLUE);
g.drawPolygon(triA);
}
}
The Obvious Issues
So, the main issue thus far is the Size and Spacing of Triangles. My code is obviously not the best in the world and I'm sure there are some much simpler solutions. This image below is what I am trying to replicate:
Here is my end Goal.
I do not wish to make a small grid like this image, but using the same rules for the rows, I would like to make a Triangle Grid which fills an entire board. In this scenario, we can assume this is either a JPanel or JFrame.
The Purpose of this goal?
Once again, I wish to apologies for the vagueness of this question.
I am trying to build a Triangle Grid for some research I am doing into Cellular Automata. The code snippet I have provided was once fashioned from a Hexagon Grid Generation Method I built. I changed the numberOfSides variable to three and adjusted the sideLength variable to try and remove spacing. This is where my problem has occured.
For those interested, here is a link to a blog by a Computer Scientist into Triangular Cellular Automata. I wish to replicate their results one day.
Triangular Game of Life
End Note
I would greatly appreciate some guidance on how to build a Triangle Grid. I'm sure there are some much more accurate methods such as using DrawLine. I would also appreciate some feedback on my question. This is my first question on Stackoverflow, after using the website for quite some time.
I will try my best to monitor this post throughout the day if anyone has any questions for me.
A Polygon can be reused in painting so you only need to create 2 Polygons, one with the triangle pointed up and the other with the triangle pointed down.
Then when you do your painting you use the Graphic.translate(...) method to position the Polygon. Or another option is to create a custom class containing 3 properties:
Polygon
Point where the Polygon is painted
Color of the polygon
Then you add each cell to an ArrayList. In the painting code you then just iterate through the ArrayList to paint each cell. The advantage of this approach is that you are not doing all the calculations every time the panel needs to be repainted.
The spacing between row's are offset.
Once you have the Shape you want to paint, you can use the getBounds() method of the Shape. Then:
for horizontal position you would use the width / 2
for vertical position you would use the height.
In this scenario, we can assume this is either a JPanel or JFrame.
It would never be a JFrame. Custom painting is done by overriding paintComponent() of a JPanel (or JComponent). Then you add the panel to the frame.
I'm sure there are some much simpler solutions.
Not necessarily simpler, but you may want to check out Playing With Shapes for a reusable class that allows you to create some interesting shapes. It also allows you to rotate a given Shape.

Drawing odd no. of rectangle for rows and columns

I am trying to draw 5 (for example) rectangles on canvas, using GC.drawRectangle(int x, int y, int width, int height);
After forth column rectangle should be drawn in next row as shown in the picture.Picture, layout for the rectangles drawn. I am not able to find some logic to draw rectangles as desired.
Here is what I was trying to do.
int col = (brushPanz-1) / 4;//gives column
int row = (brushPanz-1) % 4;//gives rows
for (int i = 0; i < brushPanz; i++) {
GC.drawRectangle((i * 172 + 5), col * 78 + 5, 500 / ratio, 220 / ratio);
}
Basically I want to use only one for loop to draw any number of rectangles. Someone, please help.
Without trying to debug your position offsets versus your size, you need (a) to compute a new row/col for each rect, (b) to use those computed values to position your rect and (c) to correctly compute row vs. column.
for (int i = 0; i < brushPanz; i++) {
int col = i % 4;//gives column
int row = i / 4;//gives rows
GC.drawRectangle((col * 172 + 5), row * 78 + 5, 500 / ratio, 220 / ratio);
}

"Snap" to int values for width/height when resizing JFrame

I have a JFrame that contains a custom JComponent that displays a grid with a fix amount of rows and columns. When the JFrame is resized, the spacing between lines is recalculated so that the grid increases in size while still keeping the same amount of elements. The issue comes when resizing to a height or width that is to large to fit n columns (or rows) but too small to fit n+1. Here's the correct view:
You can see the blue lines perfectly align with the black line on the right. If I increase the width of the window, I get the following problem:
The grid extends JComponent, and in its paintComponent I do the following:
// Get the size of the JFrame containing the Grid
Dimension df = getParent().getSize();
// Calculate spacing between vertical lines (20 = number of vertical lines)
int vert_spacing = (df.width - 2 * this.margin) / 20;
// Draw the black border
g.setColor(Color.BLACK);
g.drawRect(this.margin, this.margin, df.width - 2 * this.margin, df.height - 2 * this.margin);
// Draw vertical lines
for (int i = this.margin; i <= df.width - this.margin; i += vert_spacing) {
g.setColor(Color.blue);
g.drawLine(i, this.margin, i, df.height - this.margin);
}
A solution I thought of would be to "snap" to a good value after the JFrame is resized, but I haven't been able to get that to work and I'm not sure if it's the best solution. The issue is with the fact that drawLine takes ints as its values so the spacing between lines gets rounded up/down. Is there a workaround for this?
Thanks!
I think the problem is that you are painting the rectangle too large. You need to take into account that the rectangle size should be based on the vertical spacing * 20 and not the actual size of the parent window.
Maybe something like:
int vert_spacing = (df.width - 2 * this.margin) / 20;
int extraSpace = df.width - (vert_spacing * 20);
// Draw the black border
g.setColor(Color.BLACK);
g.drawRect(this.margin, this.margin, (df.width - extraSpace) - 2 * this.margin, df.height - 2 * this.margin);
Now of course the above solution will be skewed to the left so you may also want to center your grid in the space available. So in addition to using your margin as the X offset you would need to use half of the extra space:
int vert_spacing = (df.width - 2 * this.margin) / 20;
int extraSpace = df.width - (vert_spacing * 20);
int xOffset = extraSpace / 2;
// Draw the black border
g.setColor(Color.BLACK);
g.drawRect(this.margin + xOffset, this.margin, (df.width - extraSpace) - 2 * this.margin, df.height - 2 * this.margin);
Of course you would also need to use the xOffset when drawing the vertical lines.
You should work with floating coordinates and then round them just in order to get the integers required by the "draw" function:
// Calculate spacing between vertical lines (20 = number of vertical lines)
float vert_spacing = (float)(df.width - 2 * this.margin) / 20f;
// Draw vertical lines
for (int i=0; i<20; i++) {
int x = Math.round(this.margin + i*vert_spacing);
g.setColor(Color.blue);
g.drawLine(x, this.margin, x, df.height - this.margin);
}

Dividing a range up evenly, allowing for spaces and margins

I have a point array and a panel. getWidth() is based off the panel. Imagine cards in your hand, so HAND_CARD_WIDTH is pretty self explanatory. The purpose of this loop is to set the points evenly across the panel, which it does. However, it allow the cards to go out of the panel, which makes it look very bad. What I want to do is give a small empty margin on both sides of the panel no matter how many cards you have in your hand.
Here's the code
int iteration = 1;
int limiter = getWidth();
int slice = (limiter/(handsize+1));
while (points.size() < handsize) {
int x = slice*(iteration++);
x -= HAND_CARD_WIDTH/2;
points.add(new Point(x, y));
}
Basically I want the leftmost x to be at least 20 and the rightmost to be at most getWidth() - 20 - HAND_CARD_WIDTH. I also want the cards to be evenly spaced... I just can't think of the right equation (getting to this point was sadly a feat..).
Thanks, based on the responses (all 2 of them) heres what I went with:
if((int)points.get(0).getX() < margin){
int boost = Math.abs(margin - (int)points.get(0).getX());
slice = (boost*2)/handsize;
for(Point p : points){
p.x += boost;
boost -= slice;
}
}
Not sure if I understand your layout, but I think it is something like this:
|margin|space|card|space|card|space|margin|
or
|margin|space|card|space|margin|
So, the number of spaces is one more than number of cards and the total width is component width minus margins. componentWidth = numCards x cardWidth + (numCards + 1) x spaceWidth Now it is easy to calculate the space needed which is (componentWidth - numCards x cardWidth) / (numCards + 1) so the left position of a card is leftMargin + spaceWidth x cardNum + cardWidth x (cardNum - 1)
Care must be taken when the space is negative, then you instead must calculate how much the cards must overlap.
Try this:
final int MARGIN = 20;
int availableWidth = getWidth() - 2 * MARGIN - HAND_CARD_WIDTH;
int cardSpaceWidth = availableWidth / handsize;
for (int i = 0; i < handsize; i++) {
int x = MARGIN + ((i + 0.5) * cardSpaceWidth) - HAND_CARD_WIDTH / 2;
points.add(new Point(x, y));
}
So:
calculate the available width by subtracting the margins from total panel width
calculate the space for each card by dividing remaining space by number of cards
for each card, we count its leftmost point by taking the middle of card space and subtracting half the width of the card.
Mind you, with this solution cards still can overlap margins, if HAND_CARD_WIDTH is greater than available space for card.

Categories

Resources