In an STL format this is what my current landscape looks like. And this is what the landscape is suppossed to look like. I think I know what the problem is, but I have no clue how to solve it.
I think I need to set the Z coordinate relative to other points around it so the whole landscape's Z coordinate isn't between 0 and 1 but they rather "add up".
Don't want a solution, just a hint in the right direction.
import java.io.*;
import java.util.Random;
class Point3D {
double x, y, z;
Point3D(double dx, double dy, double dz) {
x = dx;
y = dy;
z = dz;
}
Point3D middlePoint(Point3D p) {
Point3D m = new Point3D(0.0, 0.0, 0.0);
m.x = (this.x + p.x) / 2.0;
m.y = (this.y + p.y) / 2.0;
m.z = (this.z + p.z) / 2.0;
return m;
}
}
public class Aufgabe3 {
public static void recursion(Point3D p1, Point3D p2, Point3D p3, int n) {
if (n > 0) {
if (n == 1) {
System.out.println(" facet normal 0.0 0.0 0.0");
System.out.println(" outer loop");
System.out.println(" vertex " + p1.x + " " + p1.y + " " + p1.z);
System.out.println(" vertex " + p2.x + " " + p2.y + " " + p2.z);
System.out.println(" vertex " + p3.x + " " + p3.y + " " + p3.z);
System.out.println(" endloop");
System.out.println(" endfacet");
}
Random r = new Random();
Point3D a = p1.middlePoint(p2);
Point3D b = p3.middlePoint(p1);
Point3D c = p2.middlePoint(p3);
long seedA = (long) ((p1.x + p1.y + p1.z + p2.x + p2.y + p2.z) * 1000000);
r.setSeed(seedA);
a.z = r.nextDouble() / 10;
long seedB = (long) ((p3.x + p3.y + p3.z + p1.x + p1.y + p1.z) * 1000000);
r.setSeed(seedB);
b.z = r.nextDouble() / 10;
long seedC = (long) ((p2.x + p2.y + p2.z + p3.x + p3.y + p3.z) * 1000000);
r.setSeed(seedC);
c.z = r.nextDouble() / 10;
recursion(p1, a, b, n-1);
recursion(a, p2, c, n-1);
recursion(b, c, p3, n-1);
recursion(a, b, c, n-1);
}
}
public static void main(String args[]) throws FileNotFoundException {
int n;
try {
n = Integer.parseInt(args[0]);
}
catch (Exception e) {
n = 7;
}
System.out.println("Aufgabe 3: Landschaftsgenerator");
System.out.println("n = " + n);
Random r = new Random();
Point3D p1 = new Point3D(0.8, -1.2, 0.0);
Point3D p2 = new Point3D(1.0, 1.3, 0.0);
Point3D p3 = new Point3D(-1.0, 0.0, 0.0);
System.setOut(new PrintStream(new FileOutputStream("Aufgabe3.stl")));
System.out.println("solid Aufgabe3");
recursion(p1, p2, p3, n);
System.out.println("endsolid");
}
}
The problem is the frequency distribution of the displacements you're adding. Displacements to a fractal landscape have to follow a 1/(f^b) distribution, otherwise you get random noise.
In this case, no matter what the scale of subdivision, you're adding the same vertical displacement, which is going to result in a landscape dominated by the highest frequency. Formally, a fractal surface is one that has a 'fractional' or 'fractal' geometric dimension, higher than the topological dimension of the surface, but lower than that of the embedding space. For instance, for a 2D surface being displaced in the 3rd dimension, the fractal dimension should be between 2 and 3.
For subdivision and displacement, the fractal dimension is related to beta as follows:
Dim = (7 - b)/2
With fractal behaviour therefore occurring between b = 1 and b = 3, and the random displacements follow this profile:
displacement = k * rand / (f^b)
This means that if you divide your triangle in half each time, you have to at least halve the displacement, or you'll end up with a noise surface rather than a fractal one. The best choice for a landscape is typically somewhere around b = 2.
Reference: https://fractal-landscapes.co.uk/maths.html
Related
I am currently working on a 3D-library including quaternions. As every expert, I coded my methods based on what I found on Wikipedia and it doesn't work quite right.
This is the method for calculating the product between two quaternions:
public static Quaternion product(Quaternion a, Quaternion b) {
return a.clone().multiply(b);
}
And here is its implementation:
public Quaternion multiply(Quaternion q) {
float rx = q.getX(), ry = q.getY(), rz = q.getZ(), rw = q.getW();
this.w = w*rw - x*rx - y*ry - z*rz;
this.x = w*rx + x*rw + y*rz - z*ry;
this.y = w*ry - x*rz + y*rw + z*rx;
this.z = w*rz + x*ry - y*rx + z*rw;
return this;
}
And here is a small test that I wrote:
Quaternion a = Quaternion.create(1, 1, 1, Spatium.DEG_TO_RAD * 15);
Quaternion b = Quaternion.create(1, 1, 1, Spatium.DEG_TO_RAD * 15);
Quaternion c = Quaternion.product(a, b);
System.out.println(a + " * " + b + " = " + c);
Note that the create() method initializes quaternions with x, y, z, w.
Unfortunately, the tests yields results that don't make any sense despite my amazing skills of copying and pasting Wikipedia formulas:
(0.2617994 + 1.0i + 1.0j + 1.0k) * (0.2617994 + 1.0i + 1.0j + 1.0k) = (-2.931461 + -2.6696618i + 1.0j + -6.3393235k)
For comparison, Wolfram solves it correctly and returns -2.93146 + 0.523599i + 0.523599j + 0.523599k.
Here's the formulas I so skillfully copied from Wikipedia:
I don't really have anything to say other than please help me, Wikipedia couldn't.
I think you should store the current values of x, y, z and w in a temp variable before updating it with new values.
public Quaternion multiply(Quaternion q) {
float rx = q.getX(), ry = q.getY(), rz = q.getZ(), rw = q.getW();
float cx = x; // cx = current X
float cy = y;
float cz = z;
float cw = w;
this.w = cw*rw - cx*rx - cy*ry - cz*rz;
this.x = cw*rx + cx*rw + cy*rz - cz*ry;
this.y = cw*ry - cx*rz + cy*rw + cz*rx;
this.z = cw*rz + cx*ry - cy*rx + cz*rw;
return this;
}
In your code, when you use this.w = w*rw - x*rx - y*ry - z*rz;, you are overridind the current value of w, and the next 3 operations will be affected by this changes.
I'm having some trouble with the my cartesian slope calculations in Java.
So my sourcecode lets you input 4 numbers, x1 y1 x2 y2, which represent 2 coordinates of 2 points in an cartesian coordinate system.
then i calculate the slope by calculating deltaX and deltaY.
so i use a double for the slope end calculation (deltaY / deltaX) in case you get a tenth of a number.
then i use an IF function to say: if slope = 0 --> println("not a linear line"). else calculate the cross point of the X and Y polars and println the result
So here is the problem: what if the slope is 0 (example x1:0 y1:1 x2:0 y2:9) then the i get an error: Exception in thread main java.lang.ArithmeticException: / by zero
here is the full script:
import java.io.*;
public class Cartesian
{
public static int leesIn(String var, BufferedReader in) throws IOException
{
System.out.println("type een getal in die " + var + " moet voorstellen.");
return Integer.parseInt(in.readLine());
}
public static void main(String[] args) throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int x1, x2, y1, y2;
x1 = leesIn("X1", in);
y1 = leesIn("Y1", in);
x2 = leesIn("X2", in);
y2 = leesIn("Y2", in);
System.out.println("The Coördinates of point 1 is: (" + x1 + ", " + y1 + "). The Coördinates of point 2 is: (" + x2 + ", " + y2 + ").");
int deltaY = y2 - y1;
int deltaX = x2 - x1;
double RC = deltaY / deltaX;
if ((RC) == 0)
{
System.out.println("The slope is 0, no linear line.");
}else
{
System.out.println("The slope is: " + RC);
double B = y1-(RC*x1);
System.out.println("The crosspoint with Y, if x is 0, : " + B);
}
}
}
anyone an idea how to fix my problem? tnx in advance!
You should move calculation into area where you are sure that it can be calculated (in your case double RC = deltaY / deltaX;
So your code will be:
int deltaY = y2 - y1;
int deltaX = x2 - x1;
if (deltaY == 0)
{
System.out.println("The slope is 0, no linear line.");
}else if (deltaX == 0)
{
System.out.println("Not a Linear Line");
}else
{
double RC = (double) deltaY / deltaX;
System.out.println("The slope is: " + RC);
double B = y1-(RC*x1);
System.out.println("The crosspoint with Y, if x is 0, : " + B);
}
Make a try catch block
double RC;
try{
RC = deltaY / deltaX;
}
catch(ArithmeticException ex){
System.out.println("Not a Linear Line");
}
try this
try {
double RC = deltaY / deltaX;
if ((RC) == 0)
{
System.out.println("The slope is 0, no linear line.");
}else
{
System.out.println("The slope is: " + RC);
double B = y1-(RC*x1);
System.out.println("The crosspoint with Y, if x is 0, : " + B);
}
} catch(ArithmeticException ae) {
System.out.println("Not a linear line");
}
The purpose of the method is to take in a Point (c), then move the current centroid (x,y) to the new coordinated provided. This is done through finding the difference of the two and then translating the point to the new coordinate. However, I do not know how to set the new centroid value since I am setting the methods as voids.... Any ideas?
Sorry for all of the code, tried to put as little as possible. Translate takes the point(x,y) and adds the values given (dx,dy).
private Point centroid;
Triangle(Point a, Point b, Point c) {
this.a = a;
this.b = b;
this.c = c;
triPoints = new Point[] { a, b, c };
}
public Point getCentroid() {
Point centroid;
double x = 0.0;
double y = 0.0;
x = (a.getX() + b.getX() + c.getX()) / 3;
y = (a.getY() + b.getY() + c.getY()) / 3;
centroid = new Point(x, y);
return centroid;
}
public void move(double dx, double dy) {
centroid = getCentroid();
System.out.println(centroid.getX() + " "+ centroid.getY());
centroid = centroid.translate(dx, dy);
Point newCentroid = new Point(centroid.getX(),centroid.getY());
System.out.println(newCentroid.getX() + " "+ newCentroid.getY());
if(getCentroid().equals(newCentroid)){
}else{
}
for (int index = 0; index < triPoints.length - 1; index++) {
triPoints[index].translate(dx, dy);
}
}
public void move(Point c) {
double firstx = 0.0;
double firsty = 0.0;
Point f = getCentroid();
System.out.println(f.getX()+ " "+ f.getY() + " "+ c.getX()+ " "+ c.getY());
if (f.getX() >= c.getX()) {
firstx = c.getX() - f.getX();}
else{
firstx = Math.abs(f.getX() - c.getX());
}
if (f.getY()>= c.getY()){
firsty = c.getY() - f.getY();
}
else {
firsty = Math.abs(f.getY() -c.getY());
}
move(firstx, firsty);
//System.out.println(centroid.getX() + " " + centroid.getY());
}
I am assuming you are using java.awt.Point?
If so, centroid.translate(dx, dy) is a void method: no value is actually returned, so
centroid =centroid.translate(dx, dy)
does not actually do anything.
Since you are just wanting a new centroid, try doing
centroid = getCentroid();
System.out.println(centroid.getX() + " "+ centroid.getY());
Point newCentroid = new Point(centroid.getX() + dx,centroid.getY() + dy);
System.out.println(newCentroid.getX() + " "+ newCentroid.getY());
There is no need to do the translate if all you want to do once you translate is make a new centroid.
Also, neither the translate function nor the constructor take a double (which makes sense if you are on a standard x,y graph), so you can make dx and dy int.
I'm working on some exercises and I've been stuck on this for some hours now (quite new to Java).
Anyhow, this is what I'm supposed to do:
When I run the program I will have a square in the middle of the screen and when I then click somewhere within that screen another square will be drawn at the place where I clicked and in-between these two points there are supposed to be 10 squares. So wherever I click there should always be 10 squares drawn between.
However, I can't make it to function properly.
This is what I've managed to do so far:
import se.lth.cs.ptdc.window.SimpleWindow;
import se.lth.cs.ptdc.square.Square;
public class PrintSquares2 {
public static void main(String[] args) {
SimpleWindow w = new SimpleWindow(600, 600, "PrintSquares2");
int posX = 300;
int posY = 300;
int loop = 0;
System.out.println("Skriv rotation");
Square sq1 = new Square(posX,posY,200);
sq1.draw(w);
w.waitForMouseClick();
int destX = w.getMouseX();
int destY = w.getMouseY();
System.out.println("Dest X: " + destX + " Dest Y: " + destY);
System.out.println("Pos X: " + posX + " Pos Y: " + posY);
SimpleWindow.delay(10);
//sq1.erase(w);
int jumpX = (destX - posX) / 10;
int jumpY = (destY - posY) / 10;
System.out.println(jumpX);
while (posX < destX)
{
posX = posX+10;
SimpleWindow.delay(100);
loop++;
System.out.println("Loop: " + loop);
System.out.println("Dest X: " + destX + " Dest Y: " + destY);
System.out.println("Pos X: " + posX + " Pos Y: " + posY);
Square sq2 = new Square(posX,posY,200);
sq2.draw(w);
}
while (posX > destX)
{
posX = posX-10;
SimpleWindow.delay(100);
loop++;
System.out.println("Loop: " + loop);
System.out.println("Dest X: " + destX + " Dest Y: " + destY);
System.out.println("Pos X: " + posX + " Pos Y: " + posY);
sq1.draw(w);
Square sq2 = new Square(posX,posY,200);
sq2.draw(w);
}
while (posY < destY)
{
posY = posY+10;
SimpleWindow.delay(100);
loop++;
System.out.println("Loop: " + loop);
System.out.println("Dest X: " + destX + " Dest Y: " + destY);
System.out.println("Pos X: " + posX + " Pos Y: " + posY);
sq1.draw(w);
Square sq2 = new Square(posX,posY,200);
sq2.draw(w);
}
while (posY > destY)
{
posY = posY-10;
SimpleWindow.delay(100);
loop++;
System.out.println("Loop: " + loop);
System.out.println("Dest X: " + destX + " Dest Y: " + destY);
System.out.println("Pos X: " + posX + " Pos Y: " + posY);
sq1.draw(w);
Square sq2 = new Square(posX,posY,200);
sq2.draw(w);
}
SimpleWindow.delay(10);
sq1.draw(w);
//SimpleWindow.clear(w);
}
}
I'm pretty sure that I overcomplicated everything since this should be pretty basic.
The end result is supposed to look like this:
End result
This is the way I'd have solved it:
I didn't quite understand the documentation on se.lth.cs.ptdc.square.Square but I'll assume it draws a square given the coordinates of its top-left corner and a side size.
So you have the coodinates of your first square's left-top corner and the coordinates of the last square's center. Having that it's not difficult to get the coords of the last square's top-left corner:
lastX = centerX - side/2
lastY = centerY - side/2
After you have that you find the difference between the starting and ending points:
diffX = posX - lastX
diffY = posY - lastY
and after that just draw 9 more squares:
for (int i=1; i<10; i++){
squareX = posX + (diffX/10)*i;
squareY = posY + (diffY/10)*i;
Square square = new Square(squareX,squareY,200);
square.draw(w);
}
Actually you did the first part right, just messed up with those unnecessary checks. Hope it helps.
--
Regards, svz.
Update both X and Y at the SAME time :
int jumpX = (destX - posX) / 10;
int jumpY = (destY - posY) / 10;
if (posX > destX) {
int temp = destX;
destX = posX;
posX = temp;
}
while (posX <= destX)
{
SimpleWindow.delay(100);
loop++;
System.out.println("Loop: " + loop);
System.out.println("Dest X: " + destX + " Dest Y: " + destY);
System.out.println("Pos X: " + posX + " Pos Y: " + posY);
Square sq2 = new Square(posX,posY,200);
sq2.draw(w);
posX = posX+jumpX;
posY = posY+jumpY;
}
SimpleWindow.delay(10);
sq1.draw(w);
Here's how you move in two directions at once (on a diagonal).
static final int Steps = 10;
private void test() {
int x1 = 100;
int y1 = 100;
int x2 = 300;
int y2 = 500;
double dx = (double)(x2 - x1) / (double) Steps;
double dy = (double)(y2 - y1) / (double) Steps;
double x = x1;
double y = x2;
for ( int i = 0; i < Steps; i++) {
// Simulate the drawing of the square.
System.out.println("("+x+","+y+")");
x += dx;
y += dy;
}
}
I created 5 circles with random x and y coordinates and radii using 3 arrays (for x, y and radius size). However, I need the circles to dynamically change color based on whether or not they overlap with another circle. So if one of the 5 circles doesn't overlap at all, it should be colored black. Overlapping circles should be cyan. Two circles are considered to overlap if the distance between their center points is less than the sum of their radii.
This is what I have written so far for the circles class.
The following code will successfully draw the 5 circles in an applet window, and the distances are successfully calculated, but the problem is with the coloring. There's seems to be a logic error in the color filling and I don't see the problem here. Any suggestions? Thank you so much.
public class Circles extends Applet {
public void paint(Graphics page)
{
Random locator = new Random();
int [] xpt = new int [5];
int [] ypt = new int [5];
int [] rad = new int [5];
setPreferredSize (new Dimension(300, 300));
for (int i = 0; i < xpt.length; i++){
xpt[i] = locator.nextInt(100); //need to set a number or it goes into millions, cannot set it in Random()
ypt[i] = locator.nextInt(100);
rad[i] = locator.nextInt(100);
System.out.println("The #" + i + " x-point: " + xpt[i] + " y-point: " + ypt[i] + " radius: " + rad[i]); //for debugging purposes
for (int j = 0; j < xpt.length; j++){
double xpoint1 = xpt[i]+rad[i];
double ypoint1 = ypt[i]+rad[i];
double xpoint2 = xpt[j]+rad[j];
double ypoint2 = ypt[j]+rad[j];
double radius1 = rad[i];
double radius2 = rad[j];
double theDistance = distance(xpoint1,ypoint1,xpoint2,ypoint2);
System.out.println("Comparing " + i + " to " + j); //for debugging and logic checking
if (i==j)
;
else if (theDistance <= (radius1+radius2))
{
page.setColor(Color.cyan);
page.fillOval(xpt[i], ypt[i], rad[i], rad[i]);
//page.fillOval(xpt[j], ypt[j], rad[j], rad[j]);
System.out.println("Overlap occurred. Colored " + i + " and " + j + " cyan.");
System.out.println("Center points: ("+ xpoint1 +", "+ ypoint1 +") and ("+ xpoint2 + ", "+ ypoint2 + ").");
}
else
{
page.setColor(Color.black);
page.fillOval(xpt[i], ypt[i], rad[i], rad[i]);
//page.fillOval(xpt[j], ypt[j], rad[j], rad[j]);
System.out.println("No overlap. Made " + i + " and " + j + " black.");
}
}
}
}
public static double distance(
double x1, double y1, double x2, double y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
}
The xpoint, ypoint, etc. lines are not doing what you think.
If you want to find if two circles are overlapping, you need to find if the distance between the centers of the circles is greater or less than the sum of their radii.
So:
function circlesCollide(x1, y1, r1, x2, y2, r2){
return (distance(x1, y1, x2, y2) <= (r1 + r2));
}
Why do you +rad[] here? You don't have to add the radius for comparing the distance.
double xpoint1 = xpt[i]+rad[i];
double ypoint1 = ypt[i]+rad[i];
double xpoint2 = xpt[j]+rad[j];
double ypoint2 = ypt[j]+rad[j];
[...]
double theDistance = distance(xpoint1,ypoint1,xpoint2,ypoint2);
[...]
page.fillOval(xpt[i], ypt[i], rad[i], rad[i]);
You should use xpt / ypt for the distance. not xpoint1, and use - for value and 2 * radius for size ...... i.e.:
double xpoint1 = xpt[i]-rad[i];
double ypoint1 = ypt[i]-rad[i];
double xpoint2 = xpt[j]-rad[j];
double ypoint2 = ypt[j]-rad[j];
[...]
double theDistance = distance(xpt[i],ypt[i],xpt[j],ypt[j]);
[...]
page.fillOval(xpoint1 , ypoint1, 2*rad[i], 2*rad[i]);