I currently have a program that makes a fractal tree. However, I would like to use the golden ratio in my fractal tree to get more interesting designs. I do not know exactly how to implement it with coordinates, especially with java since (0,0) is in the top left, which makes things a bit more confusing. You may ignore the parameters adder and length, they are not involved with this process. And excuse my ignorance on the matter, I am still trying to wrap my head around how exactly the Golden Ratio works. I have done some research but I really would like an answer in layman's terms.
public void paintComponent(Graphics g)
{
g.setColor(Color.RED);
draw(g, order, topX, topY,90,20, 200.00);
}
public void draw(Graphics g, int order, int x1, int y1, double angle, int adder, double length)
{
int x2, y2, x3, y3;
double newAngle = Math.toRadians(angle);
if (order == 1)
{
return;
}
else
{
x2 = (x1 - (int)Math.round(Math.cos(newAngle) * order * 10));
y2 = (y1 - (int)Math.round(Math.sin(newAngle) * order * 10));
g.drawLine(x1, y1, x2, y2);
draw(g, order-1, x2, y2, angle+30, adder+2, length+20);
draw(g, order-1, x2, y2, angle-30, adder+2, length+20);
}
}
This is what the current output is at an order of 10.
One approach to integrating the golden ratio into your code is to use it in the computation of branch length. Here, though you have a length parameter, it's unused. Instead, the length is computed as order * 10 such that the trunk is 100 long, and by the time order reaches 2, the leaves are 20 long.
If you use the length parameter, and recurse such that each successive branch order is 0.618034 the length of the ancestor one, you make a tree that has a longer trunk and core branches, and converges to a kind of broccoli-like detail at the leaves:
The other parameter you have control over is the angle, which you've set to 30 degrees. Below, I've converted your code over to Processing (it's basically Java, and easy to use for these kinds of things). You can paste this into http://www.openprocessing.org/sketch/create and run it in your browser to play around. Look how replacing the angle of 30 with uniform random number between 20 and 40 changes the tree. Keep clicking run to see different trees.
void setup()
{
size(1000,1000);
smooth();
stroke(0);
frameRate(30);
}
void go(int order, int x1, int y1, float angle, int adder, int length)
{
int x2, y2, x3, y3;
double newAngle = angle * PI / 180;
if (order == 1)
{
return;
}
else
{
x2 = (x1 - round(cos(newAngle) * length));
y2 = (y1 - round(sin(newAngle) * length));
line(x1, y1, x2, y2);
go(order-1, x2, y2, angle+random(20,40), adder+2, 0.618034 * length);
go(order-1, x2, y2, angle-random(20,40), adder+2, 0.618034 * length);
}
}
void draw()
{
stroke(255, 0, 0);
strokeWeight(1);
go(10, 500, 999, 90, 20, 100);
exit();
}
Here's an interesting, slightly off-balance tree generated by the above code:
Related
Im trying to create a slope in java. I can use the DrawLine function and it'll create a perfect one but I dont want to use that but rather create my own function for it. The problem is that it has gaps between the dots.
import java.applet.Applet;
import java.awt.Graphics;
public class slope extends Applet{
public void drawLine(int x1, int y1, int x2, int y2, Graphics g) {
double m = (y2 - y1) / (double)(x2-x1);
double y = y1;
for (int x =x1; x < x2; x++) {
drawPoint(x,(int)y,g);
y +=m;
}
}
public void paint(Graphics g) {
drawLine(20, 10, 300, 700, g); //has spaces between the dots
g.drawLine(20, 10, 300, 700); //this is perfect
}
private void drawPoint(int x, int y, Graphics g) {
g.drawLine(x, y, x, y);
}
}
Two loops: you loop over x++ only when deltaX > deltaY.
else you loop over y++ only.
Dual stepping x and y in the same loop, deciding which should be incremented (assuming you have x as a function of y too) could lead to slower drawing due to extra tests and adjacent pixels may look like a dot in the line. You'd need to play with color intensity to do antialiasing by hand (gold plating). Two loops is much simpler.
fyi, you are trying to generate an image, you could also just set ints in a matrix and make an offscreen raw image (BufferedImage and it's .setRGB() method), which you draw later. That would likely be faster and avoid visible painting delays.
Generally this is done by using an algorithm that doesn't step only along the x or y axis, but adjust the update increment by a variable amount, such that each dot is at most sqrt(2) away from each other.
So, if you think you have a point at the x value, but when you calculate it, you find that it is 3.5 pixels away (because the slope is very steep), you fall into a routine that calculates (typically recursively) an intermediate pixel between that x step
(x, y)
(0, 0) to (1, 5) distance 5.09
-> fill routine
(0, 0) to (0.5, 2.5) distance 2.69
-> fill routine
(0, 0) to (0.25, 1.25) distance 1.34 < 1.41
(0.25, 1.25) to (0.5, 2.5) distance 1.34 < 1.41
(0.5, 2.5) to (0.75, 3.75) distance 1.34 < 1.41
(0.75, 3.75) to (1, 5) distance 1.34 < 1.41
(1, 5) to (2, 10) etc...
The reason one uses 1.41 (sqrt(2)) as the maximum distance allowed is because a of pixels at a 45 degree angle from the bottom of the screen would still appear connected.
Now, in your plotting, you'll need to round the values to align to the exact pixels. There are a number of ways to do this. The simplest is just to round to the next valid value, and this works most of the time. It does have one unfortunate side effect, that is your line will appear to have jagged steps (where the rounding is moving the pixel more, the step will appear more jagged). This jaggedness is called "aliasing" as the true point is presenting through a non-true representation of the point (the alias).
A second approach is to alternatively darken both pixels proportionally, based on how close the point is. A point that is at (0.5) on the x axis would darken both pixels by 50% while a point that is at (0.25) would darken the 0 pixel by 75% and the 1 pixel by 25%. This is anti-aliasing, and may result in a line that is slightly more fuzzy, but appears to be straighter. This fuzziness can be somewhat combated by drawing a thicker line.
I hope this gives you some idea of the math behind many of the higher quality drawing routines, and certainly there are approaches that are even more sophisticated than the one I just presented.
Based on the Bresenham Algorithm, here is a java implementation that
assumes x2 > x1 and y2 > y1 and uses integer arithmetic
import java.applet.Applet;
import java.awt.*;
public class Slope extends Applet{
private int x1 = 20, y1 = 10;
private int x2 = 300, y2 = 700;
#Override
public void paint(Graphics g) {
drawLine(x1, y1, x2, y2, g);
//g.drawLine(x1, y1, x2, y2, g);
}
private void drawPoint(int x, int y, Graphics g) {
g.drawLine(x,y,x,y);
}
#Override
public void init(){
this.setSize(500,700);
}
private void drawLine(int x1,int y1,int x2,int y2,Graphics g){
int dx = x2 - x1;
int dy = y2 - y1;
int xi = 1;
int D = 2*dx - dy;
int x = x1;
for(int y = y1; y <y2; y++) {
drawPoint(x,y,g);
if(D > 0) {
x = x + xi;
D = D - 2 * dy;
}
D = D + 2 * dx;
}
}
}
I'm starting to think I'm just not able to see the obvious.
Given the following code, I would like to draw a line from the coordinates [x1, y1] to [x2, y2].
int x1 = 20;
int y1 = 10;
int x2 = 30;
int y2 = 5;
XSLFSlide pptSlide = ...
XSLFAutoShape shape = pptSlide.createAutoShape();
shape.setShapeType(ShapeType.LINE);
shape.setAnchor(x1, y1, <width>, <height>);
From what I can see the line starts at the anchor of [x1, y1] but then I have to enter a width and height instead of the coordinates of the target point. But the y component of the target coordinate is less than that if the start coordinate so I tried setting the height to a negative values, which results in an error when PowerPoint tries to open the generated PPTX document ("PowerPoint found a problem with content in the file out.pptx.");
I'm pretty sure I'm simply overlooking the obvious solution to this so can anybody help me in finding out how to draw a line for one point within the document to another point?
SetAnchor() takes an AWT Rectangle2D, which actually doesn't care if your width or height is negative (though a rectangle with negative height is not a real object after all, is it?). But POI doesn't interpret it that way, and unfortunately doesn't throw an exception to let you know.
As I understand your scenario, you just need to choose the lower starting coordinates between x1 and x2, y1 and y2 so that a positive width and height agree with your desired endpoint.
Something like this:
// using Apache POI ooxml 3.17
static void drawBetweenTwoPoints(XSLFAutoShape shape, double x1, double x2, double y1, double y2) {
shape.setAnchor(new Rectangle2D.Double(
x1 <= x2 ? x1 : x2, // choose the lowest x value
y1 <= y2 ? y1 : y2, // choose the lowest y value
Math.abs(x2 - x1), // get the actual width
Math.abs(y2 - y1) // get the actual height
));
shape.setFlipVertical(y2 < y1); // lines are drawn from rectangle top-left to
// bottom right by default.
// When y2 is less than y1, flip the shape.
}
I have a Image that I imported in a different class:
static ImageIcon grassSprite1 = new ImageIcon("Images/Sprite/grass.png");
static Image grass1 = grassSprite1.getImage();
What I want to do now is draw this Image on a JFrame that I created which would look something like this:
drawImages(Graphics g){
Graphics2D sprite = (Graphics2D) g;
sprite.drawImage(GetSpriteImage.grass1, posX1, posY1, null);
sprite.drawImage(GetSpriteImage.grass1, posX2, posY2, null);
sprite.drawImage(GetSpriteImage.grass1, posX3, posY3, null);
sprite.drawImage(GetSpriteImage.grass1, posX4, posY4, null);
//draw the Image alot of times on multiple coordinates
}
Is it possible to create a class that requests a dynamic number of parametres?
I'm looking for something like this:
//Pseudocode
MultipleImages{
public multipleImages(Image spriteImage, int int x1, int y1, int x2, int y2, ..., int xn, int yn){
for (i = 1, i < (number of x and y coordinates), i++){
drawImage(spriteImage, xi, yi)
//draws Image with coordinates
//x1, y1
//x2, y2
//...
//xn, yn
}
}
Which I can create a instance like this off:
multipleImages grass = new multipleImages(x1, y1, x2, y2, x3, y3, x4, y4, ..., xn, yn)
working with "n = any natual number".
You can have an int array as a parameter instead. This would allow you to get (practically) as many ints as you want.
public multipleImages(Image spriteImage, int[] coords) {
for (i = 0, i < coords.length, i+=2) {
drawImage(spriteImage, coords[i], coords[i+1]);
}
}
Although you should probably also check to make sure the array has an even number of elements and handle it otherwise.
Yes, it's possible to create methods(constructors too) with dynamic amount of parameters. Look here for Arbitrary Number of Arguments. You can achieve desired effect using such constructor:
public Points(Point... points)
{
//Use points as array.
points[0].x;
//...
}
Object of this class can be instantiated in that way:
Points points = new Points(new Point(0, 0), new Point(1, 1));
I'm using libGdx to create a 2d game and am trying to use this particular method to draw a simple 2d texture, specifying the 4 vertices induvidually;
draw(Texture texture, float[] spriteVertices, int offset, int length)
description says: Draws a rectangle using the given vertices. There must be 4 vertices, each made up of 5 elements in this order: x, y, color, u, v.
Other draw methods work fine, but I can't get this one to work. What im trying is this;
batch.draw(boxTexture, new float[] {-5, -5, 0, Color.toFloatBits(255, 0, 0, 255), 0, 0,
5, -5, 0, Color.toFloatBits(255, 255, 255, 255), 1, 0,
5, 5, 0, Color.toFloatBits(255, 255, 255, 255), 1, 1,
-5, 5, 0, Color.toFloatBits(255, 255, 255, 255), 0, 1}, 3, 3);
Im not very familiar with how OpenGL works, in particular what the offset and length should be. Does anyone more knowledgeable know how to get this working?
UPDATE:
It works using meshes, but then it turns out there was no transparency, which is annoying. In the end, I just added a custom method to SpriteBatch, just because its easier to get my head around. Vertices are drawn clockwise;
public void drawQuad (Texture texture, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float col) {
if (!drawing) throw new IllegalStateException("SpriteBatch.begin must be called before draw.");
if (texture != lastTexture) {
switchTexture(texture);
} else if (idx == vertices.length) //
renderMesh();
final float u = 0;
final float v = 1;
final float u2 = 1;
final float v2 = 0;
vertices[idx++] = x1;
vertices[idx++] = y1;
vertices[idx++] = col;
vertices[idx++] = u;
vertices[idx++] = v;
vertices[idx++] = x2;
vertices[idx++] = y2;
vertices[idx++] = col;
vertices[idx++] = u;
vertices[idx++] = v2;
vertices[idx++] = x3;
vertices[idx++] = y3;
vertices[idx++] = col;
vertices[idx++] = u2;
vertices[idx++] = v2;
vertices[idx++] = x4;
vertices[idx++] = y4;
vertices[idx++] = col;
vertices[idx++] = u2;
vertices[idx++] = v;
}
Offset is where in the array to start (for you 0), and length is how many indices the array needs to go through. For your case: 4 points, with 5 pieces of data for each point: 4*5 = 20.
Draw was never starting the render process because the value 3 floats isn't enough to make a triangle (15 is the minimum).
As for P.T.'s answer, this particular function does a fan render, so the correct ordering is either clockwise or counter-clockwise.
Also:
The order you put those points and textures in will render the texture upside-down (I don't know if that was intended.)
Offset and length are for taking a slice of the spriteVertices array. In your case they should be 0 and array.length (put the vertices in a local variable to compute length).
Also, I'm not sure its required, but I strongly suspect the vertices should be passed in a triangle-friendly way. You're currently doing a counter-clockwise enumeration. Generally for quads you should use a Z pattern like this:
3-4
\
1-2
(This is because OpenGL takes each set of 3 vertices in the list and renders the resulting triangle, so vertex 1,2,3 and 2,3,4 should both make useful triangles.)
3-4
\
1-2*
it's wrong, need to be like this:
4-3
1-2
The exercise I have is the following:
In display() add a method drawLine. Probably, you will need something like
drawLine(GL gl, int x1, int y1, int x2, int y2)
now using the equation of a line, plot the individual points that make up the line from x1,y1 to x2,y2 in JOGL
using (for instance) gl.glPointSize(1.0f); gl.glBegin(GL.GL_POINTS);
If you have coloured the points white, and used the following projections
gl.glViewport(-250, -150, 250, 150);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluOrtho2D(-250.0, 250.0, -150.0, 150.0);
then with a value of a line from points (0,0) to (100,100) yours will look
something like the following picture:
My code so far for the EventListener where I create my line is the following:
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
public class ThirdGLEventListener implements GLEventListener {
/**
* Interface to the GLU library.
*/
private GLU glu;
/**
* Take care of initialization here.
*/
public void init(GLAutoDrawable gld) {
GL gl = gld.getGL();
glu = new GLU();
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glViewport(-250, -150, 250, 150);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluOrtho2D(-250.0, 250.0, -150.0, 150.0);
}
/**
* Take care of drawing here.
*/
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
/*
* put your code here
*/
drawLine(gl, 0, 0, 100, 100);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
}
public void displayChanged(GLAutoDrawable drawable,
boolean modeChanged, boolean deviceChanged) {
}
private void drawLine(GL gl, int x1, int y1, int x2, int y2) {
gl.glPointSize(1.0f);
gl.glBegin(GL.GL_POINTS);
// This is where the whole problem lies.
gl.glEnd();//end drawing of points
}
}
My problem is that I don't quite know how to complete the code inside the method for the line equation. I would appreciate it if you could help me with that bit. I think the rest of it is just right, I just need to find how to implement the line equation inside the drawLine() method.
Thats how you do it in OpenGL.
glBegin(GL_POINTS);
for(float i = 0; i <= 100; ){
glVertex2f(i,i);
i+=0.01;
}
glEnd();
Also, a suggestion you want to have your Orthographic projections in GL_PROJECTION matrix and your modelview like the above code in GL_MODELVIEW
Edited play around with your +=0.01 and you will get the results BETTER WAY
glBegin(GL_LINES);
glVertex2i(0,0);
glVertex2i(100,100);
glEnd();
Try using GL_LINES:
private void drawLine(GL gl, int x1, int y1, int x2, int y2) {
gl.glPointSize(1.0f);
gl.glBegin(GL.GL_POINTS);
int samples = 100;
float dx = (x2 - x1) / (float)samples;
float dy = (y2 - y1) / (float)samples;
for( int i = 0; i < samples; i++ )
{
gl.glVertex2f( i * dx, i * dy );
}
gl.glEnd();//end drawing of points
}
Adjust samples to taste.