JavaScript graphic example: Hilbert curve

Time:2021-5-4

In 1891, German mathematician David Hilbert constructed a kind of curve. First, he divided a square into four small squares, starting from the center of the square in the northwest corner, going south to the center of the square in the southwest, then east to the center of the square in the southeast corner, and then North to the center of the square in the northeast corner. This is an iteration; If we continue the above process for four small squares, divide them down and repeat them, we will finally get a curve that can fill the whole square, which is called the hibern curve. The generation process is shown in Figure 1.

 

Figure 1   Generation of Hilbert curve

Hilbert curve can be realized by recursive process. In recursive processing, there are four ways to connect the midpoint, as shown in Figure 2.

Figure 2   Four ways to connect center points

Let the vertex coordinates of the upper left corner of the square be (x1, Y1), and the vertex coordinates of the lower right corner be (X2, Y2). If the coordinates of the upper left corner of the square of mode (3) are set to (X2, Y2) and the coordinates of the lower right corner are set to (x1, Y1), mode (3) is equivalent to mode (1) and is equivalent to rotating 180 degrees °; Similarly, mode (4) is equivalent to mode (2). Therefore, the four ways to connect the center point can be seen as (1) and (2).

The connection direction and the next expansion mode of the two connection modes are shown in Figure 3.

Figure 3   Trend and expansion of two connection modes

Among them, the coordinates of the four central points of mode (1) are as follows:

      ①(x1+dx/4,y1+dy/4)           ②(x1+dx/4, y1+3*dy/4)

      ③ (x1+3*dx/4, y1+3*dy/4)     ④(x1+3*dx/4,y1+dy/4)   (dx=x2-1,dy=y2-y1)

The coordinates of the four central points of mode (2) are as follows:

      ①(x1+dx/4,y1+dy/4)           ②(x1+3*dx/4,y1+dy/4)

      ③ (x1+3*dx/4, y1+3*dy/4)     ④(x1+dx/4,  y1+3*dy/4)

In this paper, we introduce an identification variable s, s = 1 (1) and S = – 1 (2), so that the center point coordinates of the two methods can be expressed as:

      ①(x1+dx/4,y1+dy/4)        ②(x1+(2-s)*dx/4,  y1+(2+s)*dy/4)

      ③(x1+3*dx/4, y1+3*dy/4)      ④(x1+(2+s)*dx/4,y1+(2-s)*dy/4)

When expanding recursively, the expansion modes of the four small squares in mode (1) are: mode (2), mode (1), mode (1) and mode (4) (Note: given the coordinate sequence of two vertices, it is equivalent to mode (2)); The expansion modes of the four small squares in mode (2) are mode (1), mode (2), mode (2) and mode (3).

Write the following HTML code.

Hilbert curve

   var canvas = document.getElementById(‘myCanvas’);

   var ctx = canvas.getContext(‘2d’);

   var depth=5;

   ctx.lineWidth = 2;

   ctx.strokeStyle = “red”;

   ctx.beginPath();

   ctx.moveTo(50+400/Math.pow(2,depth+1),50+400/Math.pow(2,depth+1));

   drawShapes(depth,1,50,50,450,450);

   ctx.stroke(); 

   function drawShapes(n,s,x1,y1,x2,y2)

   { 

        dx = x2 – x1,

        dy = y2 – y1;

        if (n>1)

        {  

           if(s>0)

           {

               drawShapes(n-1,-1,x1,y1,(x1+x2)/2,(y1+y2)/2);

               drawShapes(n-1,1,x1,(y1+y2)/2,(x1+x2)/2,y2);

               drawShapes(n-1,1,(x1+x2)/2,(y1+y2)/2,x2,y2);

               drawShapes(n-1,-1,x2,(y1+y2)/2,(x1+x2)/2,y1);

           }

           else

           {

               drawShapes(n-1,1,x1,y1,(x1+x2)/2,(y1+y2)/2);

               drawShapes(n-1,-1,(x1+x2)/2,y1,x2,(y1+y2)/2);

               drawShapes(n-1,-1,(x1+x2)/2,(y1+y2)/2,x2,y2);

               drawShapes(n-1,1,(x1+x2)/2,y2,x1,(y1+y2)/2);

           }

        }

        if (n==1)

        {

            ctx.lineTo(x1+dx/4,y1+dy/4);

            ctx.lineTo(x1+(2-s)*dx/4,  y1+(2+s)*dy/4);

            ctx.lineTo(x1+3*dx/4, y1+3*dy/4);

            ctx.lineTo(x1+(2+s)*dx/4,y1+(2-s)*dy/4);

        }

   }