// Click the Run button in the toolbar above to start the story
//
// =================================================================
//
// Archimedes' estimation of PI
//
val S = Staging
val unit = 100
def rads(degree: Double) = degree * Math.Pi / 180.0
val headerStyle = "text-align:center;font-size:110%;color:maroon;"
var page: StoryPage = _
var header: xml.Node = _
var pages = new collection.mutable.ListBuffer[StoryPage]
def pgHeader(hdr: String) =
<p style={headerStyle}>
{new xml.Unparsed(hdr)}
<hr/>
</p>
header = pgHeader("Archmedes' Pi")
page = Page(
name = "Archimedes's estimation of Pi",
body =
<body style="margin:15px;">
<h1>Archimedes' estimation of Pi</h1>
<p>
We're going to explore the method Archimedes used for estimating the
value of <em>pi</em> represented by the symbol:
{stFormula("""\pi""")}.
</p>
</body>,
code = {}
)
pages += page
def drawCircle(radius: Int)
{
var side = (2 * Math.Pi * radius) / 360
setPosition(-radius, 0)
setPenColor(blue)
setFillColor(green)
setAnimationDelay(0)
repeat(360)
{
forward(side)
right(1)
}
}
page = Page(
name = "Pi - Definition",
body =
<body style="margin:15px;">
<h1>Definition of PI</h1>
<p> PI is defined as the ratio of a circle's circumference to its diameter.
See the circle on the right, whose radius can be controlled using the slider.
</p>
</body>,
code = {
clear()
Mw.clear()
Mw.hideAlgebraView()
Mw.showAxes()
Mw.variable("r", 4, 0, 10, 0.5, 50, 50)
Mw.evaluate("Circle[(0, 0), r]")
}
//S.reset()
//S.fill(green)
//S.circle(S.O, unit)
//S.setFillColor(green)
//S.setPenColor(blue)
//S.line(-unit, 0, unit, 0)
//S.text("diameter", -20, 20)
// drawCircle(unit)
)
pages += page
// A method to return the points of a regular polygon of N points
// inscribed in the circle with the supplied radius
// center: The center of the circle
// radius: The radius of the circle in which we want to inscribe the polygon
// nSides: The number of sides of the polygon
// initialAngle: The angle by which we want to rotate the polygon counter-clockwise
def getPolygonPoints(center: Point,
radius: Double,
nSides: Int,
initialAngle: Double) : List[Point] =
{
// We will first generate the inital set of points on a circle with radius 100, along origin 0,0
// with an initalAngle of (0,0).
// Once we have those points, we will transform according to the args
var initialPt = new Point(0, radius)
def createPoint(count: Int) : Point = {
var theta = rads(360.0/nSides * count + initialAngle);
var cosTheta = Math.cos(theta)
var sinTheta = Math.sin(theta)
var newX = initialPt.x * cosTheta - initialPt.y * sinTheta
var newY = initialPt.x * sinTheta + initialPt.y * cosTheta
new Point(newX + center.x, newY + center.y)
}
for(i <- List.range(0, nSides)) yield createPoint(i)
}
// Draw the inner and outer polygons and trap a circle within them
def drawCircleAndPoly(radius: Double, nSides: Int) =
{
val initialAngle = 180.0 / nSides
val radiusOuter = radius / Math.cos(rads(initialAngle))
gridOff()
axesOff()
val innerPerimeter = Math.sin(rads(initialAngle)) * nSides
val outerPerimeter = Math.tan(rads(initialAngle)) * nSides
S.text("%1.10f < pi < %1.10f" format(innerPerimeter, outerPerimeter), -110, 160)
S.text("pi ~ %1.10f" format((innerPerimeter + outerPerimeter)/2), -110, 140)
val innerPoly = getPolygonPoints(S.O, radius, nSides, 0)
val outerPoly = getPolygonPoints(S.O, radiusOuter, nSides, initialAngle)
// Mark the origin
S.dot(S.O)
// Now draw the outer polygon
S.setPenColor(blue)
S.setFillColor(yellow)
S.polygon(outerPoly)
// Draw the circle
S.setPenColor(green)
S.setFillColor(new Color(255, 0, 255))
S.circle(S.O, radius)
// Draw the inner polygon
S.setPenColor(red)
S.setFillColor(new Color(255, 255, 255))
S.polygon(innerPoly)
}
page = Page(
name = "Polygons - inscribed and circumscribed",
body =
<body>
<h1>Trapping the circle</h1>
<p>The circle is inscribed and circumscribed by a regular Pentagon (5 sided polygon).</p>
<p>Try changing the number of sides below to see how the circle gets
<em>trapped</em> by the two Polygons </p>
</body>,
code = {
drawCircleAndPoly(100, 5)
stAddField("Sides", 5)
stAddButton ("Make Polygons") {
val size = stFieldValue("Sides", 5)
S.reset()
drawCircleAndPoly(100, size)
}
}
)
pages += page
val story = Story(pages: _*)
stClear()
stPlayStory(story)