Difference between revisions of "Flags with Repeats"

From ProgZoo
Jump to navigation Jump to search
 
(30 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{flags-snippet}}
<pre id='shellbody' data-qtp='canvas'></pre>
In these exercises you can use a function '''star''' which draws a five pointed star on the canvas.


You can control the position of the star by calling the '''transform''' method of ctx.
We can repeat a statement or block of statements with a for loop. The classic '''for''' loop takes the following form:


==Vietnam==
for(let i = 0; i< 10; i++){
<div class=qu data-width="200" data-height="150">
    console.log(i);
The flag of Vietnam has a yellow five pointed star on a red
}
background. This star is a popular device on many flags, we define
the star once and use it many times in later flags.


The given star has a radius of 50, it is centred on 0,0
The body of the loop runs 10 times, control variable i takes every value 0,1,2..9 in turn. We can use the value of i inside the loop if required.
which is the wrong place. We must translate to put it in the
right place.
We can use the [https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate translate] method to move the star to the right location.


The translate call is to the wrong location (50,50) - it should be at
You can dive right in or view the instructive example at [[Flag EU]]
(100,75).
==Bahrain==
<div class=qu data-width="250" data-height="155">
The flag of Bahrain has a five irregular pentagons on a red background.


[[Image:flagvietnam.png]]
Each pentagon can be represented by five points such as (0,0), (64,0) (100,15) (64,31) and (0,31).
 
[[Image:flagbahrain.png|left|frame|Flag of Bahrain]]
<pre class=usr>
<pre class=usr>
function drawFlag(ctx)
function drawFlag(ctx)
{
{
   ctx.fillStyle = 'red';
   ctx.fillStyle = 'red';
   ctx.translate(50,50);
  ctx.fillRect(0,0,250,155);
   star(ctx);
  for(let i=0;i<3;i++){
    ctx.fillStyle='white';
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(64,0);
    ctx.lineTo(100,15);
    ctx.lineTo(64,31);
    ctx.lineTo(0,31);
    ctx.fill();
    ctx.translate(0,31);
  }
}
</pre>
<pre class=ans>
function drawFlag(ctx)
{
  ctx.fillStyle = 'red';
  ctx.fillRect(0,0,250,155);
  for(let i=0;i<5;i++){
    ctx.fillStyle='white';
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(64,0);
    ctx.lineTo(100,15);
    ctx.lineTo(64,31);
    ctx.lineTo(0,31);
    ctx.fill();
    ctx.translate(0,31);
  }
}
</pre>
</div>
 
==Qatar==
<div class=qu data-width="300" data-height="153">
Consider the neighbouring state Qatar.
 
* 9 pillars, each pillar is 17 pixels below the previous.
* The five coordinates of the top pillar are (0,0) (84,0) (125,9) (84,17), (0,17)
* '''rgb(128,0,0)''' is a less jaunty red.
 
The need for a loop becomes even more obvious for this flag.
[[Image:flagqatar.png|left|frame|Flag of Qatar]]
<pre class=usr>
function drawFlag(ctx)
{
  ctx.fillStyle = 'rgb(128,0,0)';
  ctx.fillRect(0,0,250,155);
}
</pre>
<pre class=ans>
function drawFlag(ctx)
{
  ctx.fillStyle = 'rgb(128,0,0)';
  ctx.fillRect(0,0,250,155);
  for(let i=0;i<9;i++){
    ctx.fillStyle='white';
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(84,0);
    ctx.lineTo(125,9);
    ctx.lineTo(84,17);
    ctx.lineTo(0,17);
    ctx.fill();
    ctx.translate(0,17);
  }
}
</pre>
</div>
 
==India==
<div class=qu data-width="306" data-height="204">
* The flag of India is 306 by 204
* The orange, white and green stripes are equal sizes.
* The wheel has radius 30.
* The wheel has 24 spokes, the spokes are π/12 radians apart.
 
Whoever wrote the sample code used copy and paste three times, then got bored and gave up. A better programmer would have used a loop.
This is the phrase that gets repeated:
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
 
We have not really done India justice here - the actual flag is much more elegant, the spokes taper and the rim includes decoration. Nevertheless - we apologize to the sub-continent and move on.
 
[[Image:flagindia.png|left|frame|Flag of India]]
<pre class=usr>
function drawFlag(ctx)
{
  ctx.fillStyle = 'orange';
  ctx.fillRect(0,0,306,204/3);
  ctx.fillStyle = 'lime';
  ctx.fillRect(0,2*204/3,306,204/3);
  ctx.strokeStyle = 'blue';
  ctx.lineWidth = 1.5;
  ctx.translate(153,102);
  ctx.arc(0,0,30,0,2*Math.PI,true);
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
  ctx.stroke();
}
</pre>
<pre class=ans>
function drawFlag(ctx)
{
  ctx.fillStyle = 'orange';
  ctx.fillRect(0,0,306,204/3);
  ctx.fillStyle = 'white';
  ctx.fillRect(0,204/3,306,204/3);
  ctx.fillStyle = 'lime';
  ctx.fillRect(0,2*204/3,306,204/3);
  ctx.strokeStyle = 'blue';
  ctx.lineWidth = 1.5;
   ctx.translate(153,102);
  ctx.arc(0,0,30,0,2*Math.PI,true);
   for(let i=0;i<24;i++){
    ctx.moveTo(0,0);
    ctx.lineTo(0,30);
    ctx.rotate(Math.PI/12);
  }
  ctx.stroke();
}
}
</pre>
</div>
==Namibia==
<div class=qu data-width="300" data-height="200">
* The joyous flag of Namibia is 300 by 200
* Each the rightmost triangle has coordinates (19,5) (29,0) (19,-5) relative to the centre of the star burst
* The star burst is centred at (60,60)
* The yellow circle has radius 16
* The small triangles are partially covered by a blue circle of radius 20
* The right angled triangles are 240 by 160
* The red stripe is 42 wide
That lazy default programmer has done it again. Copied and pasted the same phrase three times then given up. Thank goodness you are here to fix things up!
  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);
[[Image:flagnamibia.png|left|frame|Flag of Namibia]]
<pre class=usr>
function drawFlag(ctx)
{
  ctx.fillStyle = 'yellow';
  ctx.translate(60,60);
 
  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);
  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);


function star(ctx)
  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);
}
</pre>
<pre class=ans>
function drawFlag(ctx)
{
{
  ctx.fillStyle = 'white';
  ctx.fillRect(0,0,300,200);
  ctx.strokeStyle = 'red';
  ctx.lineWidth = 42;
  ctx.moveTo(0,200);
  ctx.lineTo(300,0);
  ctx.stroke();
  ctx.fillStyle = 'blue';
  ctx.moveTo(0,0);
  ctx.lineTo(240,0);
  ctx.lineTo(0,160);
  ctx.fill();
   ctx.beginPath();
   ctx.beginPath();
   [ [ 0,-50],[11,-16],[48,-16],[18,6],[30,41],
   ctx.fillStyle = 'lime';
    [ 0,18],[-30,41],[-18,6],[-48,-16],[-11,-16]
  ctx.moveTo(300,200);
   ].forEach((xy) => ctx.lineTo(xy[0],xy[1]));
   ctx.lineTo(60,200);
  ctx.lineTo(300,40);
   ctx.fill();
   ctx.fill();
  ctx.beginPath();
  ctx.fillStyle = 'yellow';
  ctx.translate(60,60);
  ctx.arc(0,0,16,0,2*Math.PI);
  for(let i=0;i<12;i++){
    ctx.fill();
    ctx.beginPath();
    ctx.moveTo(19,5);
    ctx.lineTo(29,0);
    ctx.lineTo(19,-5);
    ctx.fill();
    ctx.rotate(Math.PI/6);
  }
  ctx.fillStyle = 'blue';
  ctx.arc(0,0,20,0,2*Math.PI);
  ctx.fillStyle = 'yellow';
  ctx.arc(0,0,16,0,2*Math.PI);
}
</pre>
</div>
==Venezuela==
<div class=qu data-width="180" data-height="120">
* There are eight stars arranged around circle centre (90,86) radius 36
* The angle between stars is 20&deg;
* Each star has radius 5
[http://www.vexilla-mundi.com/venezuela_flag.html construction sheet for Venezuela]
[[Image:flagvenezuala.png|left|frame|Flag of Venezuela]]
<pre class=usr>
function drawFlag(ctx)
{
  ctx.fillStyle = 'yellow';
  ctx.translate(60,60);
 
}
}
</pre>
</pre>
Line 39: Line 261:
function drawFlag(ctx)
function drawFlag(ctx)
{
{
  ctx.fillStyle = 'yellow';
  ctx.fillRect(0,0,180,40);
  ctx.fillStyle = 'blue';
  ctx.fillRect(0,40,180,40);
   ctx.fillStyle = 'red';
   ctx.fillStyle = 'red';
   ctx.fillRect(0,0,200,150);
   ctx.fillRect(0,80,180,40);
   ctx.translate(100,75);
   ctx.translate(90,84);
   ctx.fillStyle='yellow';
   ctx.fillStyle = 'white';
   star(ctx);
   let n = 8;
  ctx.rotate(-20*(n-1)/2*Math.PI/180);
  for(let i = 0;i<n;i++){
    ctx.translate(0,-36);
    star(ctx);
    ctx.translate(0,36);
    ctx.rotate(20*Math.PI/180);
  }
}
}


function star(ctx)
function star(ctx){
{
   ctx.beginPath();
   ctx.beginPath();
   [ [ 0,-50],[11,-16],[48,-16],[18,6],[30,41],
  ctx.scale(5.0/100,5.0/100);
    [ 0,18],[-30,41],[-18,6],[-48,-16],[-11,-16]
   [[0,-100],[22,-31],[95,-31],[36,12],[59,81],
   ].forEach((xy) => ctx.lineTo(xy[0],xy[1]));
  [0,38],[-59,81],[-36,12],[-95,-31],[-22,-31]]
   .forEach(xy=>ctx.lineTo(xy[0],xy[1]));
   ctx.fill();
   ctx.fill();
  ctx.scale(100/5,100/5);
}
}
</pre>
</pre>
</div>
</div>

Latest revision as of 08:22, 13 September 2021


We can repeat a statement or block of statements with a for loop. The classic for loop takes the following form:

for(let i = 0; i< 10; i++){
   console.log(i);
}

The body of the loop runs 10 times, control variable i takes every value 0,1,2..9 in turn. We can use the value of i inside the loop if required.

You can dive right in or view the instructive example at Flag EU

Bahrain

The flag of Bahrain has a five irregular pentagons on a red background.

Each pentagon can be represented by five points such as (0,0), (64,0) (100,15) (64,31) and (0,31).

Flag of Bahrain
function drawFlag(ctx)
{
  ctx.fillStyle = 'red';
  ctx.fillRect(0,0,250,155);
  for(let i=0;i<3;i++){
    ctx.fillStyle='white';
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(64,0);
    ctx.lineTo(100,15);
    ctx.lineTo(64,31);
    ctx.lineTo(0,31);
    ctx.fill();
    ctx.translate(0,31);
  }
}
function drawFlag(ctx)
{
  ctx.fillStyle = 'red';
  ctx.fillRect(0,0,250,155);
  for(let i=0;i<5;i++){
    ctx.fillStyle='white';
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(64,0);
    ctx.lineTo(100,15);
    ctx.lineTo(64,31);
    ctx.lineTo(0,31);
    ctx.fill();
    ctx.translate(0,31);
  }
}

Qatar

Consider the neighbouring state Qatar.

  • 9 pillars, each pillar is 17 pixels below the previous.
  • The five coordinates of the top pillar are (0,0) (84,0) (125,9) (84,17), (0,17)
  • rgb(128,0,0) is a less jaunty red.

The need for a loop becomes even more obvious for this flag.

Flag of Qatar
function drawFlag(ctx)
{
  ctx.fillStyle = 'rgb(128,0,0)';
  ctx.fillRect(0,0,250,155);
}
function drawFlag(ctx)
{
  ctx.fillStyle = 'rgb(128,0,0)';
  ctx.fillRect(0,0,250,155);
  for(let i=0;i<9;i++){
    ctx.fillStyle='white';
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.lineTo(84,0);
    ctx.lineTo(125,9);
    ctx.lineTo(84,17);
    ctx.lineTo(0,17);
    ctx.fill();
    ctx.translate(0,17);
  }
}

India

  • The flag of India is 306 by 204
  • The orange, white and green stripes are equal sizes.
  • The wheel has radius 30.
  • The wheel has 24 spokes, the spokes are π/12 radians apart.

Whoever wrote the sample code used copy and paste three times, then got bored and gave up. A better programmer would have used a loop. This is the phrase that gets repeated:

 ctx.moveTo(0,0);
 ctx.lineTo(0,30);
 ctx.rotate(Math.PI/12);

We have not really done India justice here - the actual flag is much more elegant, the spokes taper and the rim includes decoration. Nevertheless - we apologize to the sub-continent and move on.

Flag of India
function drawFlag(ctx)
{
  ctx.fillStyle = 'orange';
  ctx.fillRect(0,0,306,204/3);
  ctx.fillStyle = 'lime';
  ctx.fillRect(0,2*204/3,306,204/3);
  ctx.strokeStyle = 'blue';
  ctx.lineWidth = 1.5;
  ctx.translate(153,102);
  ctx.arc(0,0,30,0,2*Math.PI,true);
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
  ctx.moveTo(0,0);
  ctx.lineTo(0,30);
  ctx.rotate(Math.PI/12);
  ctx.stroke();
}
function drawFlag(ctx)
{
  ctx.fillStyle = 'orange';
  ctx.fillRect(0,0,306,204/3);
  ctx.fillStyle = 'white';
  ctx.fillRect(0,204/3,306,204/3);
  ctx.fillStyle = 'lime';
  ctx.fillRect(0,2*204/3,306,204/3);
  ctx.strokeStyle = 'blue';
  ctx.lineWidth = 1.5;
  ctx.translate(153,102);
  ctx.arc(0,0,30,0,2*Math.PI,true);
  for(let i=0;i<24;i++){
    ctx.moveTo(0,0);
    ctx.lineTo(0,30);
    ctx.rotate(Math.PI/12);
  }
  ctx.stroke();
}

Namibia

  • The joyous flag of Namibia is 300 by 200
  • Each the rightmost triangle has coordinates (19,5) (29,0) (19,-5) relative to the centre of the star burst
  • The star burst is centred at (60,60)
  • The yellow circle has radius 16
  • The small triangles are partially covered by a blue circle of radius 20
  • The right angled triangles are 240 by 160
  • The red stripe is 42 wide

That lazy default programmer has done it again. Copied and pasted the same phrase three times then given up. Thank goodness you are here to fix things up!

 ctx.beginPath();
 ctx.moveTo(19,5);
 ctx.lineTo(29,0);
 ctx.lineTo(19,-5);
 ctx.fill();
 ctx.rotate(Math.PI/6);
Flag of Namibia
function drawFlag(ctx)
{
  ctx.fillStyle = 'yellow';
  ctx.translate(60,60);
  
  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);

  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);

  ctx.beginPath();
  ctx.moveTo(19,5);
  ctx.lineTo(29,0);
  ctx.lineTo(19,-5);
  ctx.fill();
  ctx.rotate(Math.PI/6);
}
function drawFlag(ctx)
{
  ctx.fillStyle = 'white';
  ctx.fillRect(0,0,300,200);
  ctx.strokeStyle = 'red';
  ctx.lineWidth = 42;
  ctx.moveTo(0,200);
  ctx.lineTo(300,0);
  ctx.stroke();
  ctx.fillStyle = 'blue';
  ctx.moveTo(0,0);
  ctx.lineTo(240,0);
  ctx.lineTo(0,160);
  ctx.fill();
  ctx.beginPath();
  ctx.fillStyle = 'lime';
  ctx.moveTo(300,200);
  ctx.lineTo(60,200);
  ctx.lineTo(300,40);
  ctx.fill();
  ctx.beginPath();
  ctx.fillStyle = 'yellow';
  ctx.translate(60,60);
  ctx.arc(0,0,16,0,2*Math.PI);
  for(let i=0;i<12;i++){
    ctx.fill();
    ctx.beginPath();
    ctx.moveTo(19,5);
    ctx.lineTo(29,0);
    ctx.lineTo(19,-5);
    ctx.fill();
    ctx.rotate(Math.PI/6);
  }
  ctx.fillStyle = 'blue';
  ctx.arc(0,0,20,0,2*Math.PI);
  ctx.fillStyle = 'yellow';
  ctx.arc(0,0,16,0,2*Math.PI);
}

Venezuela

  • There are eight stars arranged around circle centre (90,86) radius 36
  • The angle between stars is 20°
  • Each star has radius 5

construction sheet for Venezuela

Flag of Venezuela
function drawFlag(ctx)
{
  ctx.fillStyle = 'yellow';
  ctx.translate(60,60);
  
}
function drawFlag(ctx)
{
  ctx.fillStyle = 'yellow';
  ctx.fillRect(0,0,180,40);
  ctx.fillStyle = 'blue';
  ctx.fillRect(0,40,180,40);
  ctx.fillStyle = 'red';
  ctx.fillRect(0,80,180,40);
  ctx.translate(90,84);
  ctx.fillStyle = 'white';
  let n = 8;
  ctx.rotate(-20*(n-1)/2*Math.PI/180);
  for(let i = 0;i<n;i++){
    ctx.translate(0,-36);
    star(ctx);
    ctx.translate(0,36);
    ctx.rotate(20*Math.PI/180);
  }
}

function star(ctx){
  ctx.beginPath();
  ctx.scale(5.0/100,5.0/100);
  [[0,-100],[22,-31],[95,-31],[36,12],[59,81],
   [0,38],[-59,81],[-36,12],[-95,-31],[-22,-31]]
  .forEach(xy=>ctx.lineTo(xy[0],xy[1]));
  ctx.fill();
  ctx.scale(100/5,100/5);
}