How To Mirror/Rotate a "fillArc" Drawing? - java

So, my situation is that I am drawing a lot of concentric circles, and to make this more efficient I am wanting to only draw 1/8 of the circle and then mirror/rotate the rest of the drawing. To be clear, let's say I have the following code:
for(int i = 0; i < end; i++) {
posX = calcX(i);
posY = calcY(i);
length = calcLength(i);
g2.fillArc(posX, posY, length, length, 0, 45);
}
// mirror/rotate 7 times...
Is this even possible? I know you can for an Image, but this seems a lot more tricky.
Thanks in advance for your help!
EDIT: g2 is a Graphics2D object.
EDIT 2: So, lets say I have the following slice. Is there a way to take this whole slide (drawn with "fillArc") and copy it 7 times and make a full circle:
EDIT 3: Fixed code to match what I'm saying.

I think g2 is a Graphics2D object?
Then you can use
g2.setTransformation();
And use a AffineTransformation to rotate the image. Altough it should be more efficient to use
g2.drawOval(...);
in order to draw circles.

Related

Issue drawing using graphics Java

I am trying to draw an Oval with a for loop iterating through a list of coordinates that each contain an x value and y value. Currently, it does not seem to be drawing anything after I start the program. It draws the first time, but when I try drawing when the program is running, it doesn't seem to be drawing.
Here is the code for drawing:
private void render(){
bs = display.getCanvas().getBufferStrategy();
if(bs == null){
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
//Draw Here!
DrawGrid(g);
g.fillOval(100, 100, 10, 10);//this seems to draw
for(int i = 0; i < points.size();i++){//this doesn't draw....
System.out.println(points.get(i));
g.drawString(points.get(i).toString(), points.get(i).x*100-5+100, points.get(i).y-5-300);
g.fillOval(points.get(i).x*100-5+100, points.get(i).y-5-300, 10, 10);
}
//End Drawing!
bs.show();
g.dispose();
}
If you need more details, I am using graphics from java.awt library. Also, I have done this in the past, but I don't know why it isn't working this time.
This part is your issue:
points.get(i).x*100-5+100
Specifically x*100
You are drawing off screen. We can see this by breaking it down:
Lets assume that you have a point of x=28.
Lets do the math on that:
For X = 28 you will have the following calc: (28 * 100) - (5 + 100) = 2695
That X point of 2695 looks very large to me. You would need a 4k screen or ultrawide screen to see it.
The solution:
Have a think about why you are using x*100, and reduce it so that the point fits on your screen. Also, if you have a small y point, then it will be in the negatives (Example: 15-5-300 = -290), and will probably draw above your screen and out of sight.

2D visibility with java grapics (Fog of War)

I am making a 2d game and i want to make 2d visibility. So my idea is to make the map and then mask it with another black (for example) polygon so that the player can see through the black polygon the map. So my idea is to draw some kind of a hole(polygon) trough the black polygon in order to see the map which is below the black polygon. I have already made the visibility but i have no idea how to make the mask.
This is what the program looks so far http://prntscr.com/7y36ev
but the problem is that if there are any objects in the dark they would still be rendered and the player could see them. I can shoot a ray and see if they are in line of sight but it would be a bit buggy because the rays will be shot in the center of the objects and if for example only their shoulder is showing up the object will not be rendered. Can somebody help ?
Edit - for anyone who wants to do the same
I made it with Path2D. First I make the outside polygon with Path2D, then make the inside polygon(the hole) and append the hole to the outside polygon. This is sample code:
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
Path2D.Double poly = new Path2D.Double();
Path2D.Double hole = new Path2D.Double();
hole.moveTo(40,40);
hole.lineTo(40,60);
hole.lineTo(60,60);
hole.lineTo(60,40);
hole.lineTo(40,40);
poly.moveTo(80,2);
poly.lineTo(80,80);
poly.lineTo(2,80);
poly.lineTo(2,2);
poly.lineTo(80,2);
poly.append(hole, true);
g2d.fill(poly);
}
Hi so far I understood your problem, you are intend to let each pixel of the map to be visible when the mask has a black pixel on the same position?
If I'm right then:
Get the BufferedImage of the Map and the BufferedImage of the Mask and using two for loops, check if Mask has black-Pixel at Position (X,Y) if so then add pixel of Map to a new BufferedImage to position (X,Y) otherwise add a black Pixel to the resulting BufferedImage at position (X,Y).
Edit:
Little bit Pseudo Code
BufferedImage mapBI = .... // the map as BufferedImage
BufferedImage maskBI = .... // the mask as BufferedImage
BufferedImage resultBI = ... // new BufferedImage with same size as mask
for (i=0; i< maskBI.width; i++){
for(j=0; j< maskBI.height; j++){
if (maskBI.pixelAt(i,j) == blackPixel){
resultBI.setPixel(i,j,mapBI.pixelAt(i,j));
}else{
resultBI.setPixel(i,j,blackPixel);
}
}
}
I hope you understand what I mean.

How to use Graphics2D g.scale() on only some things but not others?

I want to be able to zoom in my project, and it is working perfectly with a combination of g.scale(x, x) and g.translate(x, y). However, I want something to not scale with everything else (a minimap).
Specifically, I am making a minimap that will show the whole screen and the units as 1x1 pixels.
for(Unit u : units) { //cycle through arraylist of units
u.drawUnit(g, selectedUnits.contains(u)); //draws the unit, scales perfectly
g.setColor(Color.blue);
g.fillOval(rnd((u.getX()/4)/scale), rnd((u.getY()/4)/scale), rnd(1 + 1/scale), rnd(1 + 1/scale));
//rnd() is just a shorter (int)Math.round()
//The minimap's dimensions are width/4 x height/4
}
So i'm wondering if I can do it an easier way because that makes it look really strange at certain scalings.
You can get/set the AffineTransform object associated with the Graphics2D object. This allows you to readily switch back and forth between two or more transforms without having to do the math through the Graphics2D object's scale/translate/rotate methods. For example:
//render something default transform
AffineTransform defaultTransform = g.getTransform();
AffineTransform newTransform = new AffineTransform(defaultTransform);
newTransform.setScale(xScale, yScale);
g.setTransform(newTransform);
//render something with the new transform
g.setTransform(oldTransform);
//render something with the original transform

Plotting functions with using java GUI

I need to plot a polynomial given a start point and an end point. I've looked at using the paincomponent to do do it, but I'm getting confused because the origin is in the top left corner and I need my grid lines to be dynamic.
How do I make it so I can create a dynamic scale and what java class is best used for plotting a function?
For example if the user were to enter -2 2 x^2 the plotter would need to create a grid that goes from -2 has 0 in the middle and 2 on the right for the x coordinates. However if the user enters x^3 we have negative coordinates in the y plane and I'll need to slide the line containing the x coordinates up to accomidate.
Thanks!
The way I think you could do this(and I may be wrong) is to draw the y-line and x-line of your graph, and label the values for x and y using drawString at the correct position.
To illustrate this I did this example for you:
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Point2D.Double from = new Point2D.Double(300, 100);
Point2D.Double to = new Point2D.Double(300, 300);
Line2D.Double line = new Line2D.Double(from, to);
g2.draw(line);
Point2D.Double from2 = new Point2D.Double(150, 200);
Point2D.Double to2 = new Point2D.Double(450, 200);
Line2D.Double line2 = new Line2D.Double(from2, to2);
g2.draw(line2);
g2.drawString("-1", 290, 215);
}
The drawString method would draw "-1" below 0. So you could use the same thing to draw -2 below -1, etc.
I know this sounds inefficient, but it's the only way I can think of.
Hope someone else will have a better solution for you.
It shouldn't be too difficult to transform the y-coordinate if you know the size of area you want to paint to. But to be honest, why don't you use one of the plotting libs like JFreeChart, ...?

circle packing - java

I have a task to draw a circle and then fill in with the most amount of circles without touching the sides. I can draw the circle, and I can make loops to pack the circle in a hexagonal/honeycomb format, but can't control whether they are inside or outside the circle.
I have used this: g.drawOval(50, 50, 300, 300); to specify my circle. Given I'm actually specifying a square as my boundaries I can't actually determine where the circle boundaries are. So I'm basically packing the square full of circles rather than the circle full of circles.
Can some please point me in the right direction? I'm new to java so not sure if I have done this the complete wrong way. My code is below. I have another class for the frame and another with the main in it.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class DrawCircle extends JPanel
{
private int width, height, diameter;
public DrawFrame d;
public DrawCircle()
{
width = 400;
height = 400;
diameter = 300;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.blue);
g.drawOval(50, 50, 300, 300);
for(int i=50; i<200; i=i+20)
{
for(int j=50; j<350; j=j+10)
{
g.drawOval(j, i, 10, 10);
}
}
for(int i=60; i<200; i=i+20)
{
for(int j=55; j<350; j=j+10)
{
g.drawOval(j, i, 10, 10);
}
}
for(int i=330; i>190; i=i-20)
{
for(int j=340; j>40; j=j-10)
{
g.drawOval(j, i, 10, 10);
}
}
for(int i=340; i>190; i=i-20)
{
for(int j=345; j>40; j=j-10)
{
g.drawOval(j, i, 10, 10);
}
}
}
}
All those magic numbers make me cringe a bit. You're new to Java, and it's homework, so I understand why you're doing it, but I would not recommend it if you do much programming in the future.
You need an algorithm or recipe for deciding when a small circle on the inside falls outside the big one you're trying to pack. Think about the ways you might do this:
If the distance between the center of the big circle and the small circle is is greater than the difference in their radii, the small circle will overlap the big circle or fall completely outside it.
You can add this check to your code: Just before you draw the circle, perform this check. Only draw if that circle passes.
Don't worry about Java for a second; draw yourself a picture on a piece of paper, draw that enclosing and packed circle, and see if that statement is correct. Then think about any corner situations that it might not cover, just as a check.
I'll make two more recommendations. First, do this by hand without a computer once so you'll see what the "right" answer might look like. Second, see if you can separate the calculation of the circles from the drawing part. It might make your job easier, because you can concentrate on one thing at a time. It's called "decomposition". You solve complex problems by breaking them up into smaller, more manageable pieces. In this case, it's also called "model-view separation". You might need to know that someday.
Maybe another way to think about this problem would be to imagine a 2D arrangement of circles, packed in their closest arrangement, extending to infinity in both the x- and y-directions. Now take your enclosing circle, put it on top of the 2D arrangement, and eliminate all the circles that overlap the big circle. I don't know if it'll be optimal, but it's easy to visualize.

Categories

Resources