Ich schreibe ein Java-Programm, um das Mandelbrot-Set für meine einleitende Programmierklasse anzuzeigen. Ich glaube, ich habe die ganze Mathematik richtig eingerichtet, aber wenn ich versuche, das Fraktal zu zeichnen, bekomme ich nur eine feste Farbe. Ich habe die Mathematik getestet und es scheint, dass es funktionieren sollte. Ich habe über eine Stunde gesucht, aber ich habe nichts gefunden, was geholfen hat. Hier sind meine Klassen für komplexe Zahlen und tatsächlich die Mandelbrot-Menge zu erstellen: Komplexe ZahlenVerwenden eines BufferedImage zum Zeichnen der Mandelbrot-Set, nur eine durchgehende Farbe
public class ComplexNum {
//Instance Fields
private double realNum; //the real number portion of the complex number
private double imgNum; //the imaginary number portion of the complex number
//NOTE TO SELF: i = sqrt(-1); i^2 = -1; i^3 = -i; i^4 = 1; then the cycle starts over.
//Constructor
/**Creates a complex number of form x+yi, where x and y are both of type double; x represents the real number piece of the
* complex number, while y represents the imaginary piece.
* @param realPart -- the double value which is the real piece of the complex number
* (Precondition: realPart is a real number of type double)
* @param imaginaryPart -- the double value which represents the imaginary piece of the complex number
* (Precondition: imaginaryPart is a real number of type double)
*/
public ComplexNum(double realPart, double imaginaryPart){
realNum = realPart;
imgNum = imaginaryPart;
}
/**Add two complex numbers by taking the sum of their real and imaginary pieces.
* (Postcondition: returns the sum of two complex numbers)
* @param comNum -- the complex number that is to be added together with this one
* (Precondition: both the complex number you are calling this method on and comNum must have been initialized)
* @return the sum of two complex numbers
*/
public ComplexNum add(ComplexNum comNum){
return new ComplexNum(realNum+comNum.getRealPart(), imgNum+comNum.getImgPart());
}
/**Square the complex number and returns the result.
* (Precondition: the complex number must have been initialized)
* @return the squared value of the complex number
*/
public ComplexNum squareComplex(){
double realPiece = realNum*realNum; //this is a normal number
double imaginaryPiece = (realNum*imgNum)+(imgNum*realNum); //each section in parenthesis has an i attached to it, allowing both sections to be added together
double iSquaredPiece = imgNum*imgNum; //this now has an i^2
//The form that the complex number currently: a + b(i) + c(i^2), where b is actually x(i)+y(i) simplified.
//since i^2 is -1, the iSquaredPiece is actually a real number. Multiply the value by -1, then add it to a,
//and the true real number piece of the complex number is created.
realPiece = realPiece + (iSquaredPiece*-1);
return new ComplexNum(realPiece, imaginaryPiece);
}
/**Allows the real piece of a complex number to be extracted.
* (Precondition: the complex number must have been initialized)
* @return the value of the real number piece of the complex number
*/
public double getRealPart(){
return realNum;
}
/**Allows the imaginary piece of a complex number to be extracted.
* (Precondition: the complex number must have been initialized)
* @return the value of the imaginary number piece of the complex number
*/
public double getImgPart(){
return imgNum;
}
Mandelbrots
public class MandelbrotGenerator {
//Constants
/**The maximum number of times the Mandelbrot calculations will be run on a specific point. If the real and imaginary pieces
* from each calculation don't exceed 2 within the maximum number of iterations, they are part of the Mandelbrot set.
*/
public static final int MAX_ITERATIONS = 30; //The maximum number of times the calculations will be run on a specific point.
private final double MIN_X = -2.0; //The minimum value of x when graphing the Mandelbrot set
private final double MAX_Y = 2.0; //The maximum value of y when graphing the Mandelbrot set
private final double MANDEL_X_RANGE = 4.0; //The range of x values from -2 to 2 when graphing the Mandelbrot set
private final double MANDEL_Y_RANGE = 4.0; //The range of y values from -2 to 2 when graphing the Mandelbrot set
//Instance Fields
private ComplexNum z; //In the Mandelbrot equation of Z_(n+1)=Z_n^2+C, this is the value of Z_n^2
private ComplexNum c; //In the Mandelbrot equation of Z_(n+1)=Z_n^2+C, this is the value of C
private ComplexNum currentCalc; //In the Mandelbrot equation of Z_(n+1)=Z_n^2+C, this is the value of Z_(n+1)
private int numIterations; //The current number of iterations
//Constructor
/**Create a MandelbrotGenerator object.
*/
public MandelbrotGenerator(){
z = new ComplexNum(0,0);
c = new ComplexNum(0,0);
currentCalc = new ComplexNum(0,0);
numIterations = 0;
}
//Methods
/**Carry out the Mandelbrot calculation on the point at the (x,y) coordinates specified by the parameters. The return value specifies
* whether or not this point is within the Mandelbrot set, which is determined by whether or not the values of the real and imaginary
* pieces of currentCalc, or Z_(n+1) from the Mandelbrot equation, both reach or exceed the value of 2 within a number of iterations
* less than or equal to MAX_ITERATIONS.
* (Postcondition: the program will return an int value which can be used to determine whether the input point is within the Mandelbrot set)
* @param xVal -- the double value of the desired x coordinate
* (Precondition: xVal is a real number)
* @param yVal -- the double value of the desired y coordinate
* (Precondition: yVal is a real number)
* @return returns the number of iterations needed to meet or exceed the 2 threshold, or the value of MAX_ITERATIONS if the threshold is never met
*/
public int calculateMandelbrot(double xVal, double yVal, double panelWidth, double panelHeight){
double xCord = convertToMandelX(xVal, panelWidth);
double yCord = convertToMandelY(yVal, panelHeight);
c = new ComplexNum(xCord,-yCord);
for(int iterations = 0; iterations <= MAX_ITERATIONS && Math.abs(currentCalc.getRealPart())+Math.abs(currentCalc.getImgPart())<=4.0; iterations ++){
numIterations = iterations;
z = currentCalc;
currentCalc = z.squareComplex().add(c);
}
return numIterations;
}
//I haven't properly commented the two methods below yet, but these
//are used to convert the coordinates of the pixel I'm testing into
//a point on the coordinate plane with x from -2 to 2 and y from
//-2i to 2i, which the Mandelbrot set is within.
//xPixLoc and yPixLoc are the (x,y) coordinates of the pixels from the
//frame, and maxXVal and maxYVal are the (x,y) dimensions of the frame,
//400 in my case.
public double convertToMandelX(double xPixLoc, double maxXVal){
double xCoordinate = MIN_X + ((xPixLoc/maxXVal)*MANDEL_X_RANGE);
return xCoordinate;
}
public double convertToMandelY(double yPixLoc, double maxYVal){
double yCoordinate = MAX_Y -((yPixLoc/maxYVal)*MANDEL_Y_RANGE);
return yCoordinate;
}
Ich habe einige JUnit Tests durchgeführt und beide der oben genannten Klassen zu funktionieren scheint. Es könnte einen Fehler in meinen Tests geben, der zu einem Versehen geführt hat, aber nichts, was ich unterscheiden könnte. Es scheint mir, dass mein Problem mit meiner eigentlichen Erstellung des Bildes ist, das ist die Klasse unter:
Visuelle (Ich versuche zuerst mit nur zwei Farben diese Arbeit zu bekommen)
public class VisualComponent extends JComponent{
private static final long serialVersionUID = 1L;
//Constants
public static final int DEFAULT_ZOOM_CHANGE = 10;
//Instance Fields
int pnlWidth, pnlHeight; //The width and height of the panel the image will be painted into
BufferedImage fractalImg;
boolean updateImage;
//Constructor
public VisualComponent(int panelWidth, int panelHeight){
pnlWidth=panelWidth;
pnlHeight=panelHeight;
fractalImg = new BufferedImage(panelWidth, panelHeight, BufferedImage.TYPE_INT_RGB);
updateImage = true;
//also initialize a default color pallet
}
//Methods
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if(updateImage){
generateMandelbrot();
updateImage=false;
}
g2.drawImage(fractalImg,0,0,this);
}
public void generateMandelbrot(){
MandelbrotGenerator genImg = new MandelbrotGenerator();
int iterations=0;
for(int x=0; x<pnlWidth;x++){
for(int y=0; y<pnlHeight;y++){
iterations = genImg.calculateMandelbrot((double)x, (double)y, pnlWidth, pnlHeight);
System.out.print(iterations);
if(iterations == MandelbrotGenerator.MAX_ITERATIONS){
fractalImg.setRGB(x, y, Color.BLACK.getRGB());
} else {
fractalImg.setRGB(x, y, Color.WHITE.getRGB());
}
}
}
}
Hier meine Hauptmethode auch:
public class MainTester {
public static void main(String[] args){
JFrame frame=new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setResizable(false);
VisualComponent comp = new VisualComponent(400,400);
frame.add(comp);
frame.setVisible(true);
}
}
Ich bin wirklich ratlos. Was scheint zu geschehen ist, dass, wenn ich calcitMandelbrot() aufrufen, die Rückkehr immer gleich ist. Bei meinen Tests habe ich jedoch festgestellt, dass dies nicht der Fall ist. Ich habe nicht viel Erfahrung mit BufferedImages, also gibt es vielleicht einen Fehler darin, wie ich das benutze?
Da ich es so oft erwähnt habe, hier ist der Testcode, den ich auch verwendete. Ich weiß, dass dies wirklich nicht die richtige Form ist, oder zumindest nicht die Form, die mein Professor lehrte, aber ich war wirklich nur darauf konzentriert, das Problem zu finden.
public class ComplexNumTest {
@Test
public void testToString() {
ComplexNum num = new ComplexNum(5,7);
String res = num.toString();
assertEquals("failed toString()", "5.0+7.0i", res);
}
@Test
public void testAdd(){
ComplexNum num = new ComplexNum(5,7);
ComplexNum num2 = new ComplexNum(5,3);
ComplexNum num3 = num.add(num2);
String res = num3.toString();
assertEquals("failed add()", "10.0+10.0i", res);
ComplexNum num4 = new ComplexNum(5,-7);
ComplexNum num5 = new ComplexNum(-3,4);
ComplexNum num6 = num4.add(num5);
String res2 = num6.toString();
assertEquals("failed add()", "2.0+-3.0i", res2);
}
@Test
public void testSquareComplex(){
ComplexNum num = new ComplexNum(2,2);
ComplexNum num2 = num.squareComplex();
String res = num2.toString();
assertEquals("failed squareComplex()", "0.0+8.0i", res);
ComplexNum num3 = new ComplexNum(2,-2);
ComplexNum num4 = num3.squareComplex();
String res2 = num4.toString();
assertEquals("failed squareComplex()", "0.0+-8.0i", res2);
ComplexNum num5 = new ComplexNum(-1,0.5);
ComplexNum num6 = num5.squareComplex();
String res3 = num6.toString();
assertEquals("failed squareComplex()", "0.75+-1.0i", res3);
}
@Test
public void testCalculations(){
ComplexNum z = new ComplexNum(0,0);
ComplexNum y = new ComplexNum(-1,0.5);
ComplexNum a = z.squareComplex().add(y);
String res = a.toString();
assertEquals("failed calculations", "-1.0+0.5i", res);
z = a;
a = z.squareComplex().add(y);
res = a.toString();
assertEquals("failed squareComplex()", "-0.25+-0.5i", res);
}
@Test
public void getNums(){
ComplexNum z = new ComplexNum(1,3);
ComplexNum a = new ComplexNum(2,4);
double y = z.getRealPart()+a.getRealPart();
String num=y+"";
assertEquals("failed getRealPart()", "3.0", num);
y = z.getImgPart()+a.getImgPart();
num=y+"";
assertEquals("failed getRealPart()", "7.0", num);
}
@Test
public void testConvertToMandel(){
MandelbrotGenerator a = new MandelbrotGenerator();
double check = a.convertToMandelX(200, 400);
String res = check+"";
assertEquals("fail", "0.0", res);
check = a.calculateMandelbrot(200, 200, 400, 400);
res=check+"";
assertEquals("fail", "30.0", res);
boolean working=false;
if(check==MandelbrotGenerator.MAX_ITERATIONS){
working=true;
}
assertEquals("fail",true,working);
}
}
Ich hoffe, das war nicht zu viel Code, um hier auf einmal zu kotzen. Vielen Dank für die Hilfe!
Es gibt nur eine Lösung, die ich für dieses aktuelle Problem kenne: und das ist zu lernen, einen Debugger zu verwenden. –
Beachten Sie, dass Sie einen eklatanten offensichtlichen Fehler haben. Ich bin mir nicht sicher, ob es Ihre Probleme verursacht, aber unabhängig davon muss es behoben werden: Sie machen wichtige Berechnungen innerhalb einer paintComponent-Methode, etwas, das Sie ** nie ** tun sollten. Mache diese in einem Hintergrundthread und zeige sie dann ** in paintComponent an. –
[Zum Beispiel] (http://stackoverflow.com/questions/33859923/change-contents-of-bufferedimage-thenupdate-jframe-to-reflect-it/33860388#33860388). –