Week 51 of 2018
Development log of Elm Tree Workshop
30 items
- Edits to the day-1 text
- Separate day 2, add TransformationsCircle example
- Make develop script build all examples to public/
- More progress on Day 1
- Merge branch 'multiple-pages' into review-day-one
- Fix bad imports with merge
- Finish day 1
- Remove duplicated ViewBox module
- Separate Window block from example blocks
- Make develop script print the modules it compiles to HTML
- Remove calls to Debug.log from Main
- Rename TransformationsCircle to Circle, make it parametrized, edit day-2
- Merge branch 'multiple-pages' into review-day-one
- Finish first draft of day 2
- Make Monospace block font size smaller
- Merge branch 'multiple-pages' into 'master'
- Fix slashes in inlines by upgrading mdgriffith/elm-markup to 2.0.5
- Fix "Elm" capitalization in day-1
- Change directory name to "software-garden"
- Elaborate on pressing Enter in terminal
- Explain that we need to change directory after opening a terminal
- Mention that you can use other editor than Atom
- Fix link label in day-1
- Merge branch 'master' into day-2
- Fix typo
- Add links to Day 2 from index and Day 1
- Remove Debug.log calls from Circle
- Express the Day 2 motto in "Let's ..." style
- Put scattered and evenly distributed examples next to each other
- Add ACME challenge code for Let's Encrypt verification
Edits to the day-1 text
On by
Modify simplest embedded example to take background and fill config
index 3cd7b9e..83cc9bf 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -10,40 +10,40 @@
=
= | List
= -> Scalable Vector Graphics
- -> cartesian Coordinates System
+ -> Cartesian Coordinates Systems
= -> Layouts with ELM UI
=
=
=| Header
- First Program!
+ Our First Program!
=
=As mentioned before, programs are represented as text (called the /source code/). The source code is stored in files {Icon|name=file} and files are organized in directories {Icon|name=folder}.
=
=
=So the first step is to create a directory for our new program. Lets call it fpart.
-In the terminal type
+In the terminal type:
=
=| Monospace
= mkdir fpart/
=
-and then
+and then:
=
=| Monospace
= cd fpart/
=
-This creates a new directory and makes it the current one. Again, don't worry about the details.
+The first command will create our new directory and the second will make it the current directory. Again, don't worry about the details.
=
-To easily create a new program, we can type
+We can easily create a new program by typing:
=
=| Monospace
= elm init
=
-Then to create a file with source code, type
+Then to create the file which will contain our source code, type:
=
=| Monospace
= atom src/Main.elm
=
-This command should open a new Atom window with empty text file.
+This command should open a new Atom window with an empty text file.
=
=| Header
= Main.elm
@@ -58,19 +58,19 @@ This command should open a new Atom window with empty text file.
= Html.text "Hello, Tree"
=
=Type the above in the editor and save the file.
-To see the program running type the following in the terminal
+To run the program, type the following command in the terminal:
=
=| Monospace
= elm reactor
=
-This command starts the Elm reactor, which will let you run your program in the web browser. Note that it won't give you the command line back - it will run as long as you don't stop it.
+This command will start the Elm reactor, which will allow you to run your program in the web browser. Note that it won't give you the command line back - it will run as long as you don't stop it.
=
=
=| Emphasize
= Voila!
=
=
-Open following address in the web browser
+Open following address in the web browser:
=
=| Emphasize
= {Link|http://localhost:8000/src/Main.elm|url=http://localhost:8000/src/Main.elm}
@@ -78,16 +78,16 @@ Open following address in the web browser
=| Note
= *TODO*: Make the link display // characters
=
-Note that the same address was printed by Elm reactor
+Note that the same address was printed by the Elm reactor.
=
=| Header
= The problem
=
-We want to have a dot at the center of the screen, like this
+We want to display a dot at the center of the screen, like this:
=
=| DotAtTheCenterOfTheScreen
=
-Below is the complete code to draw a dot like this, but don't type it in your editor yet! We are going to recreate together it step by step.
+Below is the complete code to draw a dot like this, but don't type it in your editor yet! We are going to recreate it together, step by step.
=
=| Code
= module Main exposing (main)
@@ -114,113 +114,124 @@ Below is the complete code to draw a dot like this, but don't type it in your ed
= , Element.height Element.fill
= ]
=
+We are going to use a technology called SVG (Scalable Vector Graphics).
=
+*Scalable icon should be here*
+
+S for Scalable
=
-We are going to use a technology called SVG (Scalable Vector Graphics). Its all about drawing shapes on the screen. Let's install an Elm Package to help us work with SVG. Stop the reactor running in terminal by pressing {Code|CTRL} + {Code|C} and type the following:
+Its all about drawing shapes on the screen. Let's install an Elm Package to help us work with SVG. Stop the reactor running in the terminal by pressing {Code|CTRL} + {Code|C} and then type the following:
=
=| Monospace
= elm install elm/svg
=
-Then start the reactor again:
+Now that we have {Code|elm//svg} installed, we can write the code that will draw our dot:
+
+| Code
+ module Simplest exposing (main)
+
+ import Element
+ import Svg
+ import Svg.Attributes
+
+
+ main =
+ Svg.svg []
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ ]
+ []
+ ]
+
+Start the reactor again:
=
=| Monospace
= elm reactor
=
=| Note
- You can press up arrow {Icon|name=arrow-up} on the keyboard to get to the previous commands.
+ You can press the up arrow {Icon|name=arrow-up} on the keyboard to retrieve commands entered previously.
=
=Reload the browser. You should see something like this:
=
=| Simplest
+ background=none
+ fill=black
=
-Why is the dot at the corner?
+Something isn't quite right here. Why is the dot in the corner?
=
-It's because its center is at point called {Code|origin} or {Code|(0, 0)}. But what does it mean ?
+There are two reasons. First, because the center of the dot is at a point called the {Code|origin} or {Code|(0, 0)}. We'll explore exactly what this means later.
=
-* a picture of a vase on a table should be here *
+Second, it's because the SVG space doesn't fill the browser window. Don't believe me? We can see that the space doesn't fill the window by changing the background color of the SVG element.
=
-Move sliders to change the x and y coordinates of the dot. It's like moving a thing on a table by telling how far left, right, up or down it should go.
-
-| CartesianCoordinates
+| Note
+ Code sample for simplest with pink background should be here.
=
-To change where the dot is we can use cx and cy attributes of the circle
+When you reload the browser, you'll see this:
=
-* simplest with cx and cy should be here *
+| Note
+ Example of simplest with pink background should be here.
=
-* Module main exposing main should be here *
+| Simplest
+ background=pink
+ fill=black
=
-Note that we have a complete program that draws a dot at the center of the screen , lets take a moment to understand it.
+Now we can clearly see that our SVG element (which is pink) does not fill the screen.
=
-Think about this ( * a picture of eggs and a box of eggs should be here * )
+We can easily correct this with the help of a very handy elm package, {Code|mdgriffith//elm-ui}.
=
-| Note
- An egg is a thing.
- Six eggs are six things.
- A box of six eggs is a thing.
+Install it with the terminal.
=
+Press {Code|CTRL + C} to stop the elm-reactor, type {Code|elm install mdgriffith//elm-ui} and press {Code|Enter}.
=
+Then in {Code|src//Main.elm} add the necessary import {Code|import Element} and change {Code|Main} to look like this:
=
-Now, let's make the SVG element fill the screen
+Main = * the code of Element.layout should be here*
=
+Take a wild guess: what do you think {Code|Element.height Element.fill} and {Code|Element.height Element.width} do?
=
-| FillTheScreen
+Reload the browser to confirm your hypothesis. Voila! The SVG space now fills the screen. It should now be possible to place our dot in the center of the screen. But, how exactly will we achieve it?
=
+Let's return to the idea we introduced earlier, that the center of the dot is at a point called the {Code|origin} or {Code|(0, 0)}. What eactly does this mean?
=
-For that we will need a package called {Link|mdgriffith//elm-ui|url=https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/}
+* a picture of a vase on a table should be here *
=
-Install it using terminal
+Adjust the sliders below to change the x and y coordinates of the dot. It's like moving an object on a table by describing how far left, right, up or down it should be.
=
-{Code|CTRL + C } to stop elm-reactor and type {Code|elm install mdgriffith//elm-ui}
+| CartesianCoordinates
=
-Then in {Code|src//Main.elm} add import {Code|import Element} and change {Code|Main} to look like this :
+Knowing that the center of the dot is at the {Code|origin} or point {Code|(0,0)} of our plain, we can see that by default the origin of an SVG space is at the upper left corner. If we want to help our dot get out of hiding, we'll have to place the center of the dot at a point with positive {Code|x} and {Code|y} values.
=
-Main = * the code of Element.layout should be here*
+To change the position of the dot, we can use the {Code|cx} and {Code|cy} attributes of the {Code|circle} element.
=
-Note that our scene fills the screen, it's time to put the dot at the center of the scene.
+* simplest with cx and cy should be here *
=
-* a picture of cx and cy with width and height should be here *
+Now, if we want our dot to be exactly in the center of the screen, we'll have to set {Code|cx} and {Code|cy} to values equal to exactly half of the {Code|width} and {Code|height} of the SVG space.
=
-If we would know the height and width of the screen , we could calculate its position as
+We can calculate the position of the circle as:
=
=| Monospace
= cx = width/2
= cy = height/2
=
-There is a problem though, we don't know the height and width.
+There is a problem though! We don't actually know the width and height of the SVG space. All we know is that its {Code|width} and {Code|height} will {Code|fill} the viewport, whatever its size.
=☹️
=
-But we don't need to!
+Fortunately, we don't need to know the width and height of the SVG space!
=
-*Scalable icon should be here*
+This is a bit tricky. Instead of moving the dot in the SVG space, we can set the boundaries of the {Code|scene} so that the dot is at the center using a property called {Code|Viewbox}.
=
-S for Scalable
+To use an anology, imagine you've decided to build a holiday home with your family or friends in the Alps. Sounds pretty nice, right? Now, your budget isn't unlimited, so you've had to make a few compromises. You're in a beautiful area with a lovely view of the mountains, but yours isn't the only house in the area, and some of the others aren't the nicest to look at. Of course, you don't want your view of the beautiful snow-capped mountains to be blocked by a big pile of concrete. So what are you going to do about this? You can move your neighbours' homes, and the mountains while you're at it, so they are directly in front of your windows. Or, you can move the windows as you design your house so that you get a full view of the beautiful surroundings. Imagine you could move the windows around, as you decide the best place for them. As the window moves, you it will look as though the surroundings as moving, to the right, the left, up and down, as you shift the window. But in reality it is only your perspective that is changing.
=
-Instead of moving the dot, we can set the boundaries of the scene so that the dot is at the center using a property called Viewbox.
+A videwbox is like a window into an SVG space. It allows us to change the point of view of the scene.
=
=| ViewBox
=
-Here is how the viewbox works
-
-* a picture of viewbox should be here*
-
-viewbox = 0 0 100 100 (left, top, width and height respectively)
-
-* a picture of periscope looking table should be here*
+In this example, we can set the width and height of the viewbox to an arbitrary value. As we see in the interactive example, the width and height of the viewbox will effect how big the dot appears, but that's not so important to us at the moment. Let's set them both to 1000.
=
-The trick is to set the width and height to any arbitrary value (say 1000) and top and left to {Code|- width//2}!
+The top and left values of the viewbox are a bit trickier. We saw ealier that if we knew the width and height of our SVG scene, we could have set the cx and cy values of the dot to half the width and height of the scene to center the dot. We will have to use similar reasoning here. If we set the top and left values of the viewbox to 0, the dot will still still appear in the top left corner of the scene. If we want to see the dot moved to the right and downward within the scene, we will need the top and left values of the viewbox to be negative. If we want the origin of the SVG space to appear directly in the center of the scene, we will need to set the top and left values of the viewbox to {Code|- height//2} and {Code|- width//2}. In this case, they will both have the value 500.
=
-That way point (0,0) will always be right in the middle (the distance to the left and to the right is the same, likewise the distance to the top and bottom).
+Refresh the broswer. We should now see the dot in the center of the screen.
=
-First, lets see where the SVG boundaries are by giving it a background color
-
-
-| CenteredDot
-
-
-| Code
- Svg [background "pink"]
- [...
- ]
=
=Give a color to the dot
=index d542d78..019ba58 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -487,16 +487,23 @@ document =
= simplest : Mark.Block (Model -> Element Msg)
= simplest =
= let
- render model =
- Simplest.main
+ render : Simplest.Config -> Model -> Element Msg
+ render config model =
+ Simplest.ui config
= |> Element.html
+ |> Element.el []
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
+ , Element.padding 5
= ]
= |> BrowserWindow.window []
= in
- Mark.stub "Simplest" render
+ Mark.record2 "Simplest"
+ Simplest.Config
+ (Mark.field "background" Mark.string)
+ (Mark.field "fill" Mark.string)
+ |> Mark.map render
=
= fillTheScreen : Mark.Block (Model -> Element Msg)
= fillTheScreen =index 9f90116..2e65fa4 100644
--- a/src/Simplest.elm
+++ b/src/Simplest.elm
@@ -1,17 +1,32 @@
-module Simplest exposing (main)
+module Simplest exposing (Config, defaults, ui)
=
-import Element
+import Html exposing (Html)
=import Svg
=import Svg.Attributes
=
=
+type alias Config =
+ { background : String
+ , fill : String
+ }
+
+
+defaults : Config
+defaults =
+ Config "none" "black"
+
+
+main : Html msg
=main =
- Svg.svg
- [ Svg.Attributes.width "300"
- , Svg.Attributes.height "150"
- ]
+ ui defaults
+
+
+ui : Config -> Html msg
+ui { background, fill } =
+ Svg.svg [ Svg.Attributes.style <| "background: " ++ background ]
= [ Svg.circle
= [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill fill
= ]
= []
= ]Separate day 2, add TransformationsCircle example
On by
Expose Transformation(..) and Apply from Transformations module.
new file mode 100644
index 0000000..32d4a6c
--- /dev/null
+++ b/content/day-2.txt
@@ -0,0 +1,75 @@
+| Title
+ Day 2
+
+| Emphasize
+ Place the dots in a circle
+
+
+| Note
+ Today we are going to lear about
+
+ | List
+ - SVG transformations
+ - SVG groups (?)
+
+| Header
+ The Problem
+
+We want to place the dots in a circle, like that:
+
+| TransformationsCircle
+ dots = True
+ circle = False
+ angle = False
+ center = False
+
+As you can see, we will make the dot's have different colors, so it's more fun!
+
+How we will get there?
+
+We will need more than one dot. Let's make it 5. Then let's think what does it mean to be placed on a circle.
+
+First of all we have to realize that a circle has a center. It's a point that lays exactly in the middle:
+
+
+Then we can say that several things lay on a circle if the distance between each of them and the center is the same.
+
+In other words, you can put a thing in the center and then move it in any direction, let's say 1 meter. If you do the same to several things, you will make them lay on a circle.
+
+Of course the direction must be different each time. Otherwise the things would just stack one on top of another! We wouldn't call it a circle, right?
+
+We will change the cartesian coordinates of the dots, nothing else! But figuring out the right coordinates is a bit tricky
+
+How can we figure out the correct cartesian coordinates?
+
+| Note
+ Story about the flowerpot and the table: two ways to measure relative position, one is distance from an x and y axis (cartesian coordinates), the other is angle and distance relative to origin (polar coordinates)
+
+
+What does this have to do with a circle? Do you know the expression 'I did a 180'. Where would you be looking if you did two 180s (a '360'). We see that circles and angles are closely related!
+
+Exercise with compass and 5 objects, place objects evenly along compass. How many degrees apart are they? (observe if we multiply the result by 5, we're back to 360)
+
+We have one part of it (angle), we now need the distance. Notice they are all the same distance from the origin (the center dot) of the compass. Definition of circle: points that are an equal distance from a center. Actually, the distance doesn't matter, so long as they all have the same distance. You can have a big circle or a small circle, they're both circles
+
+Ok great, we're done! Now, does anyone know how to give an angle and distance to svg? Oh... no? We don't either... you can't. You can only give x and y values relative to the origin
+
+So we already know that angle and length are just another way of describing x and y. But we need some way of translating between the two
+
+sing a visual demonstration, if you draw a line from your object to the x axis, you have a triangle. Same if you draw a line to the y axis. You can figure out the point on the axis using sin and cos functions and multiplying the result by the length.
+
+Let's use a chart to figure out the sin and cos of our angles
+
+/It's important to get a chart, otherwise we have to use calculators which work with radians/
+
+Now we are done... we can plug in our x and y values, and presto, our dots are arranged in a circle. But we don't see most of them...
+
+Our origin is in the top left corner. This means any dots with negative x or y values are off the screen.
+
+We can shift the dots so they are on the screen, or shift the screen so that it covers the dots. We will be shifting the screen
+
+Sample viewbox program to demonstrate
+
+Create a viewbox with correct perimeters (must be more than the radius of the circle plus the radius of a dot in each direction, and width and height are circumference)
+
+{Code|svg [viewbox "-100 -100 200 200 " ] []}index 54d5902..07ece92 100644
--- a/elm.json
+++ b/elm.json
@@ -16,6 +16,7 @@
= "elm/url": "1.0.0",
= "elm-community/basics-extra": "4.0.0",
= "elm-community/list-extra": "8.1.0",
+ "elm-community/maybe-extra": "5.0.0",
= "elm-community/result-extra": "2.2.1",
= "elm-explorations/markdown": "1.0.0",
= "feathericons/elm-feather": "1.2.0",index 019ba58..ab8ac60 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -41,6 +41,7 @@ import Routes exposing (Route)
=import Simplest
=import Spiral
=import Transformations
+import TransformationsCircle
=import Tree
=import Url exposing (Url)
=import ViewBox
@@ -451,6 +452,7 @@ document =
= , fillTheScreen
= , dotAtTheCenterOfTheScreen
= , centeredDot
+ , transformationsCircle
= , line
= , gradient
= , transformations
@@ -545,6 +547,27 @@ document =
= in
= Mark.stub "CenteredDot" render
=
+ transformationsCircle : Mark.Block (Model -> Element Msg)
+ transformationsCircle =
+ let
+ render : TransformationsCircle.Config -> Model -> Element Msg
+ render config model =
+ TransformationsCircle.ui config
+ |> Element.el
+ [ Element.height (Element.px 400)
+ , Element.width Element.fill
+ , Element.padding 5
+ ]
+ |> BrowserWindow.window []
+ in
+ Mark.record4 "TransformationsCircle"
+ TransformationsCircle.Config
+ (Mark.field "circle" Mark.bool)
+ (Mark.field "center" Mark.bool)
+ (Mark.field "angle" Mark.bool)
+ (Mark.field "dots" Mark.bool)
+ |> Mark.map render
+
= line : Mark.Block (Model -> Element Msg)
= line =
= letindex 295c1ef..1b3937d 100644
--- a/src/Transformations.elm
+++ b/src/Transformations.elm
@@ -1,6 +1,8 @@
=module Transformations exposing
= ( Model
= , Msg
+ , Transformation(..)
+ , apply
= , init
= , main
= , uinew file mode 100644
index 0000000..96264ff
--- /dev/null
+++ b/src/TransformationsCircle.elm
@@ -0,0 +1,135 @@
+module TransformationsCircle exposing (Config, defaults, main, ui)
+
+import Element exposing (Element)
+import Html exposing (Html)
+import Maybe.Extra as Maybe
+import Svg exposing (Svg)
+import Svg.Attributes
+import Transformations exposing (Transformation(..))
+
+
+main : Html.Html msg
+main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (ui defaults)
+
+
+ui : Config -> Element msg
+ui config =
+ let
+ present : Bool -> Svg msg -> Maybe (Svg msg)
+ present flag shape =
+ if flag then
+ Just shape
+
+ else
+ Nothing
+
+ shapes =
+ dots
+ ++ Maybe.values
+ [ present config.circle circle
+ ]
+
+ dots =
+ if config.dots then
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "skyblue"
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate 0
+ , Translate 80 0
+ ]
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "pink"
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate 72
+ , Translate 80 0
+ ]
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "yellow"
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate 144
+ , Translate 80 0
+ ]
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "lime"
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate 216
+ , Translate 80 0
+ ]
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "maroon"
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate 288
+ , Translate 80 0
+ ]
+ ]
+ []
+ ]
+
+ else
+ []
+
+ circle =
+ Svg.circle
+ [ Svg.Attributes.r "80"
+ , Svg.Attributes.stroke "silver"
+ , Svg.Attributes.strokeWidth "1"
+ , Svg.Attributes.strokeDasharray "5 5"
+ , Svg.Attributes.fill "none"
+ ]
+ []
+ in
+ shapes
+ |> Svg.svg
+ [ Svg.Attributes.viewBox "-100 -100 200 200"
+ ]
+ |> Element.html
+
+
+defaults : Config
+defaults =
+ { circle = False
+ , center = False
+ , angle = False
+ , dots = False
+ }
+
+
+type alias Config =
+ { circle : Bool
+ , center : Bool
+ , angle : Bool
+ , dots : Bool
+ }Make develop script build all examples to public/
On by
It's a quick and dirty solution.
All examples are now in src/Examples/ directory.
There is a new Transformations module that exposes Transformation type and it's constructors and apply function.
index 568384b..3b0e90e 100755
--- a/scripts/develop
+++ b/scripts/develop
@@ -2,4 +2,10 @@
=
=set -euo pipefail
=
+# Build examples
+for example in src/Examples/*.elm
+do
+ npx elm make --output "public/${example}.html" "${example}"
+done
+
=npx elm-live src/Main.elm --pushstate -- --debugsimilarity index 98%
rename from src/CartesianCoordinates.elm
rename to src/Examples/CartesianCoordinates.elm
index fc29be3..1c4266c 100644
--- a/src/CartesianCoordinates.elm
+++ b/src/Examples/CartesianCoordinates.elm
@@ -1,4 +1,4 @@
-module CartesianCoordinates exposing
+module Examples.CartesianCoordinates exposing
= ( Model
= , Msg
= , initsimilarity index 96%
rename from src/CenteredDot.elm
rename to src/Examples/CenteredDot.elm
index 59fb692..9f00631 100644
--- a/src/CenteredDot.elm
+++ b/src/Examples/CenteredDot.elm
@@ -1,4 +1,4 @@
-module CenteredDot exposing (main)
+module Examples.CenteredDot exposing (main)
=
={-| This program demonstrates how to center an element within an SVG viewport. The idea is to make sure that (0, 0) point (so called origin) should be in the middle of the ViewBox. We can achive that, by making the top-left corner of the ViewBox same distance from the (0, 0) as the bottom right.
=similarity index 97%
rename from src/Counter.elm
rename to src/Examples/Counter.elm
index 0f0689c..66d1400 100644
--- a/src/Counter.elm
+++ b/src/Examples/Counter.elm
@@ -1,4 +1,4 @@
-module Counter exposing
+module Examples.Counter exposing
= ( Model
= , Msg
= , initsimilarity index 87%
rename from src/DotAtTheCenterOfTheScreen.elm
rename to src/Examples/DotAtTheCenterOfTheScreen.elm
index 83f0d1d..cc1875e 100644
--- a/src/DotAtTheCenterOfTheScreen.elm
+++ b/src/Examples/DotAtTheCenterOfTheScreen.elm
@@ -1,4 +1,4 @@
-module DotAtTheCenterOfTheScreen exposing (main, ui)
+module Examples.DotAtTheCenterOfTheScreen exposing (main, ui)
=
=import Element
=import Svgsimilarity index 90%
rename from src/FillTheScreen.elm
rename to src/Examples/FillTheScreen.elm
index 56f88d6..cef2371 100644
--- a/src/FillTheScreen.elm
+++ b/src/Examples/FillTheScreen.elm
@@ -1,4 +1,4 @@
-module FillTheScreen exposing (main, ui)
+module Examples.FillTheScreen exposing (main, ui)
=
=import Element
=import Svgsimilarity index 96%
rename from src/Gradient.elm
rename to src/Examples/Gradient.elm
index 4aa189c..1d7a0c9 100644
--- a/src/Gradient.elm
+++ b/src/Examples/Gradient.elm
@@ -1,4 +1,4 @@
-module Gradient exposing (main, ui)
+module Examples.Gradient exposing (main, ui)
=
=import Element
=import Svgsimilarity index 93%
rename from src/Line.elm
rename to src/Examples/Line.elm
index 53ab314..d105ef5 100644
--- a/src/Line.elm
+++ b/src/Examples/Line.elm
@@ -1,4 +1,4 @@
-module Line exposing (main, ui)
+module Examples.Line exposing (main, ui)
=
=import Element
=import Svgsimilarity index 96%
rename from src/LineTypedTransformations.elm
rename to src/Examples/LineTypedTransformations.elm
index f39d91f..46899d3 100644
--- a/src/LineTypedTransformations.elm
+++ b/src/Examples/LineTypedTransformations.elm
@@ -1,4 +1,4 @@
-module LineTypedTransformations exposing (main)
+module Examples.LineTypedTransformations exposing (main)
=
=import Element
=import Svgsimilarity index 98%
rename from src/NestedTransformations.elm
rename to src/Examples/NestedTransformations.elm
index e0aaded..b1bc6f5 100644
--- a/src/NestedTransformations.elm
+++ b/src/Examples/NestedTransformations.elm
@@ -1,4 +1,4 @@
-module NestedTransformations exposing
+module Examples.NestedTransformations exposing
= ( Model
= , Msg
= , init
@@ -26,8 +26,10 @@ import List.Extra as List
=import Point2d
=import Svg exposing (..)
=import Svg.Attributes exposing (..)
+import Transformations exposing (Transformation(..))
=
=
+main : Program () Model Msg
=main =
= Browser.sandbox
= { init = init
@@ -40,13 +42,6 @@ type alias Model =
= AnyDict String Group (Array Transformation)
=
=
-type Transformation
- = Identity
- | Scale Float Float
- | Translate Float Float
- | Rotate Float
-
-
=type Group
= = Pink
= | Green
@@ -134,7 +129,9 @@ ui model =
= nestTransformationsGroup group transformations item =
= let
= transformation =
- transformations |> Array.toList |> apply
+ transformations
+ |> Array.toList
+ |> Transformations.apply
=
= color =
= groupsimilarity index 99%
rename from src/PolarCoordinates.elm
rename to src/Examples/PolarCoordinates.elm
index 3a476cd..4fd1e93 100644
--- a/src/PolarCoordinates.elm
+++ b/src/Examples/PolarCoordinates.elm
@@ -1,4 +1,4 @@
-module PolarCoordinates exposing
+module Examples.PolarCoordinates exposing
= ( Model
= , Msg
= , initsimilarity index 98%
rename from src/RosetteTypedTransformations.elm
rename to src/Examples/RosetteTypedTransformations.elm
index 2ae161e..e83eb99 100644
--- a/src/RosetteTypedTransformations.elm
+++ b/src/Examples/RosetteTypedTransformations.elm
@@ -1,4 +1,4 @@
-module RosetteTypedTransformations exposing (main, ui)
+module Examples.RosetteTypedTransformations exposing (main, ui)
=
=import Element
=import Svgsimilarity index 89%
rename from src/Simplest.elm
rename to src/Examples/Simplest.elm
index 2e65fa4..74f75dc 100644
--- a/src/Simplest.elm
+++ b/src/Examples/Simplest.elm
@@ -1,4 +1,4 @@
-module Simplest exposing (Config, defaults, ui)
+module Examples.Simplest exposing (Config, defaults, ui)
=
=import Html exposing (Html)
=import Svgsimilarity index 98%
rename from src/Spiral.elm
rename to src/Examples/Spiral.elm
index 7e1ae87..3b52178 100644
--- a/src/Spiral.elm
+++ b/src/Examples/Spiral.elm
@@ -1,4 +1,4 @@
-module Spiral exposing (main, ui)
+module Examples.Spiral exposing (main, ui)
=
=import Element
=import Svgnew file mode 100644
index 0000000..3321826
--- /dev/null
+++ b/src/Examples/Transformations.elm
@@ -0,0 +1,343 @@
+module Examples.Transformations exposing
+ ( Model
+ , Msg
+ , init
+ , main
+ , ui
+ , update
+ )
+
+import Array exposing (Array)
+import Browser
+import Browser.Events
+import CartesianPlane
+import Dict exposing (Dict)
+import Element exposing (Element)
+import Element.Background as Background
+import Element.Border as Border
+import Element.Input as Input
+import Geometry.Svg
+import Html exposing (Html)
+import Json.Decode exposing (Decoder)
+import LineSegment2d
+import List.Extra as List
+import Point2d
+import Svg exposing (..)
+import Svg.Attributes exposing (..)
+import Transformations exposing (Transformation(..))
+
+
+main : Program () Model Msg
+main =
+ Browser.sandbox
+ { init = init
+ , view = view
+ , update = update
+ }
+
+
+type alias Model =
+ Array Transformation
+
+
+type Msg
+ = AddTransformation Transformation
+ | DeleteTransformation Int
+ | SetTransformation Int Transformation
+
+
+init : Model
+init =
+ Array.fromList
+ [ Translate 0 0
+ , Rotate 0
+ , Scale 1 1
+ ]
+
+
+view : Model -> Html Msg
+view model =
+ Element.layout
+ [ Element.height Element.fill
+ , Element.width Element.fill
+ ]
+ (ui model)
+
+
+ui : Model -> Element Msg
+ui model =
+ let
+ transformations =
+ Array.toList model
+
+ wrapper element =
+ Element.column
+ [ Element.width (Element.maximum 600 Element.fill)
+ , Element.centerX
+ , Element.spacing 20
+ ]
+ [ Element.el
+ [ Element.width Element.fill
+ ]
+ (Element.html element)
+ , Element.el
+ [ Background.color (Element.rgb 1 0.8 0.8)
+ , Element.padding 10
+ , Element.width Element.fill
+ ]
+ (transformationsUI transformations)
+ ]
+
+ shape =
+ g [ transform (Transformations.apply transformations) ]
+ [ line
+ [ x1 "0"
+ , x2 "100"
+ , y1 "0"
+ , y2 "0"
+ , stroke "red"
+ , strokeWidth "1"
+ ]
+ []
+ , circle [ cx "0", cy "0", r "2", fill "red" ] []
+ , grid
+ [ stroke "pink"
+ , fill "pink"
+ , strokeWidth "0.3"
+ ]
+ 10
+ 30
+
+ -- , rect [ x "", y "-2", width "1", height "4" ] []
+ ]
+ in
+ shape
+ |> List.singleton
+ |> CartesianPlane.graph 300
+ |> wrapper
+
+
+transformationsUI : List Transformation -> Element Msg
+transformationsUI transformations =
+ let
+ addButtons =
+ [ Element.text "Add transformation: "
+ , Input.button []
+ { onPress = Just (AddTransformation (Translate 0 0))
+ , label = Element.text "Translate"
+ }
+ , Input.button []
+ { onPress = Just (AddTransformation (Scale 1 1))
+ , label = Element.text "Scale"
+ }
+ , Input.button []
+ { onPress = Just (AddTransformation (Rotate 0))
+ , label = Element.text "Rotate"
+ }
+ ]
+
+ currentTrasformations =
+ transformations
+ |> List.indexedMap transformationUI
+ in
+ Element.column
+ [ Element.width Element.fill
+ , Element.spacing 10
+ ]
+ [ Element.row
+ [ Element.width Element.fill
+ , Element.spacing 10
+ ]
+ addButtons
+ , Element.column
+ [ Element.width Element.fill
+ , Element.spacing 10
+ ]
+ currentTrasformations
+ ]
+
+
+transformationUI : Int -> Transformation -> Element Msg
+transformationUI index transformation =
+ let
+ sliderBackground =
+ Element.el
+ [ Element.width Element.fill
+ , Element.height (Element.px 2)
+ , Element.centerY
+ , Background.color <| Element.rgb 0.7 0.7 0.7
+ , Border.rounded 2
+ ]
+ Element.none
+
+ controls =
+ case transformation of
+ Identity ->
+ [ Element.text "Identity" ]
+
+ Scale horizontal vertical ->
+ [ Input.slider
+ [ Element.behindContent sliderBackground
+ ]
+ { onChange =
+ \x ->
+ SetTransformation index (Scale x vertical)
+ , label = Input.labelLeft [] (Element.text "horizontal")
+ , min = 0
+ , max = 10
+ , value = horizontal
+ , thumb = Input.defaultThumb
+ , step = Just 0.1
+ }
+ , Input.slider
+ [ Element.behindContent sliderBackground
+ ]
+ { onChange =
+ \y ->
+ SetTransformation index (Scale horizontal y)
+ , label = Input.labelLeft [] (Element.text "vertical")
+ , min = 0
+ , max = 10
+ , value = vertical
+ , thumb = Input.defaultThumb
+ , step = Just 0.1
+ }
+ ]
+
+ Translate x y ->
+ [ Input.slider
+ [ Element.behindContent sliderBackground
+ ]
+ { onChange =
+ \value ->
+ SetTransformation index (Translate value y)
+ , label = Input.labelLeft [] (Element.text "x")
+ , min = -100
+ , max = 100
+ , value = x
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ , Input.slider
+ [ Element.behindContent sliderBackground
+ ]
+ { onChange =
+ \value ->
+ SetTransformation index (Translate x value)
+ , label = Input.labelLeft [] (Element.text "y")
+ , min = -100
+ , max = 100
+ , value = y
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ ]
+
+ Rotate angle ->
+ [ Input.slider
+ [ Element.behindContent sliderBackground
+ ]
+ { onChange =
+ \value ->
+ SetTransformation index (Rotate value)
+ , label = Input.labelLeft [] (Element.text "angle")
+ , min = -360
+ , max = 360
+ , value = angle
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ ]
+ in
+ Element.column
+ [ Element.width Element.fill
+ , Border.color (Element.rgb 0.9 0.9 0.9)
+ , Border.width 3
+ , Element.padding 5
+ , Element.spacing 20
+ ]
+ [ Element.row [ Element.width Element.fill ]
+ [ transformation
+ |> List.singleton
+ |> Transformations.apply
+ |> Element.text
+ |> Element.el [ Element.width Element.fill ]
+ , Input.button []
+ { onPress = Just (DeleteTransformation index)
+ , label = Element.text "X"
+ }
+ ]
+ , Element.column
+ [ Element.width Element.fill
+ , Element.spacing 20
+ ]
+ controls
+ ]
+
+
+update : Msg -> Model -> Model
+update msg model =
+ case msg of
+ AddTransformation transformation ->
+ Array.push transformation model
+
+ DeleteTransformation index ->
+ let
+ end =
+ Array.length model
+
+ front =
+ Array.slice 0 index model
+
+ back =
+ Array.slice (index + 1) end model
+ in
+ Array.append front back
+
+ SetTransformation index transformation ->
+ Array.set index transformation model
+
+
+subscriptions : Model -> Sub Msg
+subscriptions model =
+ Sub.none
+
+
+grid : List (Svg.Attribute msg) -> Float -> Float -> Svg msg
+grid attributes unit size =
+ let
+ positiveValues =
+ size
+ / 2
+ |> floor
+ |> List.range 1
+ |> List.map toFloat
+ |> List.map ((*) unit)
+
+ negativeValues =
+ positiveValues
+ |> List.map negate
+
+ max =
+ unit * size / 2
+
+ min =
+ negate max
+ in
+ ((positiveValues ++ negativeValues)
+ |> List.map
+ (\value ->
+ [ ( Point2d.fromCoordinates ( value, min )
+ , Point2d.fromCoordinates ( value, max )
+ )
+ , ( Point2d.fromCoordinates ( min, value )
+ , Point2d.fromCoordinates ( max, value )
+ )
+ ]
+ )
+ |> List.concat
+ |> List.map LineSegment2d.fromEndpoints
+ |> List.map (Geometry.Svg.lineSegment2d attributes)
+ )
+ |> (::) (CartesianPlane.axes attributes (size * unit))
+ |> g []similarity index 98%
rename from src/TransformationsCircle.elm
rename to src/Examples/TransformationsCircle.elm
index 96264ff..a3a507f 100644
--- a/src/TransformationsCircle.elm
+++ b/src/Examples/TransformationsCircle.elm
@@ -1,4 +1,4 @@
-module TransformationsCircle exposing (Config, defaults, main, ui)
+module Examples.TransformationsCircle exposing (Config, defaults, main, ui)
=
=import Element exposing (Element)
=import Html exposing (Html)similarity index 99%
rename from src/Tree.elm
rename to src/Examples/Tree.elm
index e2925a8..eaed7b3 100644
--- a/src/Tree.elm
+++ b/src/Examples/Tree.elm
@@ -1,4 +1,4 @@
-module Tree exposing
+module Examples.Tree exposing
= ( Model
= , Msg
= , init
@@ -19,6 +19,7 @@ import Svg exposing (..)
=import Svg.Attributes exposing (..)
=
=
+main : Program Flags Model Msg
=main =
= Browser.element
= { init = initnew file mode 100644
index 0000000..222da7a
--- /dev/null
+++ b/src/Examples/ViewBox.elm
@@ -0,0 +1,276 @@
+module Examples.ViewBox exposing
+ ( Model
+ , Msg
+ , init
+ , main
+ , ui
+ , update
+ , view
+ )
+
+import Browser
+import BrowserWindow
+import CartesianPlane exposing (graph)
+import Element
+import Element.Background as Background
+import Element.Border as Border
+import Element.Input as Input
+import Html exposing (Html)
+import Svg exposing (..)
+import Svg.Attributes exposing (..)
+
+
+main =
+ Browser.sandbox
+ { init = init
+ , view = view
+ , update = update
+ }
+
+
+type alias Model =
+ { left : Float
+ , top : Float
+ , width : Float
+ , height : Float
+ , preserveAspectRatio : Bool
+ }
+
+
+type Msg
+ = Move Float Float
+ | Resize Float Float
+ | PreserveAspectRatio Bool
+
+
+init : Model
+init =
+ { left = 0
+ , top = 0
+ , width = 400
+ , height = 400
+ , preserveAspectRatio = False
+ }
+
+
+view : Model -> Html.Html Msg
+view model =
+ let
+ wrapper element =
+ Element.el
+ [ Element.width (Element.maximum 1200 Element.fill)
+ , Element.height Element.fill
+ , Element.centerX
+ ]
+ element
+ in
+ ui model
+ |> wrapper
+ |> Element.layout
+ [ Element.height Element.fill
+ , Element.width Element.fill
+ ]
+
+
+update : Msg -> Model -> Model
+update msg model =
+ case msg of
+ Move left top ->
+ { model
+ | left = left
+ , top = top
+ }
+
+ Resize width height ->
+ { model
+ | width = width
+ , height = height
+ }
+
+ PreserveAspectRatio value ->
+ { model | preserveAspectRatio = value }
+
+
+ui model =
+ let
+ viewbox =
+ svg
+ [ viewBox "-500 -500 1000 1000"
+ ]
+ [ g [] world
+ , rect
+ [ x (String.fromFloat model.left)
+ , y (String.fromFloat model.top)
+ , width (String.fromFloat model.width)
+ , height (String.fromFloat model.height)
+ , opacity "0.3"
+ , stroke "white"
+ , fill "pink"
+ ]
+ []
+ ]
+ |> Element.html
+ |> Element.el
+ [ Element.centerX
+ , Element.centerY
+ , Element.width Element.fill
+ , Element.height Element.fill
+ ]
+
+ viewport =
+ svg
+ [ [ model.left, model.top, model.width, model.height ]
+ |> List.map String.fromFloat
+ |> String.join " "
+ |> viewBox
+ , preserveAspectRatio <|
+ case model.preserveAspectRatio of
+ True ->
+ "xMidYMid meet"
+
+ False ->
+ "none"
+ , Svg.Attributes.style "width: 100%; height: 100%; flex-grow: 1; flex-basis: 0"
+ ]
+ [ g [] world
+ , rect
+ [ x (String.fromFloat model.left)
+ , y (String.fromFloat model.top)
+ , width (String.fromFloat model.width)
+ , height (String.fromFloat model.height)
+ , opacity "0.3"
+ , stroke "white"
+ , fill "pink"
+ ]
+ []
+ ]
+ |> Element.html
+ |> Element.el
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ |> BrowserWindow.window
+ [ Element.centerX
+ , Element.centerY
+ , Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ in
+ Element.column
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ , Element.spacing 30
+ , Element.padding 30
+ ]
+ [ Element.row
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ , Element.centerX
+ , Element.spacing 30
+ ]
+ [ viewbox
+ , viewport
+ ]
+ , Input.slider
+ [ Element.behindContent
+ (Element.el
+ [ Element.width Element.fill
+ , Element.height (Element.px 2)
+ , Element.centerY
+ , Background.color <| Element.rgb 0.7 0.7 0.7
+ , Border.rounded 2
+ ]
+ Element.none
+ )
+ ]
+ { onChange = \left -> Move left model.top
+ , label =
+ Input.labelBelow [ Element.centerX ] <|
+ Element.text ("left: " ++ String.fromFloat model.left)
+ , min = -500
+ , max = 500
+ , value = model.left
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ , Input.slider
+ [ Element.behindContent
+ (Element.el
+ [ Element.width Element.fill
+ , Element.height (Element.px 2)
+ , Element.centerY
+ , Background.color <| Element.rgb 0.7 0.7 0.7
+ , Border.rounded 2
+ ]
+ Element.none
+ )
+ ]
+ { onChange = \top -> Move model.left top
+ , label =
+ Input.labelBelow [ Element.centerX ] <|
+ Element.text ("top: " ++ String.fromFloat model.top)
+ , min = -500
+ , max = 500
+ , value = model.top
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ , Input.slider
+ [ Element.behindContent
+ (Element.el
+ [ Element.width Element.fill
+ , Element.height (Element.px 2)
+ , Element.centerY
+ , Background.color <| Element.rgb 0.7 0.7 0.7
+ , Border.rounded 2
+ ]
+ Element.none
+ )
+ ]
+ { onChange = \width -> Resize width model.height
+ , label =
+ Input.labelBelow [ Element.centerX ] <|
+ Element.text ("width: " ++ String.fromFloat model.width)
+ , min = 1
+ , max = 500
+ , value = model.width
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ , Input.slider
+ [ Element.behindContent
+ (Element.el
+ [ Element.width Element.fill
+ , Element.height (Element.px 2)
+ , Element.centerY
+ , Background.color <| Element.rgb 0.7 0.7 0.7
+ , Border.rounded 2
+ ]
+ Element.none
+ )
+ ]
+ { onChange = \height -> Resize model.width height
+ , label =
+ Input.labelBelow [ Element.centerX ] <|
+ Element.text ("height: " ++ String.fromFloat model.height)
+ , min = 1
+ , max = 500
+ , value = model.height
+ , thumb = Input.defaultThumb
+ , step = Just 1
+ }
+ , Input.checkbox []
+ { checked = model.preserveAspectRatio
+ , icon = Input.defaultCheckbox
+ , label = Input.labelRight [] (Element.text "Preserve aspect ratio")
+ , onChange = PreserveAspectRatio
+ }
+ ]
+
+
+world : List (Svg Msg)
+world =
+ [ circle [ cx "400", cy "300", r "250", fill "purple" ] []
+ , circle [ cx "200", cy "350", r "50", fill "yellow" ] []
+ , circle [ cx "0", cy "0", r "20", fill "red" ] []
+ ]index ab8ac60..99d1276 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -10,41 +10,41 @@ import Basics.Extra exposing (curry)
=import Browser
=import Browser.Navigation as Navigation
=import BrowserWindow
-import CartesianCoordinates
-import CenteredDot
-import Counter
=import Dict
-import DotAtTheCenterOfTheScreen
=import Element exposing (Element)
=import Element.Background as Background
=import Element.Border as Border
=import Element.Events
=import Element.Font as Font
=import Element.Input as Input
+import Examples.CartesianCoordinates
+import Examples.CenteredDot
+import Examples.Counter
+import Examples.DotAtTheCenterOfTheScreen
+import Examples.FillTheScreen
+import Examples.Gradient
+import Examples.Line
+import Examples.NestedTransformations
+import Examples.PolarCoordinates
+import Examples.RosetteTypedTransformations
+import Examples.Simplest
+import Examples.Spiral
+import Examples.Transformations
+import Examples.TransformationsCircle
+import Examples.Tree
+import Examples.ViewBox
=import FeatherIcons exposing (icons)
-import FillTheScreen
-import Gradient
=import Html exposing (Html)
=import Html.Attributes
=import Http
-import Line
=import Mark
=import Mark.Custom
=import Mark.Default
-import NestedTransformations
=import Parser
=import Parser.Advanced
-import PolarCoordinates
=import Result.Extra as Result
-import RosetteTypedTransformations
=import Routes exposing (Route)
-import Simplest
-import Spiral
-import Transformations
-import TransformationsCircle
-import Tree
=import Url exposing (Url)
-import ViewBox
=
=
=main : Program Flags Model Msg
@@ -67,13 +67,13 @@ type alias Model =
= { url : Url
= , key : Navigation.Key
= , markup : Maybe String
- , counter : Counter.Model
- , transformations : Transformations.Model
- , nestedTransformations : NestedTransformations.Model
- , cartesianCoordinates : CartesianCoordinates.Model
- , polarCoordinates : PolarCoordinates.Model
- , tree : Maybe Tree.Model
- , viewBox : ViewBox.Model
+ , counter : Examples.Counter.Model
+ , transformations : Examples.Transformations.Model
+ , nestedTransformations : Examples.NestedTransformations.Model
+ , cartesianCoordinates : Examples.CartesianCoordinates.Model
+ , polarCoordinates : Examples.PolarCoordinates.Model
+ , tree : Maybe Examples.Tree.Model
+ , viewBox : Examples.ViewBox.Model
= }
=
=
@@ -81,14 +81,14 @@ type Msg
= = UrlRequested Browser.UrlRequest
= | UrlChanged Url
= | ContentFetched (Result Http.Error String)
- | CounterMsg Counter.Msg
- | TransformationsMsg Transformations.Msg
- | NestedTransformationsMsg NestedTransformations.Msg
- | CartesianCoordinatesMsg CartesianCoordinates.Msg
- | PolarCoordinatesMsg PolarCoordinates.Msg
- | ToggleTree (Maybe Tree.Model)
- | TreeMsg Tree.Msg
- | ViewBoxMsg ViewBox.Msg
+ | CounterMsg Examples.Counter.Msg
+ | TransformationsMsg Examples.Transformations.Msg
+ | NestedTransformationsMsg Examples.NestedTransformations.Msg
+ | CartesianCoordinatesMsg Examples.CartesianCoordinates.Msg
+ | PolarCoordinatesMsg Examples.PolarCoordinates.Msg
+ | ToggleTree (Maybe Examples.Tree.Model)
+ | TreeMsg Examples.Tree.Msg
+ | ViewBoxMsg Examples.ViewBox.Msg
=
=
=init : Flags -> Url -> Navigation.Key -> ( Model, Cmd Msg )
@@ -96,13 +96,13 @@ init flags url key =
= ( { url = url
= , key = key
= , markup = Nothing
- , counter = Counter.init
- , transformations = Transformations.init
- , nestedTransformations = NestedTransformations.init
- , cartesianCoordinates = CartesianCoordinates.init
- , polarCoordinates = PolarCoordinates.init
+ , counter = Examples.Counter.init
+ , transformations = Examples.Transformations.init
+ , nestedTransformations = Examples.NestedTransformations.init
+ , cartesianCoordinates = Examples.CartesianCoordinates.init
+ , polarCoordinates = Examples.PolarCoordinates.init
= , tree = Nothing
- , viewBox = ViewBox.init
+ , viewBox = Examples.ViewBox.init
= }
= , url
= |> Routes.parse
@@ -307,27 +307,39 @@ update msg model =
= )
=
= CounterMsg m ->
- ( { model | counter = Counter.update m model.counter }
+ ( { model | counter = Examples.Counter.update m model.counter }
= , Cmd.none
= )
=
= TransformationsMsg m ->
- ( { model | transformations = Transformations.update m model.transformations }
+ ( { model
+ | transformations =
+ Examples.Transformations.update m model.transformations
+ }
= , Cmd.none
= )
=
= NestedTransformationsMsg m ->
- ( { model | nestedTransformations = NestedTransformations.update m model.nestedTransformations }
+ ( { model
+ | nestedTransformations =
+ Examples.NestedTransformations.update m model.nestedTransformations
+ }
= , Cmd.none
= )
=
= CartesianCoordinatesMsg m ->
- ( { model | cartesianCoordinates = CartesianCoordinates.update m model.cartesianCoordinates }
+ ( { model
+ | cartesianCoordinates =
+ Examples.CartesianCoordinates.update m model.cartesianCoordinates
+ }
= , Cmd.none
= )
=
= PolarCoordinatesMsg m ->
- ( { model | polarCoordinates = PolarCoordinates.update m model.polarCoordinates }
+ ( { model
+ | polarCoordinates =
+ Examples.PolarCoordinates.update m model.polarCoordinates
+ }
= , Cmd.none
= )
=
@@ -337,7 +349,7 @@ update msg model =
= TreeMsg m ->
= case model.tree of
= Just tree ->
- Tree.update m tree
+ Examples.Tree.update m tree
= |> (\( newTree, treeCmd ) ->
= ( { model | tree = Just newTree }
= , Cmd.map TreeMsg treeCmd
@@ -348,7 +360,7 @@ update msg model =
= ( model, Cmd.none )
=
= ViewBoxMsg m ->
- ( { model | viewBox = ViewBox.update m model.viewBox }, Cmd.none )
+ ( { model | viewBox = Examples.ViewBox.update m model.viewBox }, Cmd.none )
=
=
=subscriptions : Model -> Sub Msg
@@ -358,7 +370,7 @@ subscriptions model =
= Sub.none
=
= Just tree ->
- Tree.subscriptions tree
+ Examples.Tree.subscriptions tree
= |> Sub.map TreeMsg
=
=
@@ -472,7 +484,7 @@ document =
= let
= render model =
= model.counter
- |> Counter.ui
+ |> Examples.Counter.ui
= |> Element.el
= [ Element.centerX
= , Element.centerY
@@ -489,9 +501,9 @@ document =
= simplest : Mark.Block (Model -> Element Msg)
= simplest =
= let
- render : Simplest.Config -> Model -> Element Msg
+ render : Examples.Simplest.Config -> Model -> Element Msg
= render config model =
- Simplest.ui config
+ Examples.Simplest.ui config
= |> Element.html
= |> Element.el []
= |> Element.el
@@ -502,7 +514,7 @@ document =
= |> BrowserWindow.window []
= in
= Mark.record2 "Simplest"
- Simplest.Config
+ Examples.Simplest.Config
= (Mark.field "background" Mark.string)
= (Mark.field "fill" Mark.string)
= |> Mark.map render
@@ -511,7 +523,7 @@ document =
= fillTheScreen =
= let
= render model =
- FillTheScreen.ui
+ Examples.FillTheScreen.ui
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -524,7 +536,7 @@ document =
= dotAtTheCenterOfTheScreen =
= let
= render model =
- DotAtTheCenterOfTheScreen.ui
+ Examples.DotAtTheCenterOfTheScreen.ui
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -537,7 +549,7 @@ document =
= centeredDot =
= let
= render model =
- CenteredDot.main
+ Examples.CenteredDot.main
= |> Element.html
= |> Element.el
= [ Element.height (Element.px 400)
@@ -550,9 +562,9 @@ document =
= transformationsCircle : Mark.Block (Model -> Element Msg)
= transformationsCircle =
= let
- render : TransformationsCircle.Config -> Model -> Element Msg
+ render : Examples.TransformationsCircle.Config -> Model -> Element Msg
= render config model =
- TransformationsCircle.ui config
+ Examples.TransformationsCircle.ui config
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -561,7 +573,7 @@ document =
= |> BrowserWindow.window []
= in
= Mark.record4 "TransformationsCircle"
- TransformationsCircle.Config
+ Examples.TransformationsCircle.Config
= (Mark.field "circle" Mark.bool)
= (Mark.field "center" Mark.bool)
= (Mark.field "angle" Mark.bool)
@@ -572,7 +584,7 @@ document =
= line =
= let
= render model =
- Line.ui
+ Examples.Line.ui
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -585,7 +597,7 @@ document =
= gradient =
= let
= render model =
- Gradient.ui
+ Examples.Gradient.ui
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -599,7 +611,7 @@ document =
= let
= render model =
= model.transformations
- |> Transformations.ui
+ |> Examples.Transformations.ui
= |> Element.el
= [ Element.width Element.fill
= ]
@@ -613,7 +625,7 @@ document =
= let
= render model =
= model.nestedTransformations
- |> NestedTransformations.ui
+ |> Examples.NestedTransformations.ui
= |> Element.el
= [ Element.width Element.fill
= ]
@@ -627,7 +639,7 @@ document =
= let
= render model =
= model.cartesianCoordinates
- |> CartesianCoordinates.ui
+ |> Examples.CartesianCoordinates.ui
= |> Element.el
= [ Element.width Element.fill
= ]
@@ -641,7 +653,7 @@ document =
= let
= render model =
= model.polarCoordinates
- |> PolarCoordinates.ui
+ |> Examples.PolarCoordinates.ui
= |> Element.el
= [ Element.width Element.fill
= ]
@@ -654,7 +666,7 @@ document =
= rosette =
= let
= render model =
- RosetteTypedTransformations.ui
+ Examples.RosetteTypedTransformations.ui
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -667,7 +679,7 @@ document =
= spiral =
= let
= render model =
- Spiral.ui
+ Examples.Spiral.ui
= |> Element.el
= [ Element.height (Element.px 400)
= , Element.width Element.fill
@@ -681,7 +693,7 @@ document =
= let
= render model =
= model.tree
- |> Maybe.map Tree.ui
+ |> Maybe.map Examples.Tree.ui
= |> Maybe.withDefault Element.none
= |> Element.el
= [ Element.height (Element.px 600)
@@ -697,7 +709,7 @@ document =
= let
= render model =
= model.viewBox
- |> ViewBox.ui
+ |> Examples.ViewBox.ui
= |> Element.el
= [ Element.width Element.fill
= ]index 1b3937d..d72965f 100644
--- a/src/Transformations.elm
+++ b/src/Transformations.elm
@@ -1,45 +1,8 @@
=module Transformations exposing
- ( Model
- , Msg
- , Transformation(..)
+ ( Transformation(..)
= , apply
- , init
- , main
- , ui
- , update
= )
=
-import Array exposing (Array)
-import Browser
-import Browser.Events
-import CartesianPlane
-import Dict exposing (Dict)
-import Element exposing (Element)
-import Element.Background as Background
-import Element.Border as Border
-import Element.Input as Input
-import Geometry.Svg
-import Html exposing (Html)
-import Json.Decode exposing (Decoder)
-import LineSegment2d
-import List.Extra as List
-import Point2d
-import Svg exposing (..)
-import Svg.Attributes exposing (..)
-
-
-main : Program () Model Msg
-main =
- Browser.sandbox
- { init = init
- , view = view
- , update = update
- }
-
-
-type alias Model =
- Array Transformation
-
=
=type Transformation
= = Identity
@@ -48,269 +11,6 @@ type Transformation
= | Rotate Float
=
=
-type Msg
- = AddTransformation Transformation
- | DeleteTransformation Int
- | SetTransformation Int Transformation
-
-
-init : Model
-init =
- Array.fromList
- [ Translate 0 0
- , Rotate 0
- , Scale 1 1
- ]
-
-
-view : Model -> Html Msg
-view model =
- Element.layout
- [ Element.height Element.fill
- , Element.width Element.fill
- ]
- (ui model)
-
-
-ui : Model -> Element Msg
-ui model =
- let
- transformations =
- Array.toList model
-
- wrapper element =
- Element.column
- [ Element.width (Element.maximum 600 Element.fill)
- , Element.centerX
- , Element.spacing 20
- ]
- [ Element.el
- [ Element.width Element.fill
- ]
- (Element.html element)
- , Element.el
- [ Background.color (Element.rgb 1 0.8 0.8)
- , Element.padding 10
- , Element.width Element.fill
- ]
- (transformationsUI transformations)
- ]
-
- shape =
- g [ transform (apply transformations) ]
- [ line
- [ x1 "0"
- , x2 "100"
- , y1 "0"
- , y2 "0"
- , stroke "red"
- , strokeWidth "1"
- ]
- []
- , circle [ cx "0", cy "0", r "2", fill "red" ] []
- , grid
- [ stroke "pink"
- , fill "pink"
- , strokeWidth "0.3"
- ]
- 10
- 30
-
- -- , rect [ x "", y "-2", width "1", height "4" ] []
- ]
- in
- shape
- |> List.singleton
- |> CartesianPlane.graph 300
- |> wrapper
-
-
-transformationsUI : List Transformation -> Element Msg
-transformationsUI transformations =
- let
- addButtons =
- [ Element.text "Add transformation: "
- , Input.button []
- { onPress = Just (AddTransformation (Translate 0 0))
- , label = Element.text "Translate"
- }
- , Input.button []
- { onPress = Just (AddTransformation (Scale 1 1))
- , label = Element.text "Scale"
- }
- , Input.button []
- { onPress = Just (AddTransformation (Rotate 0))
- , label = Element.text "Rotate"
- }
- ]
-
- currentTrasformations =
- transformations
- |> List.indexedMap transformationUI
- in
- Element.column
- [ Element.width Element.fill
- , Element.spacing 10
- ]
- [ Element.row
- [ Element.width Element.fill
- , Element.spacing 10
- ]
- addButtons
- , Element.column
- [ Element.width Element.fill
- , Element.spacing 10
- ]
- currentTrasformations
- ]
-
-
-transformationUI : Int -> Transformation -> Element Msg
-transformationUI index transformation =
- let
- sliderBackground =
- Element.el
- [ Element.width Element.fill
- , Element.height (Element.px 2)
- , Element.centerY
- , Background.color <| Element.rgb 0.7 0.7 0.7
- , Border.rounded 2
- ]
- Element.none
-
- controls =
- case transformation of
- Identity ->
- [ Element.text "Identity" ]
-
- Scale horizontal vertical ->
- [ Input.slider
- [ Element.behindContent sliderBackground
- ]
- { onChange =
- \x ->
- SetTransformation index (Scale x vertical)
- , label = Input.labelLeft [] (Element.text "horizontal")
- , min = 0
- , max = 10
- , value = horizontal
- , thumb = Input.defaultThumb
- , step = Just 0.1
- }
- , Input.slider
- [ Element.behindContent sliderBackground
- ]
- { onChange =
- \y ->
- SetTransformation index (Scale horizontal y)
- , label = Input.labelLeft [] (Element.text "vertical")
- , min = 0
- , max = 10
- , value = vertical
- , thumb = Input.defaultThumb
- , step = Just 0.1
- }
- ]
-
- Translate x y ->
- [ Input.slider
- [ Element.behindContent sliderBackground
- ]
- { onChange =
- \value ->
- SetTransformation index (Translate value y)
- , label = Input.labelLeft [] (Element.text "x")
- , min = -100
- , max = 100
- , value = x
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- , Input.slider
- [ Element.behindContent sliderBackground
- ]
- { onChange =
- \value ->
- SetTransformation index (Translate x value)
- , label = Input.labelLeft [] (Element.text "y")
- , min = -100
- , max = 100
- , value = y
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- ]
-
- Rotate angle ->
- [ Input.slider
- [ Element.behindContent sliderBackground
- ]
- { onChange =
- \value ->
- SetTransformation index (Rotate value)
- , label = Input.labelLeft [] (Element.text "angle")
- , min = -360
- , max = 360
- , value = angle
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- ]
- in
- Element.column
- [ Element.width Element.fill
- , Border.color (Element.rgb 0.9 0.9 0.9)
- , Border.width 3
- , Element.padding 5
- , Element.spacing 20
- ]
- [ Element.row [ Element.width Element.fill ]
- [ transformation
- |> List.singleton
- |> apply
- |> Element.text
- |> Element.el [ Element.width Element.fill ]
- , Input.button []
- { onPress = Just (DeleteTransformation index)
- , label = Element.text "X"
- }
- ]
- , Element.column
- [ Element.width Element.fill
- , Element.spacing 20
- ]
- controls
- ]
-
-
-update : Msg -> Model -> Model
-update msg model =
- case msg of
- AddTransformation transformation ->
- Array.push transformation model
-
- DeleteTransformation index ->
- let
- end =
- Array.length model
-
- front =
- Array.slice 0 index model
-
- back =
- Array.slice (index + 1) end model
- in
- Array.append front back
-
- SetTransformation index transformation ->
- Array.set index transformation model
-
-
-subscriptions : Model -> Sub Msg
-subscriptions model =
- Sub.none
-
-
=apply : List Transformation -> String
=apply transformations =
= let
@@ -342,43 +42,3 @@ apply transformations =
= transformations
= |> List.map toString
= |> String.join " "
-
-
-grid : List (Svg.Attribute msg) -> Float -> Float -> Svg msg
-grid attributes unit size =
- let
- positiveValues =
- size
- / 2
- |> floor
- |> List.range 1
- |> List.map toFloat
- |> List.map ((*) unit)
-
- negativeValues =
- positiveValues
- |> List.map negate
-
- max =
- unit * size / 2
-
- min =
- negate max
- in
- ((positiveValues ++ negativeValues)
- |> List.map
- (\value ->
- [ ( Point2d.fromCoordinates ( value, min )
- , Point2d.fromCoordinates ( value, max )
- )
- , ( Point2d.fromCoordinates ( min, value )
- , Point2d.fromCoordinates ( max, value )
- )
- ]
- )
- |> List.concat
- |> List.map LineSegment2d.fromEndpoints
- |> List.map (Geometry.Svg.lineSegment2d attributes)
- )
- |> (::) (CartesianPlane.axes attributes (size * unit))
- |> g []More progress on Day 1
On by
index 8359570..beac6da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
=/public/
=/built/
=/node_modules/
+/src/Playground.elmindex 83cc9bf..9cf6974 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -85,7 +85,11 @@ Note that the same address was printed by the Elm reactor.
=
=We want to display a dot at the center of the screen, like this:
=
-| DotAtTheCenterOfTheScreen
+| DotWithViewBox
+ background=none
+ fill=black
+ viewBox=-300 -300 600 600
+
=
=Below is the complete code to draw a dot like this, but don't type it in your editor yet! We are going to recreate it together, step by step.
=
@@ -128,9 +132,8 @@ Its all about drawing shapes on the screen. Let's install an Elm Package to help
=Now that we have {Code|elm//svg} installed, we can write the code that will draw our dot:
=
=| Code
- module Simplest exposing (main)
+ module Main exposing (main)
=
- import Element
= import Svg
= import Svg.Attributes
=
@@ -138,9 +141,7 @@ Now that we have {Code|elm//svg} installed, we can write the code that will draw
= main =
= Svg.svg []
= [ Svg.circle
- [ Svg.Attributes.r "10"
- ]
- []
+ [ Svg.Attributes.r "10" ] []
= ]
=
=Start the reactor again:
@@ -153,7 +154,7 @@ Start the reactor again:
=
=Reload the browser. You should see something like this:
=
-| Simplest
+| Dot
= background=none
= fill=black
=
@@ -163,15 +164,22 @@ There are two reasons. First, because the center of the dot is at a point called
=
=Second, it's because the SVG space doesn't fill the browser window. Don't believe me? We can see that the space doesn't fill the window by changing the background color of the SVG element.
=
-| Note
- Code sample for simplest with pink background should be here.
+| Code
+ module Main exposing (main)
=
-When you reload the browser, you'll see this:
+ import Svg
+ import Svg.Attributes
=
-| Note
- Example of simplest with pink background should be here.
=
-| Simplest
+ main =
+ Svg.svg [ Svg.Attributes.style "background: pink" ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10" ] []
+ ]
+
+When you reload the browser, you'll see this:
+
+| Dot
= background=pink
= fill=black
=
@@ -185,11 +193,42 @@ Press {Code|CTRL + C} to stop the elm-reactor, type {Code|elm install mdgriffith
=
=Then in {Code|src//Main.elm} add the necessary import {Code|import Element} and change {Code|Main} to look like this:
=
-Main = * the code of Element.layout should be here*
+| Code
+ module Main exposing (main)
=
-Take a wild guess: what do you think {Code|Element.height Element.fill} and {Code|Element.height Element.width} do?
+ import Element
+ import Svg
+ import Svg.Attributes
=
-Reload the browser to confirm your hypothesis. Voila! The SVG space now fills the screen. It should now be possible to place our dot in the center of the screen. But, how exactly will we achieve it?
+
+ main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (Element.html
+ (Svg.svg
+ [ Svg.Attributes.height "100%"
+ , Svg.Attributes.width "100%"
+ , Svg.Attributes.style "background: pink"
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10" ] []
+ ]
+ )
+ )
+
+Take a wild guess: what do you think {Code|Element.height Element.fill}, {Code|Svg.Attributes.height "100%"}, {Code|Element.width Element.fill} and {Code|Svg.Attributes.width "100%"} do?
+
+Reload the browser to confirm your hypothesis. Voila! The SVG space now fills the screen.
+
+| DotInElement
+ background=pink
+ fill=black
+ cx=0
+ cy=0
+
+It should now be possible to place our dot in the center of the screen. But, how exactly will we achieve it?
=
=Let's return to the idea we introduced earlier, that the center of the dot is at a point called the {Code|origin} or {Code|(0, 0)}. What eactly does this mean?
=
@@ -203,7 +242,40 @@ Knowing that the center of the dot is at the {Code|origin} or point {Code|(0,0)}
=
=To change the position of the dot, we can use the {Code|cx} and {Code|cy} attributes of the {Code|circle} element.
=
-* simplest with cx and cy should be here *
+| Code
+ module Main exposing (main)
+
+ import Element
+ import Svg
+ import Svg.Attributes
+
+
+ main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (Element.html
+ (Svg.svg
+ [ Svg.Attributes.height "100%"
+ , Svg.Attributes.width "100%"
+ , Svg.Attributes.style "background: pink"
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "100"
+ , Svg.Attributes.cy "50"
+ ]
+ []
+ ]
+ )
+ )
+
+| DotInElement
+ background=pink
+ fill=black
+ cx=100
+ cy=50
=
=Now, if we want our dot to be exactly in the center of the screen, we'll have to set {Code|cx} and {Code|cy} to values equal to exactly half of the {Code|width} and {Code|height} of the SVG space.
=
@@ -213,7 +285,7 @@ We can calculate the position of the circle as:
= cx = width/2
= cy = height/2
=
-There is a problem though! We don't actually know the width and height of the SVG space. All we know is that its {Code|width} and {Code|height} will {Code|fill} the viewport, whatever its size.
+There is a problem though! We don't actually know the width and height of the SVG space. All we know is that out {Code|layout's} {Code|width} and {Code|height} will {Code|fill} the viewport, and the {Code|svg} space's {Code|width} and {Code|height} are {Code|100%} of the {Code|layout}. We don't know the exact size of either (because the {Code|layout} will scale to the browser window).
=☹️
=
=Fortunately, we don't need to know the width and height of the SVG space!
@@ -226,12 +298,37 @@ A videwbox is like a window into an SVG space. It allows us to change the point
=
=| ViewBox
=
-In this example, we can set the width and height of the viewbox to an arbitrary value. As we see in the interactive example, the width and height of the viewbox will effect how big the dot appears, but that's not so important to us at the moment. Let's set them both to 1000.
+In this example, we can set the width and height of the viewbox to an arbitrary value. As we see in the interactive example, the width and height of the viewbox will effect how big the dot appears, but that's not so important to us at the moment. Let's set them both to 600.
+
+The top and left values of the viewbox are a bit trickier. We saw ealier that if we knew the width and height of our SVG scene, we could have set the cx and cy values of the dot to half the width and height of the scene to center the dot. We will have to use similar reasoning here. If we set the top and left values of the viewbox to 0, the dot will still still appear in the top left corner of the scene. If we want to see the dot moved to the right and downward within the scene, we will need the top and left values of the viewbox to be negative. If we want the origin of the SVG space to appear directly in the center of the scene, we will need to set the top and left values of the viewbox to {Code|- height//2} and {Code|- width//2}. In this case, they will both have the value 300.
+
+| Code
+ module Main exposing (main)
+
+ import Element
+ import Svg
+ import Svg.Attributes
+
=
-The top and left values of the viewbox are a bit trickier. We saw ealier that if we knew the width and height of our SVG scene, we could have set the cx and cy values of the dot to half the width and height of the scene to center the dot. We will have to use similar reasoning here. If we set the top and left values of the viewbox to 0, the dot will still still appear in the top left corner of the scene. If we want to see the dot moved to the right and downward within the scene, we will need the top and left values of the viewbox to be negative. If we want the origin of the SVG space to appear directly in the center of the scene, we will need to set the top and left values of the viewbox to {Code|- height//2} and {Code|- width//2}. In this case, they will both have the value 500.
+ main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (Element.html
+ (Svg.svg
+ [ Svg.Attributes.viewBox "-300 -300 600 600" ]
+ [ Svg.circle [ Svg.Attributes.r "10" ] []
+ ]
+ )
+ )
=
=Refresh the broswer. We should now see the dot in the center of the screen.
=
+| DotWithViewBox
+ background=none
+ fill=black
+ viewBox=-300 -300 600 600
=
=Give a color to the dot
=similarity index 91%
rename from src/Simplest.elm
rename to src/Dot.elm
index 2e65fa4..0f6eec4 100644
--- a/src/Simplest.elm
+++ b/src/Dot.elm
@@ -1,4 +1,4 @@
-module Simplest exposing (Config, defaults, ui)
+module Dot exposing (Config, defaults, ui)
=
=import Html exposing (Html)
=import Svgdeleted file mode 100644
index 83f0d1d..0000000
--- a/src/DotAtTheCenterOfTheScreen.elm
+++ /dev/null
@@ -1,27 +0,0 @@
-module DotAtTheCenterOfTheScreen exposing (main, ui)
-
-import Element
-import Svg
-import Svg.Attributes
-
-
-main =
- Element.layout
- [ Element.width Element.fill
- , Element.height Element.fill
- ]
- ui
-
-
-ui =
- Svg.svg
- [ Svg.Attributes.viewBox "-100 -100 200 200"
- ]
- [ Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- ]
- []
- ]
- |> Element.htmlnew file mode 100644
index 0000000..a3e3397
--- /dev/null
+++ b/src/DotInElement.elm
@@ -0,0 +1,44 @@
+module DotInElement exposing (Config, main, ui)
+
+import Element exposing (Element)
+import Svg
+import Svg.Attributes
+
+
+type alias Config =
+ { background : String
+ , fill : String
+ , cx : String
+ , cy : String
+ }
+
+
+defaults : Config
+defaults =
+ Config "pink" "black" "0" "0"
+
+
+main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (ui defaults)
+
+
+ui : Config -> Element msg
+ui { background, fill, cx, cy } =
+ Svg.svg
+ [ Svg.Attributes.height "100%"
+ , Svg.Attributes.width "100%"
+ , Svg.Attributes.style <| "background: " ++ background
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill fill
+ , Svg.Attributes.cx cx
+ , Svg.Attributes.cy cy
+ ]
+ []
+ ]
+ |> Element.htmlsimilarity index 66%
rename from src/CenteredDot.elm
rename to src/DotWithViewBox.elm
index 59fb692..d26753c 100644
--- a/src/CenteredDot.elm
+++ b/src/DotWithViewBox.elm
@@ -1,4 +1,9 @@
-module CenteredDot exposing (main)
+module DotWithViewBox exposing (Config, main, ui)
+
+import Element
+import Svg
+import Svg.Attributes
+
=
={-| This program demonstrates how to center an element within an SVG viewport. The idea is to make sure that (0, 0) point (so called origin) should be in the middle of the ViewBox. We can achive that, by making the top-left corner of the ViewBox same distance from the (0, 0) as the bottom right.
=
@@ -18,23 +23,35 @@ In fact it doesnt matter how wide and high the viewBox is. As long as the top wi
=That's the trick to position an object (like a dot) exactly in the center of the SVG viewport
=
=-}
+type alias Config =
+ { background : String
+ , fill : String
+ , viewBox : String
+ }
=
-import Element
-import Svg
-import Svg.Attributes
+
+defaults : Config
+defaults =
+ Config "white" "black" "-500 -500 1000 1000"
=
=
=main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (ui defaults)
+
+
+ui { background, fill, viewBox } =
= Svg.svg
- [ Svg.Attributes.style "background: pink"
- , Svg.Attributes.width "300"
- , Svg.Attributes.height "150"
- , Svg.Attributes.viewBox "-100 -100 200 200"
+ [ Svg.Attributes.viewBox viewBox
+ , Svg.Attributes.style <| "background: " ++ background
= ]
= [ Svg.circle
= [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill fill
= ]
= []
= ]
+ |> Element.htmldeleted file mode 100644
index 56f88d6..0000000
--- a/src/FillTheScreen.elm
+++ /dev/null
@@ -1,28 +0,0 @@
-module FillTheScreen exposing (main, ui)
-
-import Element
-import Svg
-import Svg.Attributes
-
-
-main =
- Element.layout
- [ Element.width Element.fill
- , Element.height Element.fill
- ]
- ui
-
-
-ui =
- Svg.svg
- [ Svg.Attributes.style "background: pink"
- , Svg.Attributes.viewBox "-100 -100 200 200"
- ]
- [ Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- ]
- []
- ]
- |> Element.htmlindex 019ba58..87b6396 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -11,10 +11,11 @@ import Browser
=import Browser.Navigation as Navigation
=import BrowserWindow
=import CartesianCoordinates
-import CenteredDot
=import Counter
=import Dict
-import DotAtTheCenterOfTheScreen
+import Dot
+import DotInElement
+import DotWithViewBox
=import Element exposing (Element)
=import Element.Background as Background
=import Element.Border as Border
@@ -22,7 +23,6 @@ import Element.Events
=import Element.Font as Font
=import Element.Input as Input
=import FeatherIcons exposing (icons)
-import FillTheScreen
=import Gradient
=import Html exposing (Html)
=import Html.Attributes
@@ -38,7 +38,6 @@ import PolarCoordinates
=import Result.Extra as Result
=import RosetteTypedTransformations
=import Routes exposing (Route)
-import Simplest
=import Spiral
=import Transformations
=import Tree
@@ -447,10 +446,9 @@ document =
=
= -- Embeded programs
= , counter
- , simplest
- , fillTheScreen
- , dotAtTheCenterOfTheScreen
- , centeredDot
+ , dot
+ , dotInElement
+ , dotWithViewBox
= , line
= , gradient
= , transformations
@@ -484,66 +482,54 @@ document =
= in
= Mark.stub "Counter" render
=
- simplest : Mark.Block (Model -> Element Msg)
- simplest =
+ dot : Mark.Block (Model -> Element Msg)
+ dot =
= let
- render : Simplest.Config -> Model -> Element Msg
+ render : Dot.Config -> Model -> Element Msg
= render config model =
- Simplest.ui config
+ Dot.ui config
= |> Element.html
- |> Element.el []
= |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
+ [ Element.width (Element.px 300)
= , Element.padding 5
= ]
- |> BrowserWindow.window []
+ |> BrowserWindow.window [ Element.height (Element.px 300) ]
= in
- Mark.record2 "Simplest"
- Simplest.Config
+ Mark.record2 "Dot"
+ Dot.Config
= (Mark.field "background" Mark.string)
= (Mark.field "fill" Mark.string)
= |> Mark.map render
=
- fillTheScreen : Mark.Block (Model -> Element Msg)
- fillTheScreen =
- let
- render model =
- FillTheScreen.ui
- |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- ]
- |> BrowserWindow.window []
- in
- Mark.stub "FillTheScreen" render
-
- dotAtTheCenterOfTheScreen : Mark.Block (Model -> Element Msg)
- dotAtTheCenterOfTheScreen =
+ dotInElement : Mark.Block (Model -> Element Msg)
+ dotInElement =
= let
- render model =
- DotAtTheCenterOfTheScreen.ui
- |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- ]
- |> BrowserWindow.window []
+ render config model =
+ DotInElement.ui config
+ |> BrowserWindow.window [ Element.height (Element.px 300) ]
= in
- Mark.stub "DotAtTheCenterOfTheScreen" render
+ Mark.record4 "DotInElement"
+ DotInElement.Config
+ (Mark.field "background" Mark.string)
+ (Mark.field "fill" Mark.string)
+ (Mark.field "cx" Mark.string)
+ (Mark.field "cy" Mark.string)
+ |> Mark.map render
=
- centeredDot : Mark.Block (Model -> Element Msg)
- centeredDot =
+ dotWithViewBox : Mark.Block (Model -> Element Msg)
+ dotWithViewBox =
= let
- render model =
- CenteredDot.main
- |> Element.html
- |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- ]
+ render config model =
+ DotWithViewBox.ui config
+ |> Element.el [ Element.height (Element.px 300) ]
= |> BrowserWindow.window []
= in
- Mark.stub "CenteredDot" render
+ Mark.record3 "DotWithViewBox"
+ DotWithViewBox.Config
+ (Mark.field "background" Mark.string)
+ (Mark.field "fill" Mark.string)
+ (Mark.field "viewBox" Mark.string)
+ |> Mark.map render
=
= line : Mark.Block (Model -> Element Msg)
= line =Merge branch 'multiple-pages' into review-day-one
On by
Fix bad imports with merge
On by
index 0f6eec4..5581546 100644
--- a/src/Examples/Dot.elm
+++ b/src/Examples/Dot.elm
@@ -1,4 +1,4 @@
-module Dot exposing (Config, defaults, ui)
+module Examples.Dot exposing (Config, defaults, ui)
=
=import Html exposing (Html)
=import Svgindex a3e3397..ee127b3 100644
--- a/src/Examples/DotInElement.elm
+++ b/src/Examples/DotInElement.elm
@@ -1,4 +1,4 @@
-module DotInElement exposing (Config, main, ui)
+module Examples.DotInElement exposing (Config, main, ui)
=
=import Element exposing (Element)
=import Svgindex d26753c..6f91dc6 100644
--- a/src/Examples/DotWithViewBox.elm
+++ b/src/Examples/DotWithViewBox.elm
@@ -1,4 +1,4 @@
-module DotWithViewBox exposing (Config, main, ui)
+module Examples.DotWithViewBox exposing (Config, main, ui)
=
=import Element
=import Svgindex 6451e35..56ef197 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -10,12 +10,7 @@ import Basics.Extra exposing (curry)
=import Browser
=import Browser.Navigation as Navigation
=import BrowserWindow
-import CartesianCoordinates
-import Counter
=import Dict
-import Dot
-import DotInElement
-import DotWithViewBox
=import Element exposing (Element)
=import Element.Background as Background
=import Element.Border as Border
@@ -23,23 +18,21 @@ import Element.Events
=import Element.Font as Font
=import Element.Input as Input
=import Examples.CartesianCoordinates
-import Examples.CenteredDot
=import Examples.Counter
-import Examples.DotAtTheCenterOfTheScreen
-import Examples.FillTheScreen
+import Examples.Dot as Dot
+import Examples.DotInElement as DotInElement
+import Examples.DotWithViewBox as DotWithViewBox
=import Examples.Gradient
=import Examples.Line
=import Examples.NestedTransformations
=import Examples.PolarCoordinates
=import Examples.RosetteTypedTransformations
-import Examples.Simplest
=import Examples.Spiral
=import Examples.Transformations
=import Examples.TransformationsCircle
=import Examples.Tree
=import Examples.ViewBox
=import FeatherIcons exposing (icons)
-import Gradient
=import Html exposing (Html)
=import Html.Attributes
=import Http
@@ -50,9 +43,7 @@ import Parser
=import Parser.Advanced
=import Result.Extra as Result
=import Routes exposing (Route)
-import Spiral
=import Transformations
-import Tree
=import Url exposing (Url)
=
=Finish day 1
On by
Create multiple dots example
index 9cf6974..b9a8560 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -318,8 +318,7 @@ The top and left values of the viewbox are a bit trickier. We saw ealier that if
= (Element.html
= (Svg.svg
= [ Svg.Attributes.viewBox "-300 -300 600 600" ]
- [ Svg.circle [ Svg.Attributes.r "10" ] []
- ]
+ [ Svg.circle [ Svg.Attributes.r "10" ] [] ]
= )
= )
=
@@ -330,29 +329,215 @@ Refresh the broswer. We should now see the dot in the center of the screen.
= fill=black
= viewBox=-300 -300 600 600
=
-Give a color to the dot
=
+Now that we've centered our dot, we can customize it by giving it a color! Let's take a deeper look at how we give attributes to an SVG element.
+
+We've already seen a few example of SVG attributes. The radius of our dot ({Code|circle}) is an attribute.
+
+| Code
+ Svg.circle [ Svg.Attributes.r "10" ] []
=
-| List
- - Explain SVG attributes ( svg elements take a list of attributes)
- - Everyone can pick a color
+Try giving it a new value to see your dot grow or shrink.
=
+Our viewBox is also an attribute. It's an attribute of the {Code|svg} element.
=
-Multiple dots
+| Code
+ Svg.svg
+ [ Svg.Attributes.viewBox "-300 -300 600 600" ]
+ [ Svg.circle [ Svg.Attributes.r "10" ] [] ]
=
+Again, try giving it new values. As we saw earlier, the first two values (which represent the left and top of the viewBox) must be equal to the negative of the half of the last two values (which correspond to width and height). Try other combinations of values to adjust the placement of the dot. If the behavior of the viewBox is difficult to understand, refer again to the interactive tutorial above.
=
-| List
- -> Introduce a problem: We want to have two dots on the screen
- -> Explain a list, and show there is already a list there (with one item)
+To color our dot, we'll have to give it a second attribute. Many SVG elements take a {Code|List} of attributes. A {Code|List} is a very important concept in software development. {Code|Lists} allow us to group an arbitary number of similar values. In this case, we'll be using a {Code|List} to group {Code|Attribute a} values. Whenever you see {Code|[...]} in an Elm source code file, you are dealing with a list.
=
+Before we give a color to our dot, try to identify all the lists in the code we're writen already. There are 5. Hint: It is possible for a list to have only 1 or 0 items ({Code|[]}).
=
-| Header
- Do you see any other lists?
+| Code
+ Svg.circle [ Svg.Attributes.r "10" ] []
+
+When we take a look at the code responsible for creating our dot, we see that it is followed by two lists. We'll only need to worry about the first one at the moment. As we've discussed, the first list already contains the {Code|r} attribute of the circle, representing the radius. We'll need to add a second attribute to the circle. We use a comma ({Code|,}) to seperate elements in a list.
+
+| Code
+ Svg.circle [ Svg.Attributes.r "10", ... ] []
+
+To color our circle, we'll use the {Code|fill} attribute.
+
+| Code
+ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+
+You should see this result:
+
+| DotWithViewBox
+ background=none
+ fill=blue
+ viewBox=-300 -300 600 600
+
+
+Let's use our new understanding of lists to do something a bit more interesting. Let's draw multiple dots!
+
+We can start by taking a look at our {Code|main} value:
+
+| Code
+ main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (Element.html
+ (Svg.svg
+ [ Svg.Attributes.viewBox "-500 -500 1000 1000"
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+ ]
+ )
+ )
+
+Where is our list of circles? To find it, first find the circle.
+
+| Code
+ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+
+Next, identify the first open square bracket {Code|[} before the circle.
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+ ...
+
+This is where the list begins.
+
+Finally, identify the matching closing brakcet {Code|]}. This is a bit tricky because there are two lists within this list. The first is the list of attributes to the circle we saw earlier. The second is an empty list. We'll see exactly what they do in a moment. Ignore both of these for now. The matching closing bracket should be on the same indentation level as the opening bracket. Your text editor should be able to help you here. When you move your cursor before the opening bracket, the closing bracket should be highlighted.
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+ ]
+
+Right now, our list of circles has one value. We want to give it a second value. The second value will look identical to the first. What is the first value?
+
+| Code
+ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+
+It might not seem obvious at first that this is all one value. But it is. {Code|Svg.circle} takes two lists as arguments. We'll see what an argument is later. For now, we will need to understand the difference between an attribute and a child.
+
+Imagine a box of colored easter eggs. One egg is painted yellow, another red, another blue. Moreover, they don't all come from the same bird. One is a small robin's egg. Another is a medium chicken egg. Another is a huge ostrich egg.
+
+Some of the elements in our image are 'things'. A box is a thing. Each egg is also a thing. Some of the elements in our image are not things. Blueness is not a thing. Medium-sizeness is not a thing. You can see blueness. You can see medium-sizeness. But they are not things. They are attributes of a thing. A thing can be blue. It can be medium-sized.
+
+It is a convention in many programming languages, including Elm and SVG, to distinguish between the attributes and children of an element. If we wanted to represent our box in SVG, we would give our box several attributes. It would have a color (maybe brown). It would have a width, length, depth. We would also give it several children. Each of the eggs within the box would be a child of the box. A box with 6 eggs would have 6 children. Each of these children (the eggs) would have different attributes: blue, red, medium-sized, etc. The children of an element are the 'things' it contains. The attributes of a thing are the elements that describe it.
+
+The first list following {Code|Svg.circle} is:
+
+| Code
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+
+This is a list of attributes. A radius is not a 'thing'. A fill color is not a 'thing'. They are elements that describe a thing. They describe our circle.
+
+The second list is:
+
+| Code
+ []
+
+It is an empty list. Nevertheless, it is a list of children. Our circles don't have any children.
+
+Is the circle itself an attribute or a thing?
+
+From Elm's perspective, this entire code block is a circle:
+
+| Code
+ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+
+This is not a circle:
+
+| Code
+ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+
+Nor is this:
+
+| Code
+ Svg.circle
+
+To create a list with two circles, we'll want to duplicate the properly formed circle value. You can give the second dot a different color from the first.
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill "red"
+ ]
+ []
+ ]
+
+Make add the second circle to the list of circles in your source code and refresh the page. What do you see?
+
+| TwoDots
+ background=none
+ viewBox=-300 -300 600 600
+ firstFill=blue
+ secondFill=red
+ firstCX=0
+ secondCX=0
+
+Only one dot! We see the second one, but what happened to the first dot? It's under the second... Both are at the origin (0, 0), so they are both in the same spot. If we want to see both dots, we will have to change their positions. To do this we'll have to use their {Code|cx} or {Code|cy} values.
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "-10"
+ , Svg.Attributes.fill "blue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "10"
+ , Svg.Attributes.fill "red"
+ ]
+ []
+ ]
+
+| TwoDots
+ background=none
+ viewBox=-300 -300 600 600
+ firstFill=blue
+ secondFill=red
+ firstCX=-100
+ secondCX=100
=
+As an exercise, try adding an {Code|Svg.Attribute.cy} attribute to the circles to adjust their vertical position.
=
-| List
- -> Element takes a list of children
- -> Mention , how can we have a list with one or zero elements? Shopping list with one item. Empty spoon drawer( list of spoons)
- -> Give your new dot a color and different coordinates
- -> Show the code for 2 dots
- -> Exercise: make 3 more dots (5 total)
+For a more advanced exercise, try adding a new circle. Why not draw 5 circles on the screen? Give them each a unique color and position.new file mode 100644
index 0000000..b0625da
--- /dev/null
+++ b/src/Examples/MultipleDots.elm
@@ -0,0 +1,41 @@
+module Examples.MultipleDots exposing (Config, main, ui)
+
+import Element
+import Svg exposing (Attribute)
+import Svg.Attributes
+
+
+type alias Config msg =
+ { background : String
+ , viewBox : String
+ , dotsAttributes : List (List (Attribute msg))
+ }
+
+
+defaults : Config msg
+defaults =
+ Config "white" "-500 -500 1000 1000" [ [ Svg.Attributes.r "10" ] ]
+
+
+main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (ui defaults)
+
+
+ui { background, viewBox, dotsAttributes } =
+ Svg.svg
+ [ Svg.Attributes.viewBox viewBox
+ , Svg.Attributes.style <| "background: " ++ background
+ ]
+ (dotsAttributes
+ |> List.map
+ (\attributes ->
+ Svg.circle
+ attributes
+ []
+ )
+ )
+ |> Element.htmlindex 56ef197..5f855b9 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -24,6 +24,7 @@ import Examples.DotInElement as DotInElement
=import Examples.DotWithViewBox as DotWithViewBox
=import Examples.Gradient
=import Examples.Line
+import Examples.MultipleDots as MultipleDots
=import Examples.NestedTransformations
=import Examples.PolarCoordinates
=import Examples.RosetteTypedTransformations
@@ -43,6 +44,7 @@ import Parser
=import Parser.Advanced
=import Result.Extra as Result
=import Routes exposing (Route)
+import Svg.Attributes
=import Transformations
=import Url exposing (Url)
=
@@ -463,6 +465,7 @@ document =
= , dot
= , dotInElement
= , dotWithViewBox
+ , twoDots
= , transformationsCircle
= , line
= , gradient
@@ -546,6 +549,36 @@ document =
= (Mark.field "viewBox" Mark.string)
= |> Mark.map render
=
+ twoDots : Mark.Block (Model -> Element Msg)
+ twoDots =
+ let
+ render config model =
+ MultipleDots.ui config
+ |> Element.el [ Element.height (Element.px 300) ]
+ |> BrowserWindow.window []
+ in
+ Mark.record6 "TwoDots"
+ (\background viewBoxConf firstFill secondFill firstCX secondCX ->
+ MultipleDots.Config background
+ viewBoxConf
+ [ [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill firstFill
+ , Svg.Attributes.cx firstCX
+ ]
+ , [ Svg.Attributes.r "10"
+ , Svg.Attributes.fill secondFill
+ , Svg.Attributes.cx secondCX
+ ]
+ ]
+ )
+ (Mark.field "background" Mark.string)
+ (Mark.field "viewBox" Mark.string)
+ (Mark.field "firstFill" Mark.string)
+ (Mark.field "secondFill" Mark.string)
+ (Mark.field "firstCX" Mark.string)
+ (Mark.field "secondCX" Mark.string)
+ |> Mark.map render
+
= transformationsCircle : Mark.Block (Model -> Element Msg)
= transformationsCircle =
= letRemove duplicated ViewBox module
On by
deleted file mode 100644
index b3f0a44..0000000
--- a/src/ViewBox.elm
+++ /dev/null
@@ -1,276 +0,0 @@
-module ViewBox exposing
- ( Model
- , Msg
- , init
- , main
- , ui
- , update
- , view
- )
-
-import Browser
-import BrowserWindow
-import CartesianPlane exposing (graph)
-import Element
-import Element.Background as Background
-import Element.Border as Border
-import Element.Input as Input
-import Html exposing (Html)
-import Svg exposing (..)
-import Svg.Attributes exposing (..)
-
-
-main =
- Browser.sandbox
- { init = init
- , view = view
- , update = update
- }
-
-
-type alias Model =
- { left : Float
- , top : Float
- , width : Float
- , height : Float
- , preserveAspectRatio : Bool
- }
-
-
-type Msg
- = Move Float Float
- | Resize Float Float
- | PreserveAspectRatio Bool
-
-
-init : Model
-init =
- { left = 0
- , top = 0
- , width = 400
- , height = 400
- , preserveAspectRatio = False
- }
-
-
-view : Model -> Html.Html Msg
-view model =
- let
- wrapper element =
- Element.el
- [ Element.width (Element.maximum 1200 Element.fill)
- , Element.height Element.fill
- , Element.centerX
- ]
- element
- in
- ui model
- |> wrapper
- |> Element.layout
- [ Element.height Element.fill
- , Element.width Element.fill
- ]
-
-
-update : Msg -> Model -> Model
-update msg model =
- case msg of
- Move left top ->
- { model
- | left = left
- , top = top
- }
-
- Resize width height ->
- { model
- | width = width
- , height = height
- }
-
- PreserveAspectRatio value ->
- { model | preserveAspectRatio = value }
-
-
-ui model =
- let
- viewbox =
- svg
- [ viewBox "-500 -500 1000 1000"
- ]
- [ g [] world
- , rect
- [ x (String.fromFloat model.left)
- , y (String.fromFloat model.top)
- , width (String.fromFloat model.width)
- , height (String.fromFloat model.height)
- , opacity "0.3"
- , stroke "white"
- , fill "pink"
- ]
- []
- ]
- |> Element.html
- |> Element.el
- [ Element.centerX
- , Element.centerY
- , Element.width Element.fill
- , Element.height Element.fill
- ]
-
- viewport =
- svg
- [ [ model.left, model.top, model.width, model.height ]
- |> List.map String.fromFloat
- |> String.join " "
- |> viewBox
- , preserveAspectRatio <|
- case model.preserveAspectRatio of
- True ->
- "xMidYMid meet"
-
- False ->
- "none"
- , Svg.Attributes.style "width: 100%; height: 100%; flex-grow: 1; flex-basis: 0"
- ]
- [ g [] world
- , rect
- [ x (String.fromFloat model.left)
- , y (String.fromFloat model.top)
- , width (String.fromFloat model.width)
- , height (String.fromFloat model.height)
- , opacity "0.3"
- , stroke "white"
- , fill "pink"
- ]
- []
- ]
- |> Element.html
- |> Element.el
- [ Element.width Element.fill
- , Element.height Element.fill
- ]
- |> BrowserWindow.window
- [ Element.centerX
- , Element.centerY
- , Element.width Element.fill
- , Element.height Element.fill
- ]
- in
- Element.column
- [ Element.width Element.fill
- , Element.height Element.fill
- , Element.spacing 30
- , Element.padding 30
- ]
- [ Element.row
- [ Element.width Element.fill
- , Element.height Element.fill
- , Element.centerX
- , Element.spacing 30
- ]
- [ viewbox
- , viewport
- ]
- , Input.slider
- [ Element.behindContent
- (Element.el
- [ Element.width Element.fill
- , Element.height (Element.px 2)
- , Element.centerY
- , Background.color <| Element.rgb 0.7 0.7 0.7
- , Border.rounded 2
- ]
- Element.none
- )
- ]
- { onChange = \left -> Move left model.top
- , label =
- Input.labelBelow [ Element.centerX ] <|
- Element.text ("left: " ++ String.fromFloat model.left)
- , min = -500
- , max = 500
- , value = model.left
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- , Input.slider
- [ Element.behindContent
- (Element.el
- [ Element.width Element.fill
- , Element.height (Element.px 2)
- , Element.centerY
- , Background.color <| Element.rgb 0.7 0.7 0.7
- , Border.rounded 2
- ]
- Element.none
- )
- ]
- { onChange = \top -> Move model.left top
- , label =
- Input.labelBelow [ Element.centerX ] <|
- Element.text ("top: " ++ String.fromFloat model.top)
- , min = -500
- , max = 500
- , value = model.top
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- , Input.slider
- [ Element.behindContent
- (Element.el
- [ Element.width Element.fill
- , Element.height (Element.px 2)
- , Element.centerY
- , Background.color <| Element.rgb 0.7 0.7 0.7
- , Border.rounded 2
- ]
- Element.none
- )
- ]
- { onChange = \width -> Resize width model.height
- , label =
- Input.labelBelow [ Element.centerX ] <|
- Element.text ("width: " ++ String.fromFloat model.width)
- , min = 1
- , max = 500
- , value = model.width
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- , Input.slider
- [ Element.behindContent
- (Element.el
- [ Element.width Element.fill
- , Element.height (Element.px 2)
- , Element.centerY
- , Background.color <| Element.rgb 0.7 0.7 0.7
- , Border.rounded 2
- ]
- Element.none
- )
- ]
- { onChange = \height -> Resize model.width height
- , label =
- Input.labelBelow [ Element.centerX ] <|
- Element.text ("height: " ++ String.fromFloat model.height)
- , min = 1
- , max = 500
- , value = model.height
- , thumb = Input.defaultThumb
- , step = Just 1
- }
- , Input.checkbox []
- { checked = model.preserveAspectRatio
- , icon = Input.defaultCheckbox
- , label = Input.labelRight [] (Element.text "Preserve aspect ratio")
- , onChange = PreserveAspectRatio
- }
- ]
-
-
-world : List (Svg Msg)
-world =
- [ circle [ cx "400", cy "300", r "250", fill "purple" ] []
- , circle [ cx "200", cy "350", r "50", fill "yellow" ] []
- , circle [ cx "0", cy "0", r "20", fill "red" ] []
- ]Separate Window block from example blocks
On by
Now each example can be nested in a Window, but doesn't have to be.
index 83cc9bf..bda2078 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -85,7 +85,8 @@ Note that the same address was printed by the Elm reactor.
=
=We want to display a dot at the center of the screen, like this:
=
-| DotAtTheCenterOfTheScreen
+| Window
+ | DotAtTheCenterOfTheScreen
=
=Below is the complete code to draw a dot like this, but don't type it in your editor yet! We are going to recreate it together, step by step.
=
@@ -153,9 +154,10 @@ Start the reactor again:
=
=Reload the browser. You should see something like this:
=
-| Simplest
- background=none
- fill=black
+| Window
+ | Simplest
+ background=none
+ fill=black
=
=Something isn't quite right here. Why is the dot in the corner?
=
@@ -171,9 +173,10 @@ When you reload the browser, you'll see this:
=| Note
= Example of simplest with pink background should be here.
=
-| Simplest
- background=pink
- fill=black
+| Window
+ | Simplest
+ background=pink
+ fill=black
=
=Now we can clearly see that our SVG element (which is pink) does not fill the screen.
=index 99d1276..e6bd250 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -475,6 +475,28 @@ document =
= , spiral
= , tree
= , viewBox
+
+ -- Window block can contain any embeded program
+ , Mark.Custom.window
+ (Mark.oneOf
+ [ counter
+ , simplest
+ , fillTheScreen
+ , dotAtTheCenterOfTheScreen
+ , centeredDot
+ , circle
+ , line
+ , gradient
+ , transformations
+ , nestedTransformations
+ , cartesianCoordinates
+ , polarCoordinates
+ , rosette
+ , spiral
+ , tree
+ , viewBox
+ ]
+ )
= ]
= )
=
@@ -489,11 +511,6 @@ document =
= [ Element.centerX
= , Element.centerY
= ]
- |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- ]
- |> BrowserWindow.window []
= |> Element.map CounterMsg
= in
= Mark.stub "Counter" render
@@ -505,13 +522,12 @@ document =
= render config model =
= Examples.Simplest.ui config
= |> Element.html
- |> Element.el []
= |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- , Element.padding 5
+ [ Element.width (Element.px 300)
+ , Element.height (Element.px 150)
= ]
- |> BrowserWindow.window []
+ |> Element.el
+ [ Element.padding 5 ]
= in
= Mark.record2 "Simplest"
= Examples.Simplest.Config
@@ -537,11 +553,6 @@ document =
= let
= render model =
= Examples.DotAtTheCenterOfTheScreen.ui
- |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- ]
- |> BrowserWindow.window []
= in
= Mark.stub "DotAtTheCenterOfTheScreen" render
=
@@ -565,12 +576,6 @@ document =
= render : Examples.TransformationsCircle.Config -> Model -> Element Msg
= render config model =
= Examples.TransformationsCircle.ui config
- |> Element.el
- [ Element.height (Element.px 400)
- , Element.width Element.fill
- , Element.padding 5
- ]
- |> BrowserWindow.window []
= in
= Mark.record4 "TransformationsCircle"
= Examples.TransformationsCircle.Config
@@ -640,10 +645,6 @@ document =
= render model =
= model.cartesianCoordinates
= |> Examples.CartesianCoordinates.ui
- |> Element.el
- [ Element.width Element.fill
- ]
- |> BrowserWindow.window []
= |> Element.map CartesianCoordinatesMsg
= in
= Mark.stub "CartesianCoordinates" renderindex 3e50354..ca76c37 100644
--- a/src/Mark/Custom.elm
+++ b/src/Mark/Custom.elm
@@ -1,5 +1,21 @@
-module Mark.Custom exposing (code, colors, css, emphasize, header, icon, image, list, monospace, note, paragraph, text, title)
-
+module Mark.Custom exposing
+ ( code
+ , colors
+ , css
+ , emphasize
+ , header
+ , icon
+ , image
+ , list
+ , monospace
+ , note
+ , paragraph
+ , text
+ , title
+ , window
+ )
+
+import BrowserWindow
=import Dict
=import Element exposing (Element)
=import Element.Background as Background
@@ -107,6 +123,24 @@ code =
= Mark.multiline
=
=
+window :
+ Mark.Block (a -> Element msg)
+ -> Mark.Block (a -> Element msg)
+window block =
+ let
+ render child model =
+ child model
+ |> Element.el
+ [ Element.height (Element.px 400)
+ , Element.width Element.fill
+ ]
+ |> BrowserWindow.window []
+ in
+ Mark.block "Window"
+ render
+ block
+
+
=note : Mark.Block (model -> Element msg)
=note =
= letMake develop script print the modules it compiles to HTML
On by
Otherwise it just prints a lot of "Success" which looks dumb.
index 3b0e90e..bf51dda 100755
--- a/scripts/develop
+++ b/scripts/develop
@@ -5,6 +5,7 @@ set -euo pipefail
=# Build examples
=for example in src/Examples/*.elm
=do
+ echo "Compiling ${example} to public/${example}.html"
= npx elm make --output "public/${example}.html" "${example}"
=done
=Remove calls to Debug.log from Main
On by
index e6bd250..072cef8 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -275,11 +275,10 @@ view model =
=
=update : Msg -> Model -> ( Model, Cmd Msg )
=update msg model =
- case Debug.log "update" msg of
+ case msg of
= UrlRequested (Browser.Internal url) ->
= ( model
= , url
- |> Debug.log "New URL"
= |> Url.toString
= |> Navigation.pushUrl model.key
= )
@@ -376,7 +375,7 @@ subscriptions model =
=
=loadContent : Route -> Cmd Msg
=loadContent route =
- case Debug.log "Route" route of
+ case route of
= Routes.Home ->
= Http.get
= { url = "/content/index.txt"Rename TransformationsCircle to Circle, make it parametrized, edit day-2
On by
index 32d4a6c..6d2aed2 100644
--- a/content/day-2.txt
+++ b/content/day-2.txt
@@ -15,36 +15,135 @@
=| Header
= The Problem
=
-We want to place the dots in a circle, like that:
+We want to place the dots in a circle, like this:
=
-| TransformationsCircle
- dots = True
- circle = False
- angle = False
- center = False
+| Window
+ | Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
=
-As you can see, we will make the dot's have different colors, so it's more fun!
+We will also make the dots have different colors... so it's more fun!
=
-How we will get there?
+| Header
+ What does it mean to be placed on a circle?
+
+We all have some intuition about a circle. You can tell if you see one and if you have a steady hand, you can probably draw one with a pencil. It's a thing that looks like this:
+
+| Circle
+ dots = 0
+ circle = 1 0
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
=
-We will need more than one dot. Let's make it 5. Then let's think what does it mean to be placed on a circle.
=
-First of all we have to realize that a circle has a center. It's a point that lays exactly in the middle:
+But what is it that makes a circle what it is? First of all we have to realize that a circle has a center. It's a point that lays exactly in the middle:
=
+| Circle
+ dots = 0
+ circle = 1 0
+ angles = 0 1
+ center = True
+ radius = 0 1
+ scatter = False
=
-Then we can say that several things lay on a circle if the distance between each of them and the center is the same.
=
-In other words, you can put a thing in the center and then move it in any direction, let's say 1 meter. If you do the same to several things, you will make them lay on a circle.
+We can say that four or more things lay on a circle, if the distance to the center is the same for each of them, like this:
=
-Of course the direction must be different each time. Otherwise the things would just stack one on top of another! We wouldn't call it a circle, right?
+| Circle
+ dots = 5
+ circle = 3 3
+ angles = 0 1
+ center = True
+ radius = 3 3
+ scatter = False
=
-We will change the cartesian coordinates of the dots, nothing else! But figuring out the right coordinates is a bit tricky
+Why more than three? Well, think about it in terms of a fair challenge. If it's one, then it can lay on any circle that crosses the place. There is very many circles like that (in fact infinitely many). The same for two. Not every circle will do, but still you could draw many different circles that they will lay on. For three things there will always be exactly one circle that they lay on (except if they lay in one line, unless you claim that straight line is an infinite circle). So three is still not much of a challenge. You could place them however you like, and claim that they lay on a circle.
=
-How can we figure out the correct cartesian coordinates?
+So only when it's four or more things, we can seriously ask whether they lay on a circle or not.
=
=| Note
- Story about the flowerpot and the table: two ways to measure relative position, one is distance from an x and y axis (cartesian coordinates), the other is angle and distance relative to origin (polar coordinates)
+ TODO: Consider if the above adds more value or confusion.
+
+ TODO: An example showing multiple circles crossing one and two points
+
+ TODO: An example showing that for three different points there will always be a circle that crosses them, see {Link|circumcircle|url=https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/Triangle2d#circumcircle}
+
+
+Because we are all about challenges, let's make five dots.
+
+So, once again - we can say that several things lay on a circle if the distance between each of them and the center of the circle is the same. We call this distance /a *radius* of a circle/.
+
+| Note
+ Matematician would say:
+
+ /Four or more points belong to a circle when there is a point (called center) that is equally distant from each of the points./
+
+ That is more precise, but perhaps a little more difficult to visualize.
+
+Ok, so this describes what it means to lay on a circle. But what are some efficient methods of putting things there? How about this.
+
+You choose a center (anywhere, say {Code|(0, 0)}) and radius (any length you like, say 80).
+
+Take a ruler and place it's one end (the one showing the value 0) at the center point. Then move the thing you want to place along the ruler the length you chose. Leave it there.
+
+Next slightly rotate the ruler around the center (keep point {Code|0} of the ruler at point {Code|(0, 0)}). Repeat the steps above with another thing. Move it along the slider the same length as previously (radius). Because this time the ruler points in different direction, the thing will end up in a different place.
+
+| Note
+ TODO: An interactive example with ruler. Basically a modified Translations.
+
+In other words, you can put a thing in the center and then move it in any direction, let's say 1 meter. If you do the same to several things in several directions (but same length), you will make them lay on a circle. The direction must be different each time. Otherwise the things would just stack one on top of another! We wouldn't call it a circle, right?
+
+Now, notice that the dots displayed by the program we are creating are not laying just anywhere on the circle. They are evenly distributed:
+
+| Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
+
+It means that not only the distance between each dot and the center is the same. Also each dots lay the same distance away from it's two nearest neighbors.
+
+Just compare it with the following picture:
+
+| Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = True
+
+These are also 5 dots laying on a circle. Look:
+
+| Circle
+ dots = 5
+ circle = 3
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = True
+
+| Note
+ IDEA: An interactive program (game of sorts) that shows a ruler and dots. User can drag the ruler around and rotate it. Also dots can be dragged around. Once the dots are placed on a circle, the program rewards the user with a nice animation and message. It would be super awesome to make it touch capable {Icon|name=award}
+
+ Then second variety. This time there is also a compass tool. User has to place the dots on a circle so that they are evenly distributed.
+
+ In the mean time we have two non-interactive examples with evenly and randomly distributed dots.
+
+
+So they lay on a circle, but there is a striking difference. They are all scattered! This means that there is something missing in our solution. We need to take care of one more aspect when we place our dots.
+
+Since the center and radius is the same for each dot, the only thing we can play with is the angle that we rotate the ruler each time.
=
+TODO: ___✁___ edit from here
=
=What does this have to do with a circle? Do you know the expression 'I did a 180'. Where would you be looking if you did two 180s (a '360'). We see that circles and angles are closely related!
=new file mode 100644
index 0000000..7d4ced3
--- /dev/null
+++ b/src/Examples/Circle.elm
@@ -0,0 +1,189 @@
+module Examples.Circle exposing (Config, defaults, main, ui)
+
+import Arc2d
+import Array
+import Element exposing (Element)
+import Geometry.Svg
+import Html exposing (Html)
+import List.Extra as List
+import Maybe.Extra as Maybe
+import Point2d
+import Svg exposing (Svg)
+import Svg.Attributes
+import Transformations exposing (Transformation(..))
+
+
+type alias Config =
+ { dots : Int -- Number of dots
+ , circle : String -- Dash array
+ , center : String -- Color
+ , radius : String -- Dash array
+ , angles : String -- Dash array
+ , scatter : Bool -- Are doot evenly distributed or scattered
+ }
+
+
+main : Html.Html msg
+main =
+ Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+ (ui defaults)
+
+
+palette : List String
+palette =
+ [ "skyblue"
+ , "orange"
+ , "red"
+ , "lime"
+ , "maroon"
+ ]
+
+
+ui : Config -> Element msg
+ui config =
+ let
+ shapes =
+ [ dots
+ , center
+ , circle
+ , compass
+ , radi
+ ]
+
+ compass : Svg msg
+ compass =
+ 0
+ :: angles
+ |> pairs
+ |> Debug.log "pairs"
+ |> List.indexedMap arc
+ |> Svg.g []
+
+ pairs : List a -> List ( a, a )
+ pairs list =
+ case list of
+ [] ->
+ []
+
+ [ one ] ->
+ []
+
+ one :: two :: rest ->
+ ( one, two ) :: pairs (two :: rest)
+
+ arc : Int -> ( Float, Float ) -> Svg msg
+ arc index ( start, end ) =
+ Arc2d.with
+ { centerPoint = Point2d.origin
+ , radius = 30
+ , startAngle = degrees start
+ , sweptAngle = degrees (end - start)
+ }
+ |> Geometry.Svg.arc2d
+ [ Svg.Attributes.stroke (color index)
+ , Svg.Attributes.strokeDasharray config.angles
+ , Svg.Attributes.fill "none"
+ ]
+
+ dots =
+ angles
+ |> List.indexedMap
+ (\index angle ->
+ dot angle (color index)
+ )
+ |> Svg.g []
+
+ center =
+ Svg.circle
+ [ Svg.Attributes.r "2"
+ , Svg.Attributes.fill config.center
+ ]
+ []
+
+ circle =
+ Svg.circle
+ [ Svg.Attributes.r "80"
+ , Svg.Attributes.stroke "silver"
+ , Svg.Attributes.strokeWidth "1"
+ , Svg.Attributes.strokeDasharray config.circle
+ , Svg.Attributes.fill "none"
+ ]
+ []
+
+ radi =
+ angles
+ |> Debug.log "angles"
+ |> List.map radius
+ |> Svg.g []
+
+ angles : List Float
+ angles =
+ if config.scatter then
+ -- TODO: Generate a list of numbers [ 0, 5, 10, 15, ... 355 ] and use Random.Extra.List.shuffle and List.take config.dots to take a random sample.
+ [ 5, 35, 85, 100, 260, 340, 300, 95, 180, 220 ]
+ |> List.take config.dots
+
+ else
+ config.dots
+ |> List.range 1
+ |> List.map
+ (\index ->
+ 360 * toFloat index / toFloat config.dots
+ )
+
+ dot : Float -> String -> Svg msg
+ dot angle fill =
+ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill fill
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate angle
+ , Translate 80 0
+ ]
+ ]
+ []
+
+ color : Int -> String
+ color index =
+ palette
+ |> Array.fromList
+ |> Array.get (modBy (List.length palette) index)
+ |> Maybe.withDefault "black"
+
+ radius angle =
+ Svg.line
+ [ Svg.Attributes.x1 "0"
+ , Svg.Attributes.y1 "0"
+ , Svg.Attributes.x2 "80"
+ , Svg.Attributes.y2 "0"
+ , Svg.Attributes.stroke "pink"
+ , Svg.Attributes.strokeDasharray config.radius
+ , Svg.Attributes.transform <|
+ Transformations.apply
+ [ Rotate angle
+ ]
+ ]
+ []
+ in
+ shapes
+ |> Svg.svg
+ [ Svg.Attributes.viewBox "-100 -100 200 200"
+ ]
+ |> Element.html
+
+
+defaults : Config
+defaults =
+ { dots = 5
+ , circle = "0 1"
+ , center = "none"
+ , radius = "0 1"
+ , angles = "0 1"
+ , scatter = False
+ }deleted file mode 100644
index a3a507f..0000000
--- a/src/Examples/TransformationsCircle.elm
+++ /dev/null
@@ -1,135 +0,0 @@
-module Examples.TransformationsCircle exposing (Config, defaults, main, ui)
-
-import Element exposing (Element)
-import Html exposing (Html)
-import Maybe.Extra as Maybe
-import Svg exposing (Svg)
-import Svg.Attributes
-import Transformations exposing (Transformation(..))
-
-
-main : Html.Html msg
-main =
- Element.layout
- [ Element.width Element.fill
- , Element.height Element.fill
- ]
- (ui defaults)
-
-
-ui : Config -> Element msg
-ui config =
- let
- present : Bool -> Svg msg -> Maybe (Svg msg)
- present flag shape =
- if flag then
- Just shape
-
- else
- Nothing
-
- shapes =
- dots
- ++ Maybe.values
- [ present config.circle circle
- ]
-
- dots =
- if config.dots then
- [ Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- , Svg.Attributes.fill "skyblue"
- , Svg.Attributes.transform <|
- Transformations.apply
- [ Rotate 0
- , Translate 80 0
- ]
- ]
- []
- , Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- , Svg.Attributes.fill "pink"
- , Svg.Attributes.transform <|
- Transformations.apply
- [ Rotate 72
- , Translate 80 0
- ]
- ]
- []
- , Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- , Svg.Attributes.fill "yellow"
- , Svg.Attributes.transform <|
- Transformations.apply
- [ Rotate 144
- , Translate 80 0
- ]
- ]
- []
- , Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- , Svg.Attributes.fill "lime"
- , Svg.Attributes.transform <|
- Transformations.apply
- [ Rotate 216
- , Translate 80 0
- ]
- ]
- []
- , Svg.circle
- [ Svg.Attributes.r "10"
- , Svg.Attributes.cx "0"
- , Svg.Attributes.cy "0"
- , Svg.Attributes.fill "maroon"
- , Svg.Attributes.transform <|
- Transformations.apply
- [ Rotate 288
- , Translate 80 0
- ]
- ]
- []
- ]
-
- else
- []
-
- circle =
- Svg.circle
- [ Svg.Attributes.r "80"
- , Svg.Attributes.stroke "silver"
- , Svg.Attributes.strokeWidth "1"
- , Svg.Attributes.strokeDasharray "5 5"
- , Svg.Attributes.fill "none"
- ]
- []
- in
- shapes
- |> Svg.svg
- [ Svg.Attributes.viewBox "-100 -100 200 200"
- ]
- |> Element.html
-
-
-defaults : Config
-defaults =
- { circle = False
- , center = False
- , angle = False
- , dots = False
- }
-
-
-type alias Config =
- { circle : Bool
- , center : Bool
- , angle : Bool
- , dots : Bool
- }index 072cef8..d8624ad 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -19,6 +19,7 @@ import Element.Font as Font
=import Element.Input as Input
=import Examples.CartesianCoordinates
=import Examples.CenteredDot
+import Examples.Circle
=import Examples.Counter
=import Examples.DotAtTheCenterOfTheScreen
=import Examples.FillTheScreen
@@ -30,7 +31,6 @@ import Examples.RosetteTypedTransformations
=import Examples.Simplest
=import Examples.Spiral
=import Examples.Transformations
-import Examples.TransformationsCircle
=import Examples.Tree
=import Examples.ViewBox
=import FeatherIcons exposing (icons)
@@ -463,7 +463,7 @@ document =
= , fillTheScreen
= , dotAtTheCenterOfTheScreen
= , centeredDot
- , transformationsCircle
+ , circle
= , line
= , gradient
= , transformations
@@ -569,19 +569,21 @@ document =
= in
= Mark.stub "CenteredDot" render
=
- transformationsCircle : Mark.Block (Model -> Element Msg)
- transformationsCircle =
+ circle : Mark.Block (Model -> Element Msg)
+ circle =
= let
- render : Examples.TransformationsCircle.Config -> Model -> Element Msg
+ render : Examples.Circle.Config -> Model -> Element Msg
= render config model =
- Examples.TransformationsCircle.ui config
+ Examples.Circle.ui config
= in
- Mark.record4 "TransformationsCircle"
- Examples.TransformationsCircle.Config
- (Mark.field "circle" Mark.bool)
- (Mark.field "center" Mark.bool)
- (Mark.field "angle" Mark.bool)
- (Mark.field "dots" Mark.bool)
+ Mark.record6 "Circle"
+ Examples.Circle.Config
+ (Mark.field "dots" Mark.int)
+ (Mark.field "circle" Mark.string)
+ (Mark.field "center" Mark.string)
+ (Mark.field "radius" Mark.string)
+ (Mark.field "angles" Mark.string)
+ (Mark.field "scatter" Mark.bool)
= |> Mark.map render
=
= line : Mark.Block (Model -> Element Msg)Merge branch 'multiple-pages' into review-day-one
On by
Finish first draft of day 2
On by
new file mode 100644
index 0000000..1c0256e
--- /dev/null
+++ b/assets/protractor.svg
@@ -0,0 +1,3406 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ width="531.49603"
+ height="531.49603"
+ sodipodi:docname="rapporteur.svg"
+ sodipodi:docbase="/tmp"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <metadata
+ id="metadata733">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs731" />
+ <sodipodi:namedview
+ inkscape:window-height="581"
+ inkscape:window-width="744"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ width="150mm"
+ height="150mm"
+ units="mm"
+ inkscape:document-units="mm"
+ inkscape:zoom="1.4367677"
+ inkscape:cx="183.55229"
+ inkscape:cy="130.82769"
+ inkscape:window-x="46"
+ inkscape:window-y="46"
+ inkscape:current-layer="layer1" />
+ <title
+ id="title4">Protractor</title>
+ <g
+ transform="translate(270.98819,265.42013)"
+ id="g6">
+ <circle
+ cx="0"
+ cy="0"
+ r="250"
+ id="circle8"
+ sodipodi:cx="0"
+ sodipodi:cy="0"
+ sodipodi:rx="250"
+ sodipodi:ry="250"
+ style="fill:#d3d3d3;fill-opacity:0.3;stroke:#000000;stroke-width:3" />
+<!-- Units of 1 --> <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9998477,1.7452406e-2,-1.7452406e-2,0.9998477,0,0)"
+ id="line10"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9993908,3.4899497e-2,-3.4899497e-2,0.9993908,0,0)"
+ id="line12"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9986295,5.2335956e-2,-5.2335956e-2,0.9986295,0,0)"
+ id="line14"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9975641,6.9756474e-2,-6.9756474e-2,0.9975641,0,0)"
+ id="line16"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9945219,0.1045285,-0.1045285,0.9945219,0,0)"
+ id="line18"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9925462,0.1218693,-0.1218693,0.9925462,0,0)"
+ id="line20"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9902681,0.1391731,-0.1391731,0.9902681,0,0)"
+ id="line22"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9876883,0.1564345,-0.1564345,0.9876883,0,0)"
+ id="line24"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9816272,0.190809,-0.190809,0.9816272,0,0)"
+ id="line26"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9781476,0.2079117,-0.2079117,0.9781476,0,0)"
+ id="line28"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9743701,0.2249511,-0.2249511,0.9743701,0,0)"
+ id="line30"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9702957,0.2419219,-0.2419219,0.9702957,0,0)"
+ id="line32"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9612617,0.2756374,-0.2756374,0.9612617,0,0)"
+ id="line34"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9563048,0.2923717,-0.2923717,0.9563048,0,0)"
+ id="line36"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9510565,0.309017,-0.309017,0.9510565,0,0)"
+ id="line38"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9455186,0.3255682,-0.3255682,0.9455186,0,0)"
+ id="line40"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9335804,0.3583679,-0.3583679,0.9335804,0,0)"
+ id="line42"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9271839,0.3746066,-0.3746066,0.9271839,0,0)"
+ id="line44"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9205049,0.3907311,-0.3907311,0.9205049,0,0)"
+ id="line46"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9135455,0.4067366,-0.4067366,0.9135455,0,0)"
+ id="line48"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.898794,0.4383711,-0.4383711,0.898794,0,0)"
+ id="line50"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8910065,0.4539905,-0.4539905,0.8910065,0,0)"
+ id="line52"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8829476,0.4694716,-0.4694716,0.8829476,0,0)"
+ id="line54"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8746197,0.4848096,-0.4848096,0.8746197,0,0)"
+ id="line56"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8571673,0.5150381,-0.5150381,0.8571673,0,0)"
+ id="line58"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8480481,0.5299193,-0.5299193,0.8480481,0,0)"
+ id="line60"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8386706,0.544639,-0.544639,0.8386706,0,0)"
+ id="line62"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8290376,0.5591929,-0.5591929,0.8290376,0,0)"
+ id="line64"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.809017,0.5877853,-0.5877853,0.809017,0,0)"
+ id="line66"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7986355,0.601815,-0.601815,0.7986355,0,0)"
+ id="line68"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7880108,0.6156615,-0.6156615,0.7880108,0,0)"
+ id="line70"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.777146,0.6293204,-0.6293204,0.777146,0,0)"
+ id="line72"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7547096,0.656059,-0.656059,0.7547096,0,0)"
+ id="line74"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7431448,0.6691306,-0.6691306,0.7431448,0,0)"
+ id="line76"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7313537,0.6819984,-0.6819984,0.7313537,0,0)"
+ id="line78"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7193398,0.6946584,-0.6946584,0.7193398,0,0)"
+ id="line80"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6946584,0.7193398,-0.7193398,0.6946584,0,0)"
+ id="line82"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6819984,0.7313537,-0.7313537,0.6819984,0,0)"
+ id="line84"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6691306,0.7431448,-0.7431448,0.6691306,0,0)"
+ id="line86"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.656059,0.7547096,-0.7547096,0.656059,0,0)"
+ id="line88"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6293204,0.777146,-0.777146,0.6293204,0,0)"
+ id="line90"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6156615,0.7880108,-0.7880108,0.6156615,0,0)"
+ id="line92"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.601815,0.7986355,-0.7986355,0.601815,0,0)"
+ id="line94"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5877853,0.809017,-0.809017,0.5877853,0,0)"
+ id="line96"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5591929,0.8290376,-0.8290376,0.5591929,0,0)"
+ id="line98"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.544639,0.8386706,-0.8386706,0.544639,0,0)"
+ id="line100"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5299193,0.8480481,-0.8480481,0.5299193,0,0)"
+ id="line102"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5150381,0.8571673,-0.8571673,0.5150381,0,0)"
+ id="line104"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4848096,0.8746197,-0.8746197,0.4848096,0,0)"
+ id="line106"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4694716,0.8829476,-0.8829476,0.4694716,0,0)"
+ id="line108"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4539905,0.8910065,-0.8910065,0.4539905,0,0)"
+ id="line110"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4383711,0.898794,-0.898794,0.4383711,0,0)"
+ id="line112"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4067366,0.9135455,-0.9135455,0.4067366,0,0)"
+ id="line114"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3907311,0.9205049,-0.9205049,0.3907311,0,0)"
+ id="line116"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3746066,0.9271839,-0.9271839,0.3746066,0,0)"
+ id="line118"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3583679,0.9335804,-0.9335804,0.3583679,0,0)"
+ id="line120"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3255682,0.9455186,-0.9455186,0.3255682,0,0)"
+ id="line122"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.309017,0.9510565,-0.9510565,0.309017,0,0)"
+ id="line124"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2923717,0.9563048,-0.9563048,0.2923717,0,0)"
+ id="line126"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2756374,0.9612617,-0.9612617,0.2756374,0,0)"
+ id="line128"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2419219,0.9702957,-0.9702957,0.2419219,0,0)"
+ id="line130"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2249511,0.9743701,-0.9743701,0.2249511,0,0)"
+ id="line132"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2079117,0.9781476,-0.9781476,0.2079117,0,0)"
+ id="line134"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.190809,0.9816272,-0.9816272,0.190809,0,0)"
+ id="line136"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1564345,0.9876883,-0.9876883,0.1564345,0,0)"
+ id="line138"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1391731,0.9902681,-0.9902681,0.1391731,0,0)"
+ id="line140"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1218693,0.9925462,-0.9925462,0.1218693,0,0)"
+ id="line142"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1045285,0.9945219,-0.9945219,0.1045285,0,0)"
+ id="line144"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(6.9756474e-2,0.9975641,-0.9975641,6.9756474e-2,0,0)"
+ id="line146"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(5.2335956e-2,0.9986295,-0.9986295,5.2335956e-2,0,0)"
+ id="line148"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(3.4899497e-2,0.9993908,-0.9993908,3.4899497e-2,0,0)"
+ id="line150"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(1.7452406e-2,0.9998477,-0.9998477,1.7452406e-2,0,0)"
+ id="line152"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-1.7452406e-2,0.9998477,-0.9998477,-1.7452406e-2,0,0)"
+ id="line154"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-3.4899497e-2,0.9993908,-0.9993908,-3.4899497e-2,0,0)"
+ id="line156"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-5.2335956e-2,0.9986295,-0.9986295,-5.2335956e-2,0,0)"
+ id="line158"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-6.9756474e-2,0.9975641,-0.9975641,-6.9756474e-2,0,0)"
+ id="line160"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1045285,0.9945219,-0.9945219,-0.1045285,0,0)"
+ id="line162"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1218693,0.9925462,-0.9925462,-0.1218693,0,0)"
+ id="line164"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1391731,0.9902681,-0.9902681,-0.1391731,0,0)"
+ id="line166"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1564345,0.9876883,-0.9876883,-0.1564345,0,0)"
+ id="line168"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.190809,0.9816272,-0.9816272,-0.190809,0,0)"
+ id="line170"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2079117,0.9781476,-0.9781476,-0.2079117,0,0)"
+ id="line172"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2249511,0.9743701,-0.9743701,-0.2249511,0,0)"
+ id="line174"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2419219,0.9702957,-0.9702957,-0.2419219,0,0)"
+ id="line176"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2756374,0.9612617,-0.9612617,-0.2756374,0,0)"
+ id="line178"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2923717,0.9563048,-0.9563048,-0.2923717,0,0)"
+ id="line180"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.309017,0.9510565,-0.9510565,-0.309017,0,0)"
+ id="line182"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3255682,0.9455186,-0.9455186,-0.3255682,0,0)"
+ id="line184"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3583679,0.9335804,-0.9335804,-0.3583679,0,0)"
+ id="line186"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3746066,0.9271839,-0.9271839,-0.3746066,0,0)"
+ id="line188"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3907311,0.9205049,-0.9205049,-0.3907311,0,0)"
+ id="line190"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4067366,0.9135455,-0.9135455,-0.4067366,0,0)"
+ id="line192"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4383711,0.898794,-0.898794,-0.4383711,0,0)"
+ id="line194"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4539905,0.8910065,-0.8910065,-0.4539905,0,0)"
+ id="line196"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4694716,0.8829476,-0.8829476,-0.4694716,0,0)"
+ id="line198"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4848096,0.8746197,-0.8746197,-0.4848096,0,0)"
+ id="line200"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5150381,0.8571673,-0.8571673,-0.5150381,0,0)"
+ id="line202"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5299193,0.8480481,-0.8480481,-0.5299193,0,0)"
+ id="line204"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.544639,0.8386706,-0.8386706,-0.544639,0,0)"
+ id="line206"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5591929,0.8290376,-0.8290376,-0.5591929,0,0)"
+ id="line208"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5877853,0.809017,-0.809017,-0.5877853,0,0)"
+ id="line210"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.601815,0.7986355,-0.7986355,-0.601815,0,0)"
+ id="line212"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6156615,0.7880108,-0.7880108,-0.6156615,0,0)"
+ id="line214"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6293204,0.777146,-0.777146,-0.6293204,0,0)"
+ id="line216"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.656059,0.7547096,-0.7547096,-0.656059,0,0)"
+ id="line218"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6691306,0.7431448,-0.7431448,-0.6691306,0,0)"
+ id="line220"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6819984,0.7313537,-0.7313537,-0.6819984,0,0)"
+ id="line222"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6946584,0.7193398,-0.7193398,-0.6946584,0,0)"
+ id="line224"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7193398,0.6946584,-0.6946584,-0.7193398,0,0)"
+ id="line226"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7313537,0.6819984,-0.6819984,-0.7313537,0,0)"
+ id="line228"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7431448,0.6691306,-0.6691306,-0.7431448,0,0)"
+ id="line230"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7547096,0.656059,-0.656059,-0.7547096,0,0)"
+ id="line232"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.777146,0.6293204,-0.6293204,-0.777146,0,0)"
+ id="line234"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7880108,0.6156615,-0.6156615,-0.7880108,0,0)"
+ id="line236"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7986355,0.601815,-0.601815,-0.7986355,0,0)"
+ id="line238"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.809017,0.5877853,-0.5877853,-0.809017,0,0)"
+ id="line240"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8290376,0.5591929,-0.5591929,-0.8290376,0,0)"
+ id="line242"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8386706,0.544639,-0.544639,-0.8386706,0,0)"
+ id="line244"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8480481,0.5299193,-0.5299193,-0.8480481,0,0)"
+ id="line246"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8571673,0.5150381,-0.5150381,-0.8571673,0,0)"
+ id="line248"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8746197,0.4848096,-0.4848096,-0.8746197,0,0)"
+ id="line250"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8829476,0.4694716,-0.4694716,-0.8829476,0,0)"
+ id="line252"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8910065,0.4539905,-0.4539905,-0.8910065,0,0)"
+ id="line254"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.898794,0.4383711,-0.4383711,-0.898794,0,0)"
+ id="line256"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9135455,0.4067366,-0.4067366,-0.9135455,0,0)"
+ id="line258"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9205049,0.3907311,-0.3907311,-0.9205049,0,0)"
+ id="line260"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9271839,0.3746066,-0.3746066,-0.9271839,0,0)"
+ id="line262"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9335804,0.3583679,-0.3583679,-0.9335804,0,0)"
+ id="line264"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9455186,0.3255682,-0.3255682,-0.9455186,0,0)"
+ id="line266"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9510565,0.309017,-0.309017,-0.9510565,0,0)"
+ id="line268"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9563048,0.2923717,-0.2923717,-0.9563048,0,0)"
+ id="line270"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9612617,0.2756374,-0.2756374,-0.9612617,0,0)"
+ id="line272"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9702957,0.2419219,-0.2419219,-0.9702957,0,0)"
+ id="line274"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9743701,0.2249511,-0.2249511,-0.9743701,0,0)"
+ id="line276"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9781476,0.2079117,-0.2079117,-0.9781476,0,0)"
+ id="line278"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9816272,0.190809,-0.190809,-0.9816272,0,0)"
+ id="line280"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9876883,0.1564345,-0.1564345,-0.9876883,0,0)"
+ id="line282"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9902681,0.1391731,-0.1391731,-0.9902681,0,0)"
+ id="line284"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9925462,0.1218693,-0.1218693,-0.9925462,0,0)"
+ id="line286"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9945219,0.1045285,-0.1045285,-0.9945219,0,0)"
+ id="line288"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9975641,6.9756474e-2,-6.9756474e-2,-0.9975641,0,0)"
+ id="line290"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9986295,5.2335956e-2,-5.2335956e-2,-0.9986295,0,0)"
+ id="line292"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9993908,3.4899497e-2,-3.4899497e-2,-0.9993908,0,0)"
+ id="line294"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9998477,1.7452406e-2,-1.7452406e-2,-0.9998477,0,0)"
+ id="line296"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9998477,-1.7452406e-2,1.7452406e-2,-0.9998477,0,0)"
+ id="line298"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9993908,-3.4899497e-2,3.4899497e-2,-0.9993908,0,0)"
+ id="line300"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9986295,-5.2335956e-2,5.2335956e-2,-0.9986295,0,0)"
+ id="line302"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9975641,-6.9756474e-2,6.9756474e-2,-0.9975641,0,0)"
+ id="line304"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9945219,-0.1045285,0.1045285,-0.9945219,0,0)"
+ id="line306"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9925462,-0.1218693,0.1218693,-0.9925462,0,0)"
+ id="line308"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9902681,-0.1391731,0.1391731,-0.9902681,0,0)"
+ id="line310"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9876883,-0.1564345,0.1564345,-0.9876883,0,0)"
+ id="line312"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9816272,-0.190809,0.190809,-0.9816272,0,0)"
+ id="line314"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9781476,-0.2079117,0.2079117,-0.9781476,0,0)"
+ id="line316"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9743701,-0.2249511,0.2249511,-0.9743701,0,0)"
+ id="line318"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9702957,-0.2419219,0.2419219,-0.9702957,0,0)"
+ id="line320"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9612617,-0.2756374,0.2756374,-0.9612617,0,0)"
+ id="line322"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9563048,-0.2923717,0.2923717,-0.9563048,0,0)"
+ id="line324"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9510565,-0.309017,0.309017,-0.9510565,0,0)"
+ id="line326"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9455186,-0.3255682,0.3255682,-0.9455186,0,0)"
+ id="line328"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9335804,-0.3583679,0.3583679,-0.9335804,0,0)"
+ id="line330"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9271839,-0.3746066,0.3746066,-0.9271839,0,0)"
+ id="line332"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9205049,-0.3907311,0.3907311,-0.9205049,0,0)"
+ id="line334"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9135455,-0.4067366,0.4067366,-0.9135455,0,0)"
+ id="line336"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.898794,-0.4383711,0.4383711,-0.898794,0,0)"
+ id="line338"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8910065,-0.4539905,0.4539905,-0.8910065,0,0)"
+ id="line340"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8829476,-0.4694716,0.4694716,-0.8829476,0,0)"
+ id="line342"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8746197,-0.4848096,0.4848096,-0.8746197,0,0)"
+ id="line344"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8571673,-0.5150381,0.5150381,-0.8571673,0,0)"
+ id="line346"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8480481,-0.5299193,0.5299193,-0.8480481,0,0)"
+ id="line348"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8386706,-0.544639,0.544639,-0.8386706,0,0)"
+ id="line350"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8290376,-0.5591929,0.5591929,-0.8290376,0,0)"
+ id="line352"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.809017,-0.5877853,0.5877853,-0.809017,0,0)"
+ id="line354"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7986355,-0.601815,0.601815,-0.7986355,0,0)"
+ id="line356"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7880108,-0.6156615,0.6156615,-0.7880108,0,0)"
+ id="line358"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.777146,-0.6293204,0.6293204,-0.777146,0,0)"
+ id="line360"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7547096,-0.656059,0.656059,-0.7547096,0,0)"
+ id="line362"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7431448,-0.6691306,0.6691306,-0.7431448,0,0)"
+ id="line364"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7313537,-0.6819984,0.6819984,-0.7313537,0,0)"
+ id="line366"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7193398,-0.6946584,0.6946584,-0.7193398,0,0)"
+ id="line368"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6946584,-0.7193398,0.7193398,-0.6946584,0,0)"
+ id="line370"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6819984,-0.7313537,0.7313537,-0.6819984,0,0)"
+ id="line372"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6691306,-0.7431448,0.7431448,-0.6691306,0,0)"
+ id="line374"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.656059,-0.7547096,0.7547096,-0.656059,0,0)"
+ id="line376"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6293204,-0.777146,0.777146,-0.6293204,0,0)"
+ id="line378"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6156615,-0.7880108,0.7880108,-0.6156615,0,0)"
+ id="line380"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.601815,-0.7986355,0.7986355,-0.601815,0,0)"
+ id="line382"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5877853,-0.809017,0.809017,-0.5877853,0,0)"
+ id="line384"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5591929,-0.8290376,0.8290376,-0.5591929,0,0)"
+ id="line386"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.544639,-0.8386706,0.8386706,-0.544639,0,0)"
+ id="line388"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5299193,-0.8480481,0.8480481,-0.5299193,0,0)"
+ id="line390"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5150381,-0.8571673,0.8571673,-0.5150381,0,0)"
+ id="line392"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4848096,-0.8746197,0.8746197,-0.4848096,0,0)"
+ id="line394"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4694716,-0.8829476,0.8829476,-0.4694716,0,0)"
+ id="line396"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4539905,-0.8910065,0.8910065,-0.4539905,0,0)"
+ id="line398"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4383711,-0.898794,0.898794,-0.4383711,0,0)"
+ id="line400"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4067366,-0.9135455,0.9135455,-0.4067366,0,0)"
+ id="line402"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3907311,-0.9205049,0.9205049,-0.3907311,0,0)"
+ id="line404"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3746066,-0.9271839,0.9271839,-0.3746066,0,0)"
+ id="line406"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3583679,-0.9335804,0.9335804,-0.3583679,0,0)"
+ id="line408"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3255682,-0.9455186,0.9455186,-0.3255682,0,0)"
+ id="line410"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.309017,-0.9510565,0.9510565,-0.309017,0,0)"
+ id="line412"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2923717,-0.9563048,0.9563048,-0.2923717,0,0)"
+ id="line414"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2756374,-0.9612617,0.9612617,-0.2756374,0,0)"
+ id="line416"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2419219,-0.9702957,0.9702957,-0.2419219,0,0)"
+ id="line418"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2249511,-0.9743701,0.9743701,-0.2249511,0,0)"
+ id="line420"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.2079117,-0.9781476,0.9781476,-0.2079117,0,0)"
+ id="line422"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.190809,-0.9816272,0.9816272,-0.190809,0,0)"
+ id="line424"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1564345,-0.9876883,0.9876883,-0.1564345,0,0)"
+ id="line426"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1391731,-0.9902681,0.9902681,-0.1391731,0,0)"
+ id="line428"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1218693,-0.9925462,0.9925462,-0.1218693,0,0)"
+ id="line430"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1045285,-0.9945219,0.9945219,-0.1045285,0,0)"
+ id="line432"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-6.9756474e-2,-0.9975641,0.9975641,-6.9756474e-2,0,0)"
+ id="line434"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-5.2335956e-2,-0.9986295,0.9986295,-5.2335956e-2,0,0)"
+ id="line436"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-3.4899497e-2,-0.9993908,0.9993908,-3.4899497e-2,0,0)"
+ id="line438"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(-1.7452406e-2,-0.9998477,0.9998477,-1.7452406e-2,0,0)"
+ id="line440"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(1.7452406e-2,-0.9998477,0.9998477,1.7452406e-2,0,0)"
+ id="line442"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(3.4899497e-2,-0.9993908,0.9993908,3.4899497e-2,0,0)"
+ id="line444"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(5.2335956e-2,-0.9986295,0.9986295,5.2335956e-2,0,0)"
+ id="line446"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(6.9756474e-2,-0.9975641,0.9975641,6.9756474e-2,0,0)"
+ id="line448"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1045285,-0.9945219,0.9945219,0.1045285,0,0)"
+ id="line450"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1218693,-0.9925462,0.9925462,0.1218693,0,0)"
+ id="line452"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1391731,-0.9902681,0.9902681,0.1391731,0,0)"
+ id="line454"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1564345,-0.9876883,0.9876883,0.1564345,0,0)"
+ id="line456"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.190809,-0.9816272,0.9816272,0.190809,0,0)"
+ id="line458"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2079117,-0.9781476,0.9781476,0.2079117,0,0)"
+ id="line460"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2249511,-0.9743701,0.9743701,0.2249511,0,0)"
+ id="line462"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2419219,-0.9702957,0.9702957,0.2419219,0,0)"
+ id="line464"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2756374,-0.9612617,0.9612617,0.2756374,0,0)"
+ id="line466"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.2923717,-0.9563048,0.9563048,0.2923717,0,0)"
+ id="line468"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.309017,-0.9510565,0.9510565,0.309017,0,0)"
+ id="line470"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3255682,-0.9455186,0.9455186,0.3255682,0,0)"
+ id="line472"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3583679,-0.9335804,0.9335804,0.3583679,0,0)"
+ id="line474"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3746066,-0.9271839,0.9271839,0.3746066,0,0)"
+ id="line476"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3907311,-0.9205049,0.9205049,0.3907311,0,0)"
+ id="line478"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4067366,-0.9135455,0.9135455,0.4067366,0,0)"
+ id="line480"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4383711,-0.898794,0.898794,0.4383711,0,0)"
+ id="line482"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4539905,-0.8910065,0.8910065,0.4539905,0,0)"
+ id="line484"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4694716,-0.8829476,0.8829476,0.4694716,0,0)"
+ id="line486"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4848096,-0.8746197,0.8746197,0.4848096,0,0)"
+ id="line488"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5150381,-0.8571673,0.8571673,0.5150381,0,0)"
+ id="line490"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5299193,-0.8480481,0.8480481,0.5299193,0,0)"
+ id="line492"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.544639,-0.8386706,0.8386706,0.544639,0,0)"
+ id="line494"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5591929,-0.8290376,0.8290376,0.5591929,0,0)"
+ id="line496"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5877853,-0.809017,0.809017,0.5877853,0,0)"
+ id="line498"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.601815,-0.7986355,0.7986355,0.601815,0,0)"
+ id="line500"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6156615,-0.7880108,0.7880108,0.6156615,0,0)"
+ id="line502"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6293204,-0.777146,0.777146,0.6293204,0,0)"
+ id="line504"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.656059,-0.7547096,0.7547096,0.656059,0,0)"
+ id="line506"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6691306,-0.7431448,0.7431448,0.6691306,0,0)"
+ id="line508"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6819984,-0.7313537,0.7313537,0.6819984,0,0)"
+ id="line510"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6946584,-0.7193398,0.7193398,0.6946584,0,0)"
+ id="line512"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7193398,-0.6946584,0.6946584,0.7193398,0,0)"
+ id="line514"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7313537,-0.6819984,0.6819984,0.7313537,0,0)"
+ id="line516"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7431448,-0.6691306,0.6691306,0.7431448,0,0)"
+ id="line518"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7547096,-0.656059,0.656059,0.7547096,0,0)"
+ id="line520"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.777146,-0.6293204,0.6293204,0.777146,0,0)"
+ id="line522"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7880108,-0.6156615,0.6156615,0.7880108,0,0)"
+ id="line524"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7986355,-0.601815,0.601815,0.7986355,0,0)"
+ id="line526"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.809017,-0.5877853,0.5877853,0.809017,0,0)"
+ id="line528"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8290376,-0.5591929,0.5591929,0.8290376,0,0)"
+ id="line530"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8386706,-0.544639,0.544639,0.8386706,0,0)"
+ id="line532"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8480481,-0.5299193,0.5299193,0.8480481,0,0)"
+ id="line534"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8571673,-0.5150381,0.5150381,0.8571673,0,0)"
+ id="line536"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8746197,-0.4848096,0.4848096,0.8746197,0,0)"
+ id="line538"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8829476,-0.4694716,0.4694716,0.8829476,0,0)"
+ id="line540"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8910065,-0.4539905,0.4539905,0.8910065,0,0)"
+ id="line542"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.898794,-0.4383711,0.4383711,0.898794,0,0)"
+ id="line544"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9135455,-0.4067366,0.4067366,0.9135455,0,0)"
+ id="line546"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9205049,-0.3907311,0.3907311,0.9205049,0,0)"
+ id="line548"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9271839,-0.3746066,0.3746066,0.9271839,0,0)"
+ id="line550"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9335804,-0.3583679,0.3583679,0.9335804,0,0)"
+ id="line552"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9455186,-0.3255682,0.3255682,0.9455186,0,0)"
+ id="line554"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9510565,-0.309017,0.309017,0.9510565,0,0)"
+ id="line556"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9563048,-0.2923717,0.2923717,0.9563048,0,0)"
+ id="line558"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9612617,-0.2756374,0.2756374,0.9612617,0,0)"
+ id="line560"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9702957,-0.2419219,0.2419219,0.9702957,0,0)"
+ id="line562"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9743701,-0.2249511,0.2249511,0.9743701,0,0)"
+ id="line564"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9781476,-0.2079117,0.2079117,0.9781476,0,0)"
+ id="line566"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9816272,-0.190809,0.190809,0.9816272,0,0)"
+ id="line568"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9876883,-0.1564345,0.1564345,0.9876883,0,0)"
+ id="line570"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9902681,-0.1391731,0.1391731,0.9902681,0,0)"
+ id="line572"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9925462,-0.1218693,0.1218693,0.9925462,0,0)"
+ id="line574"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9945219,-0.1045285,0.1045285,0.9945219,0,0)"
+ id="line576"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9975641,-6.9756474e-2,6.9756474e-2,0.9975641,0,0)"
+ id="line578"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9986295,-5.2335956e-2,5.2335956e-2,0.9986295,0,0)"
+ id="line580"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9993908,-3.4899497e-2,3.4899497e-2,0.9993908,0,0)"
+ id="line582"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="240"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9998477,-1.7452406e-2,1.7452406e-2,0.9998477,0,0)"
+ id="line584"
+ style="stroke:#808080" />
+<!-- Units of 5 --> <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9961947,8.7155743e-2,-8.7155743e-2,0.9961947,0,0)"
+ id="line586"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9659258,0.258819,-0.258819,0.9659258,0,0)"
+ id="line588"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9063078,0.4226183,-0.4226183,0.9063078,0,0)"
+ id="line590"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.819152,0.5735764,-0.5735764,0.819152,0,0)"
+ id="line592"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5735764,0.819152,-0.819152,0.5735764,0,0)"
+ id="line594"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4226183,0.9063078,-0.9063078,0.4226183,0,0)"
+ id="line596"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.258819,0.9659258,-0.9659258,0.258819,0,0)"
+ id="line598"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(8.7155743e-2,0.9961947,-0.9961947,8.7155743e-2,0,0)"
+ id="line600"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-8.7155743e-2,0.9961947,-0.9961947,-8.7155743e-2,0,0)"
+ id="line602"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.258819,0.9659258,-0.9659258,-0.258819,0,0)"
+ id="line604"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4226183,0.9063078,-0.9063078,-0.4226183,0,0)"
+ id="line606"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5735764,0.819152,-0.819152,-0.5735764,0,0)"
+ id="line608"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.819152,0.5735764,-0.5735764,-0.819152,0,0)"
+ id="line610"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9063078,0.4226183,-0.4226183,-0.9063078,0,0)"
+ id="line612"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9659258,0.258819,-0.258819,-0.9659258,0,0)"
+ id="line614"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9961947,8.7155743e-2,-8.7155743e-2,-0.9961947,0,0)"
+ id="line616"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9961947,-8.7155743e-2,8.7155743e-2,-0.9961947,0,0)"
+ id="line618"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9659258,-0.258819,0.258819,-0.9659258,0,0)"
+ id="line620"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9063078,-0.4226183,0.4226183,-0.9063078,0,0)"
+ id="line622"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.819152,-0.5735764,0.5735764,-0.819152,0,0)"
+ id="line624"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5735764,-0.819152,0.819152,-0.5735764,0,0)"
+ id="line626"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.4226183,-0.9063078,0.9063078,-0.4226183,0,0)"
+ id="line628"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.258819,-0.9659258,0.9659258,-0.258819,0,0)"
+ id="line630"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(-8.7155743e-2,-0.9961947,0.9961947,-8.7155743e-2,0,0)"
+ id="line632"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(8.7155743e-2,-0.9961947,0.9961947,8.7155743e-2,0,0)"
+ id="line634"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.258819,-0.9659258,0.9659258,0.258819,0,0)"
+ id="line636"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.4226183,-0.9063078,0.9063078,0.4226183,0,0)"
+ id="line638"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5735764,-0.819152,0.819152,0.5735764,0,0)"
+ id="line640"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.819152,-0.5735764,0.5735764,0.819152,0,0)"
+ id="line642"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9063078,-0.4226183,0.4226183,0.9063078,0,0)"
+ id="line644"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9659258,-0.258819,0.258819,0.9659258,0,0)"
+ id="line646"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="230"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9961947,-8.7155743e-2,8.7155743e-2,0.9961947,0,0)"
+ id="line648"
+ style="stroke:#808080" />
+<!-- Units of 10 --> <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9848078,0.1736482,-0.1736482,0.9848078,0,0)"
+ id="line650"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9396926,0.3420201,-0.3420201,0.9396926,0,0)"
+ id="line652"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8660254,0.5,-0.5,0.8660254,0,0)"
+ id="line654"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7660444,0.6427876,-0.6427876,0.7660444,0,0)"
+ id="line656"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6427876,0.7660444,-0.7660444,0.6427876,0,0)"
+ id="line658"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5,0.8660254,-0.8660254,0.5,0,0)"
+ id="line660"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3420201,0.9396926,-0.9396926,0.3420201,0,0)"
+ id="line662"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1736482,0.9848078,-0.9848078,0.1736482,0,0)"
+ id="line664"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1736482,0.9848078,-0.9848078,-0.1736482,0,0)"
+ id="line666"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3420201,0.9396926,-0.9396926,-0.3420201,0,0)"
+ id="line668"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5,0.8660254,-0.8660254,-0.5,0,0)"
+ id="line670"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6427876,0.7660444,-0.7660444,-0.6427876,0,0)"
+ id="line672"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7660444,0.6427876,-0.6427876,-0.7660444,0,0)"
+ id="line674"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8660254,0.5,-0.5,-0.8660254,0,0)"
+ id="line676"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9396926,0.3420201,-0.3420201,-0.9396926,0,0)"
+ id="line678"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9848078,0.1736482,-0.1736482,-0.9848078,0,0)"
+ id="line680"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9848078,-0.1736482,0.1736482,-0.9848078,0,0)"
+ id="line682"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.9396926,-0.3420201,0.3420201,-0.9396926,0,0)"
+ id="line684"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.8660254,-0.5,0.5,-0.8660254,0,0)"
+ id="line686"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7660444,-0.6427876,0.6427876,-0.7660444,0,0)"
+ id="line688"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.6427876,-0.7660444,0.7660444,-0.6427876,0,0)"
+ id="line690"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,0,0)"
+ id="line692"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.3420201,-0.9396926,0.9396926,-0.3420201,0,0)"
+ id="line694"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.1736482,-0.9848078,0.9848078,-0.1736482,0,0)"
+ id="line696"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.1736482,-0.9848078,0.9848078,0.1736482,0,0)"
+ id="line698"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.3420201,-0.9396926,0.9396926,0.3420201,0,0)"
+ id="line700"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.5,-0.8660254,0.8660254,0.5,0,0)"
+ id="line702"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.6427876,-0.7660444,0.7660444,0.6427876,0,0)"
+ id="line704"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7660444,-0.6427876,0.6427876,0.7660444,0,0)"
+ id="line706"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)"
+ id="line708"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9396926,-0.3420201,0.3420201,0.9396926,0,0)"
+ id="line710"
+ style="stroke:#808080" />
+ <line
+ x1="0"
+ y1="210"
+ x2="0"
+ y2="250"
+ transform="matrix(0.9848078,-0.1736482,0.1736482,0.9848078,0,0)"
+ id="line712"
+ style="stroke:#808080" />
+<!-- Highlighted units --> <line
+ x1="0"
+ y1="-250"
+ x2="0"
+ y2="250"
+ transform="matrix(0.7071068,0.7071068,-0.7071068,0.7071068,0,0)"
+ id="line714"
+ style="stroke:#ff0000" />
+ <line
+ x1="0"
+ y1="-250"
+ x2="0"
+ y2="250"
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)"
+ id="line716"
+ style="stroke:#ff0000" />
+ <line
+ x1="0"
+ y1="-250"
+ x2="0"
+ y2="250"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="line718"
+ style="stroke:#008000" />
+ <line
+ x1="0"
+ y1="-250"
+ x2="0"
+ y2="250"
+ id="line720"
+ style="stroke:#008000" />
+<!-- Helper circles --> <circle
+ cx="0"
+ cy="0"
+ r="200"
+ id="circle722"
+ sodipodi:cx="0"
+ sodipodi:cy="0"
+ sodipodi:rx="200"
+ sodipodi:ry="200"
+ style="fill:none;stroke:#808080" />
+ <circle
+ cx="0"
+ cy="0"
+ r="150"
+ id="circle724"
+ sodipodi:cx="0"
+ sodipodi:cy="0"
+ sodipodi:rx="150"
+ sodipodi:ry="150"
+ style="fill:none;stroke:#808080" />
+ <circle
+ cx="0"
+ cy="0"
+ r="100"
+ id="circle726"
+ sodipodi:cx="0"
+ sodipodi:cy="0"
+ sodipodi:rx="100"
+ sodipodi:ry="100"
+ style="fill:none;stroke:#808080" />
+ <circle
+ cx="0"
+ cy="0"
+ r="50"
+ id="circle728"
+ sodipodi:cx="0"
+ sodipodi:cy="0"
+ sodipodi:rx="50"
+ sodipodi:ry="50"
+ style="fill:none;stroke:#808080" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer1"
+ inkscape:label="nombres">
+ <g
+ id="g3000">
+ <text
+ sodipodi:linespacing="100%"
+ id="text2886"
+ y="64.47551"
+ x="266.91858"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="64.47551"
+ x="266.91858"
+ id="tspan2888"
+ sodipodi:role="line">0</tspan></text>
+ <text
+ transform="matrix(0.934898,0.3549166,-0.3549166,0.934898,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2890"
+ y="-49.55188"
+ x="336.83362"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-49.55188"
+ x="336.83362"
+ id="tspan2892"
+ sodipodi:role="line">20</tspan></text>
+ <text
+ transform="matrix(0.983636,0.1801671,-0.1801671,0.983636,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2894"
+ y="10.690214"
+ x="306.32104"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="10.690214"
+ x="306.32104"
+ id="tspan2896"
+ sodipodi:role="line">10</tspan></text>
+ <text
+ transform="matrix(0.858982,0.5120058,-0.5120058,0.858982,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2898"
+ y="-111.83684"
+ x="359.12906"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-111.83684"
+ x="359.12906"
+ id="tspan2900"
+ sodipodi:role="line">30</tspan></text>
+ <text
+ transform="matrix(0.7636146,0.6456724,-0.6456724,0.7636146,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2902"
+ y="-173.86545"
+ x="369.93304"
+ style="font-size:14.00000191px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-173.86545"
+ x="369.93304"
+ id="tspan2904"
+ sodipodi:role="line">40</tspan></text>
+ <text
+ transform="matrix(0.6410049,0.7675368,-0.7675368,0.6410049,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2906"
+ y="-239.44522"
+ x="369.7211"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-239.44522"
+ x="369.7211"
+ id="tspan2908"
+ sodipodi:role="line">50</tspan></text>
+ <text
+ transform="matrix(0.4920312,0.8705776,-0.8705776,0.4920312,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2910"
+ y="-307.14023"
+ x="355.31683"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-307.14023"
+ x="355.31683"
+ id="tspan2912"
+ sodipodi:role="line">60</tspan></text>
+ <text
+ transform="matrix(0.3329444,0.9429465,-0.9429465,0.3329444,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2914"
+ y="-368.034"
+ x="330.30707"
+ style="font-size:14.00000191px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-368.034"
+ x="330.30707"
+ id="tspan2916"
+ sodipodi:role="line">70</tspan></text>
+ <text
+ transform="matrix(0.1708576,0.9852957,-0.9852957,0.1708576,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2918"
+ y="-422.65707"
+ x="299.59378"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-422.65707"
+ x="299.59378"
+ id="tspan2920"
+ sodipodi:role="line">80</tspan></text>
+ <text
+ transform="matrix(0,1,-1,0,0,0)"
+ sodipodi:linespacing="100%"
+ id="text2922"
+ y="-472.76172"
+ x="257.04504"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-472.76172"
+ x="257.04504"
+ id="tspan2924"
+ sodipodi:role="line">90</tspan></text>
+ </g>
+ <g
+ id="g3022"
+ transform="matrix(-1,0,0,-1,541.91333,530.70606)">
+ <text
+ sodipodi:linespacing="100%"
+ id="text3024"
+ y="64.47551"
+ x="266.91858"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="64.47551"
+ x="266.91858"
+ id="tspan3026"
+ sodipodi:role="line">0</tspan></text>
+ <text
+ transform="matrix(0.934898,0.3549166,-0.3549166,0.934898,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3028"
+ y="-49.55188"
+ x="336.83362"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-49.55188"
+ x="336.83362"
+ id="tspan3030"
+ sodipodi:role="line">20</tspan></text>
+ <text
+ transform="matrix(0.983636,0.1801671,-0.1801671,0.983636,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3032"
+ y="10.690214"
+ x="306.32104"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="10.690214"
+ x="306.32104"
+ id="tspan3034"
+ sodipodi:role="line">10</tspan></text>
+ <text
+ transform="matrix(0.858982,0.5120058,-0.5120058,0.858982,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3036"
+ y="-111.83684"
+ x="359.12906"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-111.83684"
+ x="359.12906"
+ id="tspan3038"
+ sodipodi:role="line">30</tspan></text>
+ <text
+ transform="matrix(0.7636146,0.6456724,-0.6456724,0.7636146,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3040"
+ y="-173.86545"
+ x="369.93304"
+ style="font-size:14.00000191px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-173.86545"
+ x="369.93304"
+ id="tspan3042"
+ sodipodi:role="line">40</tspan></text>
+ <text
+ transform="matrix(0.6410049,0.7675368,-0.7675368,0.6410049,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3044"
+ y="-239.44522"
+ x="369.7211"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-239.44522"
+ x="369.7211"
+ id="tspan3046"
+ sodipodi:role="line">50</tspan></text>
+ <text
+ transform="matrix(0.4920312,0.8705776,-0.8705776,0.4920312,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3048"
+ y="-307.14023"
+ x="355.31683"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-307.14023"
+ x="355.31683"
+ id="tspan3050"
+ sodipodi:role="line">60</tspan></text>
+ <text
+ transform="matrix(0.3329444,0.9429465,-0.9429465,0.3329444,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3052"
+ y="-368.034"
+ x="330.30707"
+ style="font-size:14.00000191px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-368.034"
+ x="330.30707"
+ id="tspan3054"
+ sodipodi:role="line">70</tspan></text>
+ <text
+ transform="matrix(0.1708576,0.9852957,-0.9852957,0.1708576,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3056"
+ y="-422.65707"
+ x="299.59378"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-422.65707"
+ x="299.59378"
+ id="tspan3058"
+ sodipodi:role="line">80</tspan></text>
+ <text
+ transform="matrix(0,1,-1,0,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3060"
+ y="-472.76172"
+ x="257.04504"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="-472.76172"
+ x="257.04504"
+ id="tspan3062"
+ sodipodi:role="line">90</tspan></text>
+ </g>
+ <g
+ id="g3100">
+ <text
+ transform="matrix(0.9847623,-0.1739055,0.1739055,0.9847623,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3064"
+ y="107.18554"
+ x="214.40683"
+ style="font-size:13.99999809px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="107.18554"
+ x="214.40683"
+ id="tspan3066"
+ sodipodi:role="line">10</tspan></text>
+ <text
+ transform="matrix(0.9361242,-0.3516695,0.3516695,0.9361242,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3068"
+ y="142.12463"
+ x="154.94203"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="142.12463"
+ x="154.94203"
+ id="tspan3070"
+ sodipodi:role="line">20</tspan></text>
+ <text
+ transform="matrix(0.8651952,-0.5014352,0.5014352,0.8651952,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3072"
+ y="164.11133"
+ x="94.490524"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="164.11133"
+ x="94.490524"
+ id="tspan3074"
+ sodipodi:role="line">30</tspan></text>
+ <text
+ transform="matrix(0.7658449,-0.6430253,0.6430253,0.7658449,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3076"
+ y="176.02191"
+ x="29.440561"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="176.02191"
+ x="29.440561"
+ id="tspan3078"
+ sodipodi:role="line">40</tspan></text>
+ <text
+ transform="matrix(0.6414771,-0.7671422,0.7671422,0.6414771,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3080"
+ y="176.32138"
+ x="-36.683174"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="176.32138"
+ x="-36.683174"
+ id="tspan3082"
+ sodipodi:role="line">50</tspan></text>
+ <text
+ transform="matrix(0.497669,-0.867367,0.867367,0.497669,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3084"
+ y="165.79233"
+ x="-102.21782"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="165.79233"
+ x="-102.21782"
+ id="tspan3086"
+ sodipodi:role="line">60</tspan></text>
+ <text
+ transform="matrix(0.3403569,-0.9402963,0.9402963,0.3403569,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3088"
+ y="143.97623"
+ x="-164.87398"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="143.97623"
+ x="-164.87398"
+ id="tspan3090"
+ sodipodi:role="line">70</tspan></text>
+ <text
+ transform="matrix(0.1752809,-0.9845185,0.9845185,0.1752809,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3092"
+ y="112.04415"
+ x="-221.67944"
+ style="font-size:14.00000191px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="112.04415"
+ x="-221.67944"
+ id="tspan3094"
+ sodipodi:role="line">80</tspan></text>
+ </g>
+ <g
+ id="g3118"
+ transform="matrix(-1,0,0,-1,542.14643,530.77343)">
+ <text
+ transform="matrix(0.9847623,-0.1739055,0.1739055,0.9847623,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3120"
+ y="107.18554"
+ x="214.40683"
+ style="font-size:13.99999809px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="107.18554"
+ x="214.40683"
+ id="tspan3122"
+ sodipodi:role="line">10</tspan></text>
+ <text
+ transform="matrix(0.9361242,-0.3516695,0.3516695,0.9361242,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3124"
+ y="142.12463"
+ x="154.94203"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="142.12463"
+ x="154.94203"
+ id="tspan3126"
+ sodipodi:role="line">20</tspan></text>
+ <text
+ transform="matrix(0.8651952,-0.5014352,0.5014352,0.8651952,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3128"
+ y="164.11133"
+ x="94.490524"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="164.11133"
+ x="94.490524"
+ id="tspan3130"
+ sodipodi:role="line">30</tspan></text>
+ <text
+ transform="matrix(0.7658449,-0.6430253,0.6430253,0.7658449,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3132"
+ y="176.02191"
+ x="29.440561"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="176.02191"
+ x="29.440561"
+ id="tspan3134"
+ sodipodi:role="line">40</tspan></text>
+ <text
+ transform="matrix(0.6414771,-0.7671422,0.7671422,0.6414771,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3136"
+ y="176.32138"
+ x="-36.683174"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="176.32138"
+ x="-36.683174"
+ id="tspan3138"
+ sodipodi:role="line">50</tspan></text>
+ <text
+ transform="matrix(0.497669,-0.867367,0.867367,0.497669,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3140"
+ y="165.79233"
+ x="-102.21782"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="165.79233"
+ x="-102.21782"
+ id="tspan3142"
+ sodipodi:role="line">60</tspan></text>
+ <text
+ transform="matrix(0.3403569,-0.9402963,0.9402963,0.3403569,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3144"
+ y="143.97623"
+ x="-164.87398"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="143.97623"
+ x="-164.87398"
+ id="tspan3146"
+ sodipodi:role="line">70</tspan></text>
+ <text
+ transform="matrix(0.1752809,-0.9845185,0.9845185,0.1752809,0,0)"
+ sodipodi:linespacing="100%"
+ id="text3148"
+ y="112.04415"
+ x="-221.67944"
+ style="font-size:14.00000191px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Thryomanes"
+ xml:space="preserve"><tspan
+ y="112.04415"
+ x="-221.67944"
+ id="tspan3150"
+ sodipodi:role="line">80</tspan></text>
+ </g>
+ </g>
+</svg>index 6d2aed2..3dd306a 100644
--- a/content/day-2.txt
+++ b/content/day-2.txt
@@ -48,7 +48,7 @@ But what is it that makes a circle what it is? First of all we have to realize t
= dots = 0
= circle = 1 0
= angles = 0 1
- center = True
+ center = red
= radius = 0 1
= scatter = False
=
@@ -59,15 +59,21 @@ We can say that four or more things lay on a circle, if the distance to the cent
= dots = 5
= circle = 3 3
= angles = 0 1
- center = True
+ center = red
= radius = 3 3
= scatter = False
=
-Why more than three? Well, think about it in terms of a fair challenge. If it's one, then it can lay on any circle that crosses the place. There is very many circles like that (in fact infinitely many). The same for two. Not every circle will do, but still you could draw many different circles that they will lay on. For three things there will always be exactly one circle that they lay on (except if they lay in one line, unless you claim that straight line is an infinite circle). So three is still not much of a challenge. You could place them however you like, and claim that they lay on a circle.
+| Note
+ Why more than three? One, two or three things always lay on at least one circle, so it's not much of a challenge that way.
=
-So only when it's four or more things, we can seriously ask whether they lay on a circle or not.
+ One thing lay on any circle that crosses the place. You could draw very many circles like that (in fact as many as you want).
+
+ Similar for two things. Not every circle will do, but still you could draw many different circles that they will lay on.
+
+ For three things there will always be exactly one circle that they lay on (except if they lay in one line). So three is still not much of a challenge. You could place them however you like, and always say that they lay on a circle.
+
+ Only when it's four or more things, we can seriously ask whether they lay on a circle or not.
=
-| Note
= TODO: Consider if the above adds more value or confusion.
=
= TODO: An example showing multiple circles crossing one and two points
@@ -77,7 +83,7 @@ So only when it's four or more things, we can seriously ask whether they lay on
=
=Because we are all about challenges, let's make five dots.
=
-So, once again - we can say that several things lay on a circle if the distance between each of them and the center of the circle is the same. We call this distance /a *radius* of a circle/.
+So, once again - we can say that several things (in our case dots) lay on a circle if the distance between each of them and the center of the circle is the same. We call this distance /a *radius* of a circle/.
=
=| Note
= Matematician would say:
@@ -86,7 +92,7 @@ So, once again - we can say that several things lay on a circle if the distance
=
= That is more precise, but perhaps a little more difficult to visualize.
=
-Ok, so this describes what it means to lay on a circle. But what are some efficient methods of putting things there? How about this.
+Ok, so this describes what it means to lay on a circle. But what are some efficient methods of putting things there? How about the following.
=
=You choose a center (anywhere, say {Code|(0, 0)}) and radius (any length you like, say 80).
=
@@ -143,32 +149,281 @@ So they lay on a circle, but there is a striking difference. They are all scatte
=
=Since the center and radius is the same for each dot, the only thing we can play with is the angle that we rotate the ruler each time.
=
-TODO: ___✁___ edit from here
+A common way of representing rotation is in degrees. It works like that: imagine a circle around you. You are in the center. Now imagine that the circle is divided in 360 equal segments. If you turn from the segment you face to the next one on the right (a very small turn) then you have turned one degree. If you turn around to face the opposite direction, that's a turn of 180 degrees. Do it again and you are facing the same direction as before (a 360 degree turn). If you turn to the right (as on a corner of a street), then you have turned 90 degrees (half of 180, quarter of 360).
+
+In physical world we often use a tool called protractor to measure angles. It typically has one degree segments already marked for you. It looks like this:
+
+| Image
+ src = /assets/protractor.svg
+ description = A protractor by Georges Khaznadar <georgesk@ofset.org>
+
+| Note
+ TODO: Modify the image to make marks 0 - 360. We can convert it to Elm code (using https:////level.app//svg-to-elm) and then reuse it in our examples.
+
+Now if we make the turns of the ruler equal between placing each dot, then the dots will be placed evenly. Equal turns mean that the number of degrees covered by each turn will be the same, including the turn you would need to make to go from the last dot back to the first. But how many degrees shall it be?
+
+In mathematics there is a special operation to determine it. Perhaps you have heard about it: it's called division and is written like that:
+
+| Monospace
+ 360 / 5
+
+Maybe you can solve it in your head, but if not, why not use Elm REPL? Go to the terminal, stop the reactor (if it's running) and type:
+
+| Monospace
+ elm repl
=
-What does this have to do with a circle? Do you know the expression 'I did a 180'. Where would you be looking if you did two 180s (a '360'). We see that circles and angles are closely related!
+And then
=
-Exercise with compass and 5 objects, place objects evenly along compass. How many degrees apart are they? (observe if we multiply the result by 5, we're back to 360)
+| Monospace
+ 360 / 5
=
-We have one part of it (angle), we now need the distance. Notice they are all the same distance from the origin (the center dot) of the compass. Definition of circle: points that are an equal distance from a center. Actually, the distance doesn't matter, so long as they all have the same distance. You can have a big circle or a small circle, they're both circles
+You should see:
=
-Ok great, we're done! Now, does anyone know how to give an angle and distance to svg? Oh... no? We don't either... you can't. You can only give x and y values relative to the origin
+| Monospace
+ ---- Elm 0.19.0 ----------------------------------------------------------------
+ Read <https://elm-lang.org/0.19.0/repl> to learn more: exit, help, imports, etc.
+ --------------------------------------------------------------------------------
+ > 360 / 5
+ 72 : Float
+ >
=
-So we already know that angle and length are just another way of describing x and y. But we need some way of translating between the two
+Type {Code|:exit} to close the REPL.
+
+Turns out that the result is 72. That's the number of degrees we have to turn our ruler around the center each time we place a new dot. If you have a protractor like the one pictured above, you can use it to measure the turn. Then measure the distance from the center along the ruler (a length called radius) and place the dot there.
+
+| Header
+ The Code
+
+Now that we understand what it means to be placed on a circle and evenly distributed, it's time to create a program that displays dots like that. Once again, this is the intended result:
+
+| Window
+ | Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
=
-sing a visual demonstration, if you draw a line from your object to the x axis, you have a triangle. Same if you draw a line to the y axis. You can figure out the point on the axis using sin and cos functions and multiplying the result by the length.
+We will start from where we left off yesterday. Open {Code|src//Main.elm} in your editor. It should have the following code:
=
-Let's use a chart to figure out the sin and cos of our angles
+| Code
+ module Main exposing (main)
=
-/It's important to get a chart, otherwise we have to use calculators which work with radians/
+ import Element
+ import Svg
+ import Svg.Attributes
=
-Now we are done... we can plug in our x and y values, and presto, our dots are arranged in a circle. But we don't see most of them...
=
-Our origin is in the top left corner. This means any dots with negative x or y values are off the screen.
+ main =
+ Svg.svg
+ [ Svg.Attributes.viewBox "-100 -100 200 200"
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ ]
+ []
+ ]
+ |> Element.html
+ |> Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
=
-We can shift the dots so they are on the screen, or shift the screen so that it covers the dots. We will be shifting the screen
+It's a good starting point. We already have a single dot in the middle. Let's say this is will be the center of our circle.
=
-Sample viewbox program to demonstrate
+Now it's time to introduce our protractor and ruler. These is a property of an SVG element called `transform`. You use it like that:
=
-Create a viewbox with correct perimeters (must be more than the radius of the circle plus the radius of a dot in each direction, and width and height are circumference)
+| Monospace
+ Svg.Attributes.transform "translate(80)"
=
-{Code|svg [viewbox "-100 -100 200 200 " ] []}
+This will move the dot ("translate" is a fancy term for "move") 80 units.
+
+Also, let's change the color of the dot. In the end it should look like this:
+
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.transform "translate(80)"
+ , Svg.Attributes.fill "skyblue"
+ ]
+ []
+ ]
+
+With this change, start the reactor by typing in your terminal:
+
+| Monospace
+ elm reactor
+
+and {Link|open the program in your browser|url=http://localhost/src/Main.elm}. You should see something like this:
+
+| Window
+ | Circle
+ dots = 1
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
+
+As you can see the dot is no longer in the center - it has moved!
+
+Now we need a second dot. If you remember the discussion about lists from previous day, you know what to do. Just duplicate the first SVG circle and put it after the first one, with a coma in between. Like this:
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.transform "translate(80)"
+ , Svg.Attributes.fill "skyblue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "orange"
+ , Svg.Attributes.transform "translate(80)"
+ ]
+ []
+ ]
+
+Now let's focus on the second one. We gave it a different color, so we can distinguish between them, but now we don't see the first one! That's because it's exactly in the same spot as the second one, which covers it. They are stacked in a way. We need to move the second dot in a different direction, so it's on a circle, but 72 degree apart from the first one.
+
+For that we need to add another transformation before the move. First we will rotate, then translate:
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.transform "translate(80)"
+ , Svg.Attributes.fill "skyblue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "orange"
+ , Svg.Attributes.transform "rotate(72) translate(80)"
+ ]
+ []
+ ]
+
+This will rotate the element by 72 degrees. On it's own it wouldn't make any difference, because the dot is round - it doesn't matter how you rotate it, it always looks the same. But It also rotates it's internal coordinates system. So the translation will move it in a different direction then the first dot.
+
+Now it's time to add the fird, red dot. Duplicate the second one, change fill to `"red"` and put `144` for rotate function, like this:
+
+| Code
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.transform "translate(80)"
+ , Svg.Attributes.fill "skyblue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "orange"
+ , Svg.Attributes.transform "rotate(72) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "red"
+ , Svg.Attributes.transform "rotate(144) translate(80)"
+ ]
+ []
+ ]
+
+Why 144? It's because 72 + 72 is 144! So to be 72 degree apart from a dot that's at 72 degree, you need to be at 144 (or 0, but the first dot is already there).
+
+This makes the last two dots trivial. Just rotate them to 216 and 288 and give them lime and maroon colors. Note that 288 + 72 = 360, so the distance between the first and last dot is correct.
+
+
+The complete program should look like this:
+
+| Code
+ module Main exposing (main)
+
+ import Element
+ import Svg
+ import Svg.Attributes
+
+
+ main =
+ Svg.svg
+ [ Svg.Attributes.viewBox "-100 -100 200 200"
+ ]
+ [ Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.transform "translate(80)"
+ , Svg.Attributes.fill "skyblue"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "orange"
+ , Svg.Attributes.transform "rotate(72) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "red"
+ , Svg.Attributes.transform "rotate(144) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "lime"
+ , Svg.Attributes.transform "rotate(216) translate(80)"
+ ]
+ []
+ , Svg.circle
+ [ Svg.Attributes.r "10"
+ , Svg.Attributes.cx "0"
+ , Svg.Attributes.cy "0"
+ , Svg.Attributes.fill "maroon"
+ , Svg.Attributes.transform "rotate(288) translate(80)"
+ ]
+ []
+ ]
+ |> Element.html
+ |> Element.layout
+ [ Element.width Element.fill
+ , Element.height Element.fill
+ ]
+
+In the browser it should look exactly as we planned:
+
+| Window
+ | Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
+
+| Emphasize
+ Congtrarulations! You are ready for {Link|Day 3|url=/day-3.html}!index 7d4ced3..b38e6aa 100644
--- a/src/Examples/Circle.elm
+++ b/src/Examples/Circle.elm
@@ -23,6 +23,14 @@ type alias Config =
= }
=
=
+
+{- TODO:
+ - Display radius (text)
+ - Display angles of turns (in degrees)
+ - Make an arrow head at the end point of the arc representing a turn (see https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/Arc2d#tangentDirection)
+-}
+
+
=main : Html.Html msg
=main =
= Element.layoutMake Monospace block font size smaller
On by
Otherwise Elm REPL welcom lines don't fit in the block and cause scroll.
index ca76c37..bfe94a4 100644
--- a/src/Mark/Custom.elm
+++ b/src/Mark/Custom.elm
@@ -63,7 +63,7 @@ monospace : Mark.Block (model -> Element msg)
=monospace =
= Mark.Default.monospace
= [ Element.padding 20
- , Font.size 18
+ , Font.size 14
= , Element.width Element.fill
= , Border.color colors.gray
= , Border.width 3Merge branch 'multiple-pages' into 'master'
On by
Split the content into multiple pages
Closes #1
See merge request software-garden/software-garden.gitlab.io!3
Fix slashes in inlines by upgrading mdgriffith/elm-markup to 2.0.5
On by
index 07ece92..b321d9d 100644
--- a/elm.json
+++ b/elm.json
@@ -22,7 +22,7 @@
= "feathericons/elm-feather": "1.2.0",
= "ianmackenzie/elm-geometry": "1.2.1",
= "ianmackenzie/elm-geometry-svg": "1.0.2",
- "mdgriffith/elm-markup": "2.0.2",
+ "mdgriffith/elm-markup": "2.0.5",
= "mdgriffith/elm-ui": "1.1.0",
= "turboMaCk/any-dict": "1.0.1"
= },
@@ -40,4 +40,4 @@
= "direct": {},
= "indirect": {}
= }
-}
\ No newline at end of file
+}Fix "Elm" capitalization in day-1
On by
index 78ccd3e..9767b34 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -11,7 +11,7 @@
= | List
= -> Scalable Vector Graphics
= -> Cartesian Coordinates Systems
- -> Layouts with ELM UI
+ -> Layouts with Elm UI
=
=
=| HeaderChange directory name to "software-garden"
On by
index 9767b34..228262e 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -20,16 +20,17 @@
=As mentioned before, programs are represented as text (called the /source code/). The source code is stored in files {Icon|name=file} and files are organized in directories {Icon|name=folder}.
=
=
-So the first step is to create a directory for our new program. Lets call it fpart.
+So the first step is to create a directory for our new program. Let's call it "software-garden".
+
=In the terminal type:
=
=| Monospace
- mkdir fpart/
+ mkdir software-garden/
=
=and then:
=
=| Monospace
- cd fpart/
+ cd software-garden/
=
=The first command will create our new directory and the second will make it the current directory. Again, don't worry about the details.
=Elaborate on pressing Enter in terminal
On by
index 228262e..b64da0d 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -27,14 +27,17 @@ In the terminal type:
=| Monospace
= mkdir software-garden/
=
-and then:
+press enter key. Then type:
=
=| Monospace
= cd software-garden/
=
-The first command will create our new directory and the second will make it the current directory. Again, don't worry about the details.
+| Note
+ Press enter again. Generally when we ask you to type something in a terminal, we imply that you press enter afterwards. That's how you signal that you are done typing and expect computer to process your command. Alternatively we call it entering a command.
+
+ In this case the first command will create our new directory and the second will make it the current directory. Again, don't worry about the details.
=
-We can easily create a new program by typing:
+We can easily create a new program by entering a following command:
=
=| Monospace
= elm initExplain that we need to change directory after opening a terminal
On by
index b64da0d..9a5ba1a 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -35,7 +35,7 @@ press enter key. Then type:
=| Note
= Press enter again. Generally when we ask you to type something in a terminal, we imply that you press enter afterwards. That's how you signal that you are done typing and expect computer to process your command. Alternatively we call it entering a command.
=
- In this case the first command will create our new directory and the second will make it the current directory. Again, don't worry about the details.
+ In this case the first command will create our new directory and the second will make it the current directory, so that subsequent commands will be executed in it's context. Again, don't worry about the details, but if you close your terminal and then open it again, you will need to enter `cd software-garden/` to set this context again.
=
=We can easily create a new program by entering a following command:
=Mention that you can use other editor than Atom
On by
index 9a5ba1a..9c72fa3 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -47,7 +47,7 @@ Then to create the file which will contain our source code, type:
=| Monospace
= atom src/Main.elm
=
-This command should open a new Atom window with an empty text file.
+This command should open a new Atom window with an empty text file. If you prefer to use different editor, feel free to do so.
=
=| Header
= Main.elmFix link label in day-1
On by
index 9c72fa3..713c2a3 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -77,7 +77,7 @@ This command will start the Elm reactor, which will allow you to run your progra
=Open following address in the web browser:
=
=| Emphasize
- {Link|http://localhost:8000/src/Main.elm|url=http://localhost:8000/src/Main.elm}
+ {Link|http:////localhost:8000//src//Main.elm|url=http://localhost:8000/src/Main.elm}
=
=| Note
= *TODO*: Make the link display // charactersMerge branch 'master' into day-2
On by
Fix typo
On by
index 3dd306a..b9410fd 100644
--- a/content/day-2.txt
+++ b/content/day-2.txt
@@ -426,4 +426,4 @@ In the browser it should look exactly as we planned:
= scatter = False
=
=| Emphasize
- Congtrarulations! You are ready for {Link|Day 3|url=/day-3.html}!
+ Congratulations! You are ready for {Link|Day 3|url=/day-3.html}!Add links to Day 2 from index and Day 1
On by
index 78ccd3e..9f2145e 100644
--- a/content/day-1.txt
+++ b/content/day-1.txt
@@ -548,3 +548,9 @@ Only one dot! We see the second one, but what happened to the first dot? It's un
=As an exercise, try adding an {Code|Svg.Attribute.cy} attribute to the circles to adjust their vertical position.
=
=For a more advanced exercise, try adding a new circle. Why not draw 5 circles on the screen? Give them each a unique color and position.
+
+| Emphasize
+ {Icon|name=award}
+
+| Emphasize
+ We really hope you enjoyed this first day of our workshop. See you at {Link|Day 2|url=/day-2.html}!index 58f6798..39d8332 100644
--- a/content/index.txt
+++ b/content/index.txt
@@ -10,4 +10,5 @@
=| List
= # {Link|Before the course begins|url=/preparation.html}
= # {Link|Day 1 - Let's Make a Dot|url=/day-1.html}
+ # {Link|Day 2 - Let's Place the Dots in a Circle|url=/day-2.html}
= # {Link|The rest - Work in progress|url=/rest.html}Remove Debug.log calls from Circle
On by
index b38e6aa..35baf6c 100644
--- a/src/Examples/Circle.elm
+++ b/src/Examples/Circle.elm
@@ -66,7 +66,6 @@ ui config =
= 0
= :: angles
= |> pairs
- |> Debug.log "pairs"
= |> List.indexedMap arc
= |> Svg.g []
=
@@ -123,7 +122,6 @@ ui config =
=
= radi =
= angles
- |> Debug.log "angles"
= |> List.map radius
= |> Svg.g []
=Express the Day 2 motto in "Let's ..." style
On by
index b9410fd..c28bbed 100644
--- a/content/day-2.txt
+++ b/content/day-2.txt
@@ -2,7 +2,7 @@
= Day 2
=
=| Emphasize
- Place the dots in a circle
+ Let's Place the Dots in a Circle
=
=
=| NotePut scattered and evenly distributed examples next to each other
On by
Implement new block: Row
index c28bbed..edb1bc0 100644
--- a/content/day-2.txt
+++ b/content/day-2.txt
@@ -105,37 +105,44 @@ Next slightly rotate the ruler around the center (keep point {Code|0} of the rul
=
=In other words, you can put a thing in the center and then move it in any direction, let's say 1 meter. If you do the same to several things in several directions (but same length), you will make them lay on a circle. The direction must be different each time. Otherwise the things would just stack one on top of another! We wouldn't call it a circle, right?
=
-Now, notice that the dots displayed by the program we are creating are not laying just anywhere on the circle. They are evenly distributed:
+Now, notice that the dots displayed by the program we are creating are not laying just anywhere on the circle. They are evenly distributed. It means that not only the distance between each dot and the center is the same. Also each dots lay the same distance away from it's two nearest neighbors. Just compare the following two pictures:
=
-| Circle
- dots = 5
- circle = 0 1
- angles = 0 1
- center = none
- radius = 0 1
- scatter = False
+| Row
+ | Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = True
=
-It means that not only the distance between each dot and the center is the same. Also each dots lay the same distance away from it's two nearest neighbors.
+ | Circle
+ dots = 5
+ circle = 0 1
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
=
-Just compare it with the following picture:
+Both are showing 5 dots laying on a circle. Look:
=
-| Circle
- dots = 5
- circle = 0 1
- angles = 0 1
- center = none
- radius = 0 1
- scatter = True
+| Row
+ | Circle
+ dots = 5
+ circle = 3
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = True
=
-These are also 5 dots laying on a circle. Look:
+ | Circle
+ dots = 5
+ circle = 3
+ angles = 0 1
+ center = none
+ radius = 0 1
+ scatter = False
=
-| Circle
- dots = 5
- circle = 3
- angles = 0 1
- center = none
- radius = 0 1
- scatter = True
=
=| Note
= IDEA: An interactive program (game of sorts) that shows a ruler and dots. User can drag the ruler around and rotate it. Also dots can be dragged around. Once the dots are placed on a circle, the program rewards the user with a nice animation and message. It would be super awesome to make it touch capable {Icon|name=award}
@@ -145,7 +152,7 @@ These are also 5 dots laying on a circle. Look:
= In the mean time we have two non-interactive examples with evenly and randomly distributed dots.
=
=
-So they lay on a circle, but there is a striking difference. They are all scattered! This means that there is something missing in our solution. We need to take care of one more aspect when we place our dots.
+So the dots on the left lay on a circle, but there is a striking difference. They are all scattered! This means that there is something missing in our solution. We need to take care of one more aspect when we place our dots.
=
=Since the center and radius is the same for each dot, the only thing we can play with is the angle that we rotate the ruler each time.
=index 444dac4..f8def73 100644
--- a/src/Main.elm
+++ b/src/Main.elm
@@ -450,57 +450,41 @@ document =
= )
= Mark.Custom.title
= (Mark.manyOf
- [ Mark.Custom.header
- , Mark.Custom.paragraph
- , Mark.Custom.monospace
- , Mark.Custom.code
- , Mark.Custom.note
- , Mark.Custom.emphasize
- , Mark.Custom.list
- , Mark.Custom.image
-
- -- Embeded programs
- , counter
- , dot
- , dotInElement
- , dotWithViewBox
- , twoDots
- , circle
- , line
- , gradient
- , transformations
- , nestedTransformations
- , cartesianCoordinates
- , polarCoordinates
- , rosette
- , spiral
- , tree
- , viewBox
-
- -- Window block can contain any embeded program
- , Mark.Custom.window
- (Mark.oneOf
- [ counter
- , dot
- , dotInElement
- , dotWithViewBox
- , twoDots
- , circle
- , line
- , gradient
- , transformations
- , nestedTransformations
- , cartesianCoordinates
- , polarCoordinates
- , rosette
- , spiral
- , tree
- , viewBox
- ]
- )
- ]
+ ([ Mark.Custom.header
+ , Mark.Custom.paragraph
+ , Mark.Custom.monospace
+ , Mark.Custom.code
+ , Mark.Custom.note
+ , Mark.Custom.emphasize
+ , Mark.Custom.list
+ , Mark.Custom.image
+ ]
+ ++ examples
+ ++ [ Mark.Custom.window (Mark.oneOf examples)
+ , Mark.Custom.row (Mark.manyOf examples)
+ ]
+ )
= )
=
+ examples =
+ [ counter
+ , dot
+ , dotInElement
+ , dotWithViewBox
+ , twoDots
+ , circle
+ , line
+ , gradient
+ , transformations
+ , nestedTransformations
+ , cartesianCoordinates
+ , polarCoordinates
+ , rosette
+ , spiral
+ , tree
+ , viewBox
+ ]
+
= -- Embeded programs' blocks
= counter : Mark.Block (Model -> Element Msg)
= counter =index bfe94a4..193f700 100644
--- a/src/Mark/Custom.elm
+++ b/src/Mark/Custom.elm
@@ -10,6 +10,7 @@ module Mark.Custom exposing
= , monospace
= , note
= , paragraph
+ , row
= , text
= , title
= , window
@@ -141,6 +142,29 @@ window block =
= block
=
=
+row :
+ Mark.Block (List (a -> Element msg))
+ -> Mark.Block (a -> Element msg)
+row block =
+ let
+ render children model =
+ children
+ |> List.map (\child -> child model)
+ |> List.map
+ (Element.el
+ [ Element.width Element.fill
+ , Border.width 1
+ , Border.rounded 5
+ , Border.color (Element.rgb 0.6 0.6 0.6)
+ ]
+ )
+ |> Element.row [ Element.spacing 20 ]
+ in
+ Mark.block "Row"
+ render
+ block
+
+
=note : Mark.Block (model -> Element msg)
=note =
= letAdd ACME challenge code for Let's Encrypt verification
On by
Temporarily enable this branch (custom-domain) in CI, so we can test if it works before merging.
index 4472935..28e2f71 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -15,3 +15,4 @@ pages:
=
= only:
= - master
+ - custom-domainnew file mode 100644
index 0000000..44f3504
--- /dev/null
+++ b/.well-known/acme-challenge/HVUehfup9PAAASIMOcJoCGvD9q9bzX_W_tBUSSI6RXI
@@ -0,0 +1 @@
+HVUehfup9PAAASIMOcJoCGvD9q9bzX_W_tBUSSI6RXI.HvUI1nPJPHTnM--CR4G53bMPL5yhCFd2qGlsMDuIw14