Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check program debug

So I finished up a program that recursively draws lines which takes an argument "n" to define the depth of the recursion. I have 2 functions, one which draws the relatively left line and another which draws the relatively right one. I tested it ant it seems to work for the first 4 levels, but then either the lines become too small to accurately represent or there's something wrong with my code because the breaks between the lines seem to become arbitrary. Was hoping somebody could test my code and see if they could find what the problem is.

The following image is of depth 10.

EDIT: fixed a part of code, still need help though

public class Art
{

//draws the relatively left line
public static void drawLeftLine(double x0, double y0, double x1, double y1)
{
    //define new x coordinate for line
    //double x2 = (1/3.0)*(x1 - x0);

    //color of line
    StdDraw.setPenColor(StdDraw.BLUE);


    //draw line by adding new x coord to original
    StdDraw.line(x0, y0, x1, y1);

}
//draw relatively right line
public static void drawRightLine(double x0, double y0, double x1, double y1)
{
    //define new x coord for line
    //double x2 = (2/3.0)*(x1 - x0);

    //color of line
    StdDraw.setPenColor(StdDraw.BLUE);


    //draw line by adding new x coord to original
    StdDraw.line(x0, y0, x1, y1);

}

public static void cantor(int n, double x0, double y0, double x1, double y1)
{
    if (n == 0)
        return;

    drawLeftLine(x0, y0, x1, y1);
    drawRightLine(x0, y0, x1, y1);

    y0 = y0 - 0.1;
    y1 = y1 - 0.1;



    cantor(n-1, x0, y0, x0 + ((x1 - x0))/3.0, y1); //left
    cantor(n-1, (2.0/ 3) * (x1 - x0) + x0, y0, x1, y1); //right

}

public static void main(String[] args)
{ 
    //change n into integer (depth)
    int n = Integer.parseInt(args[0]);

    //specify inital values for line
    double x0 = 0;
    double y0 = 0.9;
    double x1 = 0.9;
    double y1 = 0.9;



    //recursive function cantor
    cantor(n, x0, y0, x1, y1);

}
}
like image 293
user2782981 Avatar asked Oct 02 '22 18:10

user2782981


1 Answers

I think that the drawing looks incorrect because the of the fact that all of the nice double values are being approximated with discrete pixels causing unwanted overlap between the line segments (see EDIT at the bottom). Some comments about your code however :

1) You don't need the drawLeftLine and drawRightLine methods since currently they are drawing exactly the same thing. Since at each step you are calling cantor twice (once for each side of the deleted inner third), you have one call to cantor for each line segment that has to be drawn. As such I would put all of the drawing directly into the cantor method.

2) Since y0 and y1 are both always the same, I would reduce them to just a single y variable.

3) I would simplify the math for computing the new x0 and x1 values down to

double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right

4) Instead of decrementing the y value by 0.1 every time, you should have a global variable that decides the amount by which this should be decremented (otherwise if you try n > 10 things will break). This value can just be set to 1.0 / n.

5) You don't need to set the color of the pen every time you paint. You can set it just once in the main method.

6) StdDraw already sets a border around the picture you are drawing so there is no need to start your coordinates from 0.9 - you can use 1 instead.

Following these suggestions the code would look like this :

private static double yIncrement;

public static void cantor(int n, double x0, double x1, double y) {
  if (n == 0)
    return;

  StdDraw.line(x0, y, x1, y);

  y = y - yIncrement;

  double third = (x1 - x0) / 3;
  cantor(n - 1, x0, x0 + third, y); // left
  cantor(n - 1, x1 - third, x1, y); // right

}

public static void main(String[] args) {
  //change n into integer (depth)
  int n = Integer.parseInt(args[0]);

  // specify inital values for line
  double x0 = 0;
  double x1 = 1;
  double y = 1;

  yIncrement = 1.0 / n;
  StdDraw.setPenColor(Color.BLUE);

  // recursive function cantor
  cantor(n, x0, x1, y);
}

EDIT : Playing around with the StdDraw canvas size, canvas scaling settings, and line segment endpoint rounding mode you can get a slightly better picture (the code below produces a picture that looks mostly correct down to the 8th level)

private static double yIncrement;

public static void cantor(int n, double x0, double x1, double y) {
  if (n == 0)
    return;

  x0 = Math.ceil(x0);
  x1 = Math.floor(x1);

  StdDraw.line(x0, y, x1, y);

  y = y - yIncrement;

  double third = (x1 - x0) / 3;
  cantor(n - 1, x0, x0 + third, y); // left
  cantor(n - 1, x1 - third, x1, y); // right

}

public static void main(String[] args) {
  // change n into integer (depth)
  int n = Integer.parseInt(args[0]);

  int width = 1920;
  int height = 1080;

  StdDraw.setCanvasSize(width, height);

  // specify inital values for line
  double x0 = 0;
  double x1 = width;
  double y = 1;

  yIncrement = 1.0 / n;
  StdDraw.setPenColor(Color.BLUE);
  StdDraw.setXscale(0, width);

  // recursive function cantor
  cantor(n, x0, x1, y);
}

To display everything down to the tenth level with absolute correctness you would need a width of 3^9 pixels (19K pixels). For level 9 that's 3^8 = 6K. For level 8 that's 3^7 = 2k, which is why it looks almost correct with 1.9K pixel width and integer rounding.

like image 178
SamYonnou Avatar answered Oct 07 '22 18:10

SamYonnou