# Khan/khan-exercises

Add new exercise: areas of trapezoids, rhombi, and kites. Also teensy…

… style change to area of parallelograms.
1 parent a46a295 commit b41affcf17bac9f976bb472b956eb7db6ba2252c osnr committed
4 exercises/area_of_parallelograms.html
 @@ -19,11 +19,11 @@ return { drawBase: function() { - base = graph.path([[0, 0], [B, 0]], { "stroke": KhanUtil.ORANGE }); + base = graph.path([[0, 0], [B, 0]], { stroke: KhanUtil.ORANGE }); baseL = graph.label([B/2, 0], "\\color{" + KhanUtil.ORANGE + "}{b = " + B + "\\text{ " + UNIT + "}}", "below"); }, drawHeight: function() { - height = graph.path([[B, 0], [B, H]], { "stroke": KhanUtil.BLUE, "stroke-dasharray": "." }); + height = graph.path([[B, 0], [B, H]], { stroke: KhanUtil.BLUE, strokeDasharray: "." }); heightL = graph.label([B, H/2], "\\color{" + KhanUtil.BLUE + "}{h = " + H + "\\text{ " + UNIT + "}}", "right"); }, drawArea: function() {
257 exercises/areas_of_trapezoids_rhombi_and_kites.html
 @@ -0,0 +1,257 @@ + + + + + Areas of trapezoids, rhombi, and kites + + + +
+
+ randFromArray([ + ["in", "inch"], + ["ft", "foot"], + ["m", "meter"], + ["cm", "centimeter"], + ["", "unit"] + ]) +
+ +
+
+
+ randRange(2, 8) + randRange(2, 8) + randRange(1, 6) + + randRangeNonZero(-2, 2) + + 1/2 * (B1 + B2) * H +
+ +
What is the area of this figure?
+ +
+ init({ + range: [[-4, max(B1, B2) + 4], [-1, H + 1]], + scale: [30, 30] + }); + + var v = [[0, 0], [B1, 0], [B2 + SH, H], [SH, H], [0, 0]]; + + style({ stroke: BLUE, fill: "#eee"}, + function() { + path(v); + + label([B1/2, 0], B1 + "\\text{ " + UNIT + "}", "below"); + label([B2/2 + SH, H], B2 + "\\text{ " + UNIT + "}", "above"); + + path([[B1, 0], [B1, H]], H, { strokeDasharray: "." }); + label([B1, H/2], H + "\\text{ " + UNIT + "}", "right"); + + parallel([[0, 0], [B1, 0]], 1); + parallel([[SH, H], [B2 + SH, H]], 1); + }); + + rightAngleBox([[0, 0], [B1, 0]], [[B1, 0], [B1, H]], { stroke: GRAY, opacity: 0.5 }); +
+ +
+ K + square plural(UNIT_TEXT) +
+ +
+

This figure is a quadrilateral with a pair of parallel sides (the top and bottom sides), so it's a trapezoid.

+
+

+ area of a trapezoid = \dfrac12 \cdot (b_1 + b_2) \cdot h + [Show me why] +

+
+

Let's draw a line between the opposite ends of the two bases.

+
+ var showSubHint = function() { + graph.subhint.show(); + + $("a[data-subhint='area-trapezoid']") + .unbind("click", showSubHint) + .click(hideSubHint); + }; + + var hideSubHint = function() { + graph.subhint.hide(); + +$("a[data-subhint='area-trapezoid']") + .unbind("click", hideSubHint) + .click(showSubHint); + }; + + graph.subhint = raphael.set().push( + path([[0, 0], [B1, 0], [B2 + SH, H]], { stroke: BLUE, fill: ORANGE, opacity: 0.5 }), + path([[SH, H], [B2 + SH, H], [0, 0]], { stroke: BLUE, fill: RED, opacity: 0.5 }) + ); + hideSubHint(); +
+

Notice that the line divides the trapezoid into two triangles: one triangle with base b_1 = B1, and another triangle with base b_2 = B2. Both triangles have height h = H.

+

The area of the trapezoid is equal to the sum of the areas of the two trapezoids.

+

A = \dfrac12 \cdot b_1 \cdot h + \dfrac12 \cdot b_2 \cdot h

+

Factor out \dfrac12 \cdot h to get the formula for the area of a trapezoid:

+

A = \dfrac12 \cdot h \cdot (b_1 + b_2) = \dfrac12 \cdot (b_1 + b_2) \cdot h

+
+
+
+

Now use this formula to calculate the trapezoid's area.

+

b_1 = B1

+

b_2 = B2

+

h = H

+

A = \dfrac12 \cdot (B1 + B2) \cdot H = K

+
+
+
+ +
+
+ randRange(1, 7) * 2 + randRange(1, 7) * 2 + + randFromArray(["v", "h"]) + rand(3) !== 0 ? randRange(1, 5) : D1/2 + + 1/2 * D1 * D2 + + SH === D1/2 +
+ +
What is the area of this figure?
+ +
+ var range, v; + var drawCongruencies, drawD1, drawD2; + if (ORIENT === "h") { + range = [[-1, D1 + 2], [-D2/2 - 1, D2/2 + 1]]; + v = [[0, 0], [SH, D2/2], [D1, 0], [SH, -D2/2], [0, 0]]; + + drawCongruencies = function(style) { + congruent([[0, 0], [SH, D2/2]], 1, style); + congruent([[0, 0], [SH, -D2/2]], 1, style); + + congruent([[SH, D2/2], [D1, 0]], RHOMBUS ? 1 : 2, style); + congruent([[SH, -D2/2], [D1, 0]], RHOMBUS ? 1 : 2, style); + }; + drawD1 = function(style) { + return { + label: label([D1/2, 0], D1 + "\\text{ " + UNIT + "}", style), + path: path([[0, 0], [D1, 0]], style) + }; + }; + drawD2 = function(style) { + return { + label: label([D1, 0], D2 + "\\text{ " + UNIT + "}", "right", style), + path: path([[D1, -D2/2], [D1, D2/2]], style) + }; + }; + } else { + range = [[-D2/2 - 1, D2/2 + 1], [-1, D1 + 2]]; + v = [[0, 0], [D2/2, SH], [0, D1], [-D2/2, SH], [0, 0]]; + + drawCongruencies = function(style) { + congruent([[0, 0], [D2/2, SH]], 1); + congruent([[0, 0], [-D2/2, SH]], 1); + + congruent([[D2/2, SH], [0, D1]], RHOMBUS ? 1 : 2); + congruent([[0, D1], [-D2/2, SH]], RHOMBUS ? 1 : 2); + }; + drawD1 = function(style) { + return { + label: label([0, D1/2], D1 + "\\text{ " + UNIT + "}", style), + path: path([[0, 0], [0, D1]], style) + }; + }; + drawD2 = function(style) { + return { + label: label([0, D1], D2 + "\\text{ " + UNIT + "}", "above", style), + path: path([[-D2/2, D1], [D2/2, D1]], style) + }; + }; + } + + init({ range: range, scale: 20 }); + + path(v, { stroke: BLUE, fill: "#eee" }); + drawCongruencies({ stroke: BLUE }); + + style({ stroke: BLUE, strokeDasharray: "." }, function() { + graph.d1 = drawD1(); + graph.d2 = drawD2(); + }); + rightAngleBox(graph.d1.path.graphiePath, graph.d2.path.graphiePath, { stroke: GRAY, opacity: 0.5 }); +
+ +
+ K + square plural(UNIT_TEXT) +
+ +
+
+

This figure is a quadrilateral with perpendicular diagonals and two pairs of congruent, adjacent sides, so it is a kite.

+

In fact, because this shape's sides are all congruent, it is also a rhombus.

+
+
+

+ area of a kite = \dfrac12 \cdot d_1 \cdot d_2 + [Show me why] +

+
+

The horizontalvertical diagonal in the center splits the kite into two congruent triangles.

+
+ var showSubHint = function() { + graph.subhint.show(); + + $("a[data-subhint='area-kite']") + .unbind("click", showSubHint) + .click(hideSubHint); + }; + + var hideSubHint = function() { + graph.subhint.hide(); + +$("a[data-subhint='area-kite']") + .unbind("click", hideSubHint) + .click(showSubHint); + }; + + if (ORIENT === "h") { + graph.subhint = raphael.set().push( + path([[0, 0], [SH, D2/2], [D1, 0], [0, 0]], { fill: ORANGE, opacity: 0.5 }), + path([[0, 0], [SH, -D2/2], [D1, 0], [0, 0]], { fill: GREEN, opacity: 0.5 }) + ); + } else { + graph.subhint = raphael.set().push( + path([[0, 0], [D2/2, SH], [0, D1], [0, 0]], { fill: ORANGE, opacity: 0.5 }), + path([[0, 0], [-D2/2, SH], [0, D1], [0, 0]], { fill: GREEN, opacity: 0.5 }) + ); + } + hideSubHint(); +
+

Let d_1 = D1, the diagonal that bisects the kite. Then let d_2 = D2.

+

Notice that d_1 is the base of both triangles, and d_2 is the combined height of the two triangles, so \dfrac{d_2}{2} is the height of each triangle.

+

So the area of each triangle is:

+

A_T = \dfrac12 \cdot b \cdot h = \dfrac12 \cdot d_1 \cdot \dfrac{d_2}{2} = \dfrac14 \cdot d_1 \cdot d_2

+

The area of both triangles combined, 2A_T, is the total area of the kite:

+

2A_T = 2(\dfrac14 \cdot d_1 \cdot d_2) = \dfrac12 \cdot d_1 \cdot d_2 = A

+
+
+
+

Now use this formula to calculate the kite's area.

+

d_1 = D1

+

d_2 = D2

+

A = \dfrac12 \cdot D1 \cdot D2 = K

+
+
+
+
+
+ +
124 utils/graphie-geometry.js
 @@ -14,6 +14,67 @@ function rotatePoint(p, deg, c) { return [KhanUtil.roundTo(9, x), KhanUtil.roundTo(9, y)]; } +function getSideMidpoint(path) { + return [(path[0][0] + path[1][0]) / 2, + (path[0][1] + path[1][1]) / 2]; +} + +$.extend(KhanUtil, { + rightAngleBox: function(path1, path2, style) { + var graph = KhanUtil.currentGraph; + + var size = 0.5; + + var intersection = findIntersection(path1, path2), + path = [intersection], + curr = graph.cartToPolar(intersection)[1], + offset; + + for (var i = 1; i < 4; i++) { + offset = graph.polar(size, curr); + + path.push([path[i - 1][0] - offset[0], + path[i - 1][1] - offset[1]]); + + curr -= 90; + } + + path.push(intersection); + + return graph.path(path, style); + }, + + parallel: function(path, num, style) { + var graph = KhanUtil.currentGraph; + + var spacing = 0.5; + + point = getSideMidpoint(path); + + graph.path([path[0], point],$.extend(style, { arrows: "->" })); + }, + + congruent: function(path, num, style) { + var graph = KhanUtil.currentGraph; + + var spacing = 5, scale = 5; + + for (var i = 0; i < num; i++) { + var sPath = _.map(path, graph.scalePoint), + sPoint = getSideMidpoint(sPath), + angle = Math.atan((sPath[0][1] - sPath[1][1]) / (sPath[0][0] - sPath[1][0])), + perpangle = angle + Math.PI / 2; + + var sMarkPath = [[sPoint[0] + Math.cos(angle)*spacing*i + Math.cos(perpangle)*scale, + sPoint[1] + Math.sin(angle)*spacing*i + Math.sin(perpangle)*scale], + [sPoint[0] + Math.cos(angle)*spacing*i - Math.cos(perpangle)*scale, + sPoint[1] + Math.sin(angle)*spacing*i - Math.sin(perpangle)*scale]]; + + graph.path(_.map(sMarkPath, graph.unscalePoint), style); + } + } +}); + function RegularPolygon(center, numSides, radius, rotation, fillColor) { var graph = KhanUtil.currentGraph; rotation = rotation || 0; @@ -53,6 +114,69 @@ function RegularPolygon(center, numSides, radius, rotation, fillColor) { return graph.line(rotatePoint(coords[0], fudge), rotatePoint(coords[1], fudge), { stroke: color }); } + this.drawSide = function(style) { + return graph.line(this.path.graphiePath[0], this.path.graphiePath[1], style); + } + + this.drawSideLabel = function(s, color) { + var path = this.path.graphiePath; + return graph.label(getSideMidpoint(path), "\\color{"+color+"}{"+s+"}", "right"); + } + + this.drawRadius = function(style) { + var vertex = this.path.graphiePath[0]; + + return graph.line(center, vertex, style); + } + + this.drawRadiusLabel = function(r, color) { + var vertex = this.path.graphiePath[0]; + + return graph.label([(vertex[0] - center[0]) / 2, (vertex[1] - center[1]) / 2], "\\color{"+color+"}{"+r+"}", "below"); + } + + this.drawApothem = function(style) { + return graph.line(center, getSideMidpoint(this.path.graphiePath), style); + } + + this.drawApothemLabel = function(a, color) { + var midpoint = getSideMidpoint(this.path.graphiePath); + + return graph.label([(midpoint[0] - center[0]) / 2, (midpoint[1] - center[1]) / 2], "\\color{"+color+"}{"+a+"}", "above"); + } + + this.drawRightBox = function(style) { + + } + + this.drawCentralAngle = function(style) { + return graph.arc(center, 0.5, 0, 180 / numSides, null, style); + } + + this.drawCentralAngleLabel = function(t, color) { + return graph.label(center, "\\color{"+color+"}{"+t+"}", "above right"); + } + + this.drawIncircle = function(style) { + return graph.circle(center, KhanUtil.getDistance(center, getSideMidpoint(this.path.graphiePath)), style); + } + + this.drawCircumcircle = function(style) { + return graph.circle(center, radius, style); + } + + this.drawRightTriangle = function(i, fromMidpoint, style) { + var vertex = this.path.graphiePath[i], + vertex2 = this.path.graphiePath[i + 1], + midpoint = lineMidpoint([vertex, vertex2]); + + if (fromMidpoint) { + return graph.path([center, midpoint, vertex2, center], style); + } else { + return graph.path([center, vertex, midpoint, center], style); + } + } + // Does not currently work with 2 points on one side this.splitPath = function(line) { var points = linePathIntersection(line, this.path),