Difference between revisions of "W1504 First Steps on a Path"

From Coder Merlin
(Updated formatting)
Line 8: Line 8:


== Get Ready ==
== Get Ready ==
Begin a '''new project''':
{{NewProject|Begin a '''new''' project.}}


Create a new Igis shell project within your "Experiences" directory.  
Create a new Igis shell project within your "Experiences" directory.  
Line 21: Line 21:
</syntaxhighlight>
</syntaxhighlight>


Run the project. (This may take some time.)
{{RunProgram|Run the program. (This may take some time)
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
./run.sh
./run.sh
</syntaxhighlight>
</syntaxhighlight>}}


Open a browser (or use a new tab on an already-open browser).
Open a browser (or use a new tab on an already-open browser).
Line 46: Line 46:
         let path = Path()
         let path = Path()
         path.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
         path.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
         canvas.paint(path)
         canvas.render(path)
     }
     }
</syntaxhighlight>
</syntaxhighlight>


Now, run the program and view in a browser before continuing.
{{RunProgram|Run the program and view in a browser before continuing.}}


Note that there are always at least three steps to painting a path:
Note that there are always at least three steps to painting a path:
Line 59: Line 59:
Let's add a second arc.  Modify setup as follows:
Let's add a second arc.  Modify setup as follows:


<syntaxhighlight lang="swift">
<syntaxhighlight lang="swift" highlight="4">
     override func setup(canvas:Canvas) {
     override func setup(canvas:Canvas) {
         let path = Path()
         let path = Path()
         path.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
         path.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
         path.arc(center:Point(x:500, y:283), radius:100, startAngle:0.2*Double.pi, endAngle:0.8*Double.pi)
         path.arc(center:Point(x:500, y:283), radius:100, startAngle:0.2*Double.pi, endAngle:0.8*Double.pi)
         canvas.paint(path)
         canvas.render(path)
     }
     }
</syntaxhighlight>
</syntaxhighlight>


Now, run the program and view in a browser before continuing.
{{RunProgram|Run the program and view in a browser before continuing.}}


One of the many advantages of paths is that they can be both stroked and filled, just as rectangles.  Modify setup as follows:
One of the many advantages of paths is that they can be both stroked and filled, just as rectangles.  Modify setup as follows:


<syntaxhighlight lang="swift">
<syntaxhighlight lang="swift" highlight="2, 6-8">
     override func setup(canvas:Canvas) {
     override func setup(canvas:Canvas) {
         let outerPath = Path(fillMode:.fillAndStroke)
         let outerPath = Path(fillMode:.fillAndStroke)
Line 80: Line 80:
         let outerFillColor = FillStyle(color:Color(.seashell))
         let outerFillColor = FillStyle(color:Color(.seashell))
         let outerLineWidth = LineWidth(width:2)
         let outerLineWidth = LineWidth(width:2)
         canvas.paint(outerFillColor, outerLineWidth, outerPath)
         canvas.render(outerFillColor, outerLineWidth, outerPath)
     }
     }
</syntaxhighlight>
</syntaxhighlight>


Now, run the program and view in a browser before continuing.
{{RunProgram|Run the program and view in a browser before continuing.}}


Let's add a new path. Modify setup as follows:
Let's add a new path. Modify setup as follows:


<syntaxhighlight lang="swift">
<syntaxhighlight lang="swift" highlight="10-14">
   override func setup(canvas:Canvas) {
   override func setup(canvas:Canvas) {
         let outerPath = Path(fillMode:.fillAndStroke)
         let outerPath = Path(fillMode:.fillAndStroke)
Line 96: Line 96:
         let outerFillColor = FillStyle(color:Color(.seashell))
         let outerFillColor = FillStyle(color:Color(.seashell))
         let outerLineWidth = LineWidth(width:2)
         let outerLineWidth = LineWidth(width:2)
         canvas.paint(outerFillColor, outerLineWidth, outerPath)
         canvas.render(outerFillColor, outerLineWidth, outerPath)


         let innerPath = Path(fillMode:.fillAndStroke)
         let innerPath = Path(fillMode:.fillAndStroke)
Line 102: Line 102:
         let innerFillColor = FillStyle(color:Color(.royalblue))
         let innerFillColor = FillStyle(color:Color(.royalblue))
         let innerLineWidth = LineWidth(width:1)
         let innerLineWidth = LineWidth(width:1)
         canvas.paint(innerFillColor, innerLineWidth, innerPath)
         canvas.render(innerFillColor, innerLineWidth, innerPath)
     }
     }
</syntaxhighlight>
</syntaxhighlight>


Now, run the program and view in a browser before continuing.
{{RunProgram|Run the program and view in a browser before continuing.}}


Let's add an ellipse.  Note that we can combine different object types on the same canvas.  Modify setup by adding the following text to the end of the method:
Let's add an ellipse.  Note that we can combine different object types on the same canvas.  Modify setup by adding the following text to the end of the method:
Line 113: Line 113:
         let pupil = Ellipse(center:Point(x:500, y:340), radiusX:4, radiusY:4, fillMode:.fill)
         let pupil = Ellipse(center:Point(x:500, y:340), radiusX:4, radiusY:4, fillMode:.fill)
         let pupilFillColor = FillStyle(color:Color(.black))
         let pupilFillColor = FillStyle(color:Color(.black))
         canvas.paint(pupilFillColor, pupil)
         canvas.render(pupilFillColor, pupil)
</syntaxhighlight>
</syntaxhighlight>


Now, run the program and view in a browser before continuing.
{{RunProgram|Run the program and view in a browser before continuing.}}


Let's add some lines.  Note that in this case, because we are using the moveTo() primitive, the line segments are not connected to one another.  Modify setup by adding the following text to the end of the method:
Let's add some lines.  Note that in this case, because we are using the moveTo() primitive, the line segments are not connected to one another.  Modify setup by adding the following text to the end of the method:
Line 128: Line 128:
         let lashesStrokeColor = StrokeStyle(color:Color(.brown))
         let lashesStrokeColor = StrokeStyle(color:Color(.brown))
         let lashesWidth = LineWidth(width:2)
         let lashesWidth = LineWidth(width:2)
         canvas.paint(lashesStrokeColor, lashesWidth, lashes)
         canvas.render(lashesStrokeColor, lashesWidth, lashes)
</syntaxhighlight>
</syntaxhighlight>


Now, run the program and view in a browser before continuing.
{{RunProgram|Run the program and view in a browser before continuing.}}


= Exercises =
= Exercises =
{{Exercises|
Continuing with this project:
Continuing with this project:
# Add at least five more eyelashes above the eye.  Pay attention to the proper angle.  (It will be helpful to PLAN this by using graph paper.)
# Add at least five more eyelashes above the eye.  Pay attention to the proper angle.  (It will be helpful to PLAN this by using graph paper.)
Line 140: Line 141:
# Move all of the code to draw the eye to a separate function, named "paintEye()".  Invoke the function.
# Move all of the code to draw the eye to a separate function, named "paintEye()".  Invoke the function.
# Modify the function to accept a Point parameter, "location", which will specify the location of the eye.
# Modify the function to accept a Point parameter, "location", which will specify the location of the eye.
# Invoke the paintEye() function twice using two different locations, placing the eyes at an appropriate distance apart.
# Invoke the paintEye() function twice using two different locations, placing the eyes at an appropriate distance apart.}}

Revision as of 00:03, 6 December 2019

Within these castle walls be forged Mavens of Computer Science ...
— Merlin, The Coder

Prerequisites[edit]

Research[edit]

Experiment[edit]

Get Ready[edit]

New document
Begin a new project.

Create a new Igis shell project within your "Experiences" directory.

cd ~/Experiences
git clone https://github.com/TheCoderMerlin/IgisShellD W1504

Enter into the Sources/IgisShellD directory of the new project.

cd W1504/Sources/IgisShellD/
Start button green arrow
Run the program. (This may take some time)
./run.sh

Open a browser (or use a new tab on an already-open browser). Go to the URL: http://www.codermerlin.com/users/user-name/dyn/index.html

NOTE: You MUST change user-name to your actual user name. For example, http://www.codermerlin.com/users/john-williams/dyn/index.html

You'll know your successful if you see the title bar change to "Coder Merlin: IGIS".

Primitives[edit]

Paths enable us to execute a series of primitives (lines, curves, ellipses, arcs, etc.) into a single unit for later display. Let's start by painting a path with a single arc.

Open main.swift in emacs.

emacs main.swift

Find the function within the Painter object named "setup". Edit the contents as follows:

    override func setup(canvas:Canvas) {
        let path = Path()
        path.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
        canvas.render(path)
    }
Start button green arrow
Run the program and view in a browser before continuing.

Note that there are always at least three steps to painting a path:

  1. Create the path object and specify the starting point of the path
  2. Build the path by adding primitives. Often multiple primitives will be added to a path. In many cases, as new primitives are added, the starting point of the new primitive connects with the ending point of the previous primitive.
  3. Paint the path on the canvas

Let's add a second arc. Modify setup as follows:

    override func setup(canvas:Canvas) {
        let path = Path()
        path.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
        path.arc(center:Point(x:500, y:283), radius:100, startAngle:0.2*Double.pi, endAngle:0.8*Double.pi)
        canvas.render(path)
    }
Start button green arrow
Run the program and view in a browser before continuing.

One of the many advantages of paths is that they can be both stroked and filled, just as rectangles. Modify setup as follows:

    override func setup(canvas:Canvas) {
        let outerPath = Path(fillMode:.fillAndStroke)
        outerPath.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
        outerPath.arc(center:Point(x:500, y:283), radius:100, startAngle:0.2*Double.pi, endAngle:0.8*Double.pi)

        let outerFillColor = FillStyle(color:Color(.seashell))
        let outerLineWidth = LineWidth(width:2)
        canvas.render(outerFillColor, outerLineWidth, outerPath)
    }
Start button green arrow
Run the program and view in a browser before continuing.

Let's add a new path. Modify setup as follows:

   override func setup(canvas:Canvas) {
        let outerPath = Path(fillMode:.fillAndStroke)
        outerPath.arc(center:Point(x:500, y:400), radius:100, startAngle:1.2*Double.pi, endAngle:1.8*Double.pi)
        outerPath.arc(center:Point(x:500, y:283), radius:100, startAngle:0.2*Double.pi, endAngle:0.8*Double.pi)
 
        let outerFillColor = FillStyle(color:Color(.seashell))
        let outerLineWidth = LineWidth(width:2)
        canvas.render(outerFillColor, outerLineWidth, outerPath)

        let innerPath = Path(fillMode:.fillAndStroke)
        innerPath.arc(center:Point(x:500, y:340), radius:15)
        let innerFillColor = FillStyle(color:Color(.royalblue))
        let innerLineWidth = LineWidth(width:1)
        canvas.render(innerFillColor, innerLineWidth, innerPath)
    }
Start button green arrow
Run the program and view in a browser before continuing.

Let's add an ellipse. Note that we can combine different object types on the same canvas. Modify setup by adding the following text to the end of the method:

        let pupil = Ellipse(center:Point(x:500, y:340), radiusX:4, radiusY:4, fillMode:.fill)
        let pupilFillColor = FillStyle(color:Color(.black))
        canvas.render(pupilFillColor, pupil)
Start button green arrow
Run the program and view in a browser before continuing.

Let's add some lines. Note that in this case, because we are using the moveTo() primitive, the line segments are not connected to one another. Modify setup by adding the following text to the end of the method:

        let lashes = Path()
        lashes.moveTo(Point(x:415, y:325))
        lashes.lineTo(Point(x:395, y:305))
        lashes.moveTo(Point(x:440, y:310))
        lashes.lineTo(Point(x:420, y:290))
        let lashesStrokeColor = StrokeStyle(color:Color(.brown))
        let lashesWidth = LineWidth(width:2)
        canvas.render(lashesStrokeColor, lashesWidth, lashes)
Start button green arrow
Run the program and view in a browser before continuing.

Exercises[edit]

ExercisesExercisesIcon.png

Continuing with this project:

  1. Add at least five more eyelashes above the eye. Pay attention to the proper angle. (It will be helpful to PLAN this by using graph paper.)
  2. Change the color of the eyelashes to the color of your eyelashes.
  3. Change the color of the iris to match the color of your eyes.
  4. Move all of the code to draw the eye to a separate function, named "paintEye()". Invoke the function.
  5. Modify the function to accept a Point parameter, "location", which will specify the location of the eye.
  6. Invoke the paintEye() function twice using two different locations, placing the eyes at an appropriate distance apart.