Skip to content
Browse files

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

… style change to area of parallelograms.
  • Loading branch information...
1 parent a46a295 commit b41affcf17bac9f976bb472b956eb7db6ba2252c @osnr osnr committed
View
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() {
View
257 exercises/areas_of_trapezoids_rhombi_and_kites.html
@@ -0,0 +1,257 @@
+<!DOCTYPE html>
+<html data-require="math graphie word-problems subhints graphie-geometry">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Areas of trapezoids, rhombi, and kites</title>
+ <script src="../khan-exercise.js"></script>
+</head>
+<body>
+ <div class="exercise">
+ <div class="vars">
+ <var id="UNIT,UNIT_TEXT">randFromArray([
+ ["in", "inch"],
+ ["ft", "foot"],
+ ["m", "meter"],
+ ["cm", "centimeter"],
+ ["", "unit"]
+ ])</var>
+ </div>
+
+ <div class="problems">
+ <div id="trapezoid">
+ <div class="vars">
+ <var id="B1">randRange(2, 8)</var>
+ <var id="B2">randRange(2, 8)</var>
+ <var id="H">randRange(1, 6)</var>
+
+ <var id="SH">randRangeNonZero(-2, 2)</var>
+
+ <var id="K">1/2 * (B1 + B2) * H</var>
+ </div>
+
+ <div class="question">What is the area of this figure?</div>
+
+ <div class="graphie" id="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 });
+ </div>
+
+ <div class="solution" data-type="multiple">
+ <span class="sol"><var>K</var></span>
+ square <var>plural(UNIT_TEXT)</var>
+ </div>
+
+ <div class="hints">
+ <p>This figure is a quadrilateral with a pair of parallel sides (the top and bottom sides), so it&#39;s a trapezoid.</p>
+ <div>
+ <p>
+ area of a trapezoid <code>= \dfrac12 \cdot (b_1 + b_2) \cdot h</code>
+ [<a href="#" class="show-subhint" data-subhint="area-trapezoid">Show me why</a>]
+ </p>
+ <div class="subhint" id="area-trapezoid">
+ <p>Let&#39;s draw a line between the opposite ends of the two bases.</p>
+ <div class="graphie" data-update="figure">
+ 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();
+ </div>
+ <p>Notice that the line divides the trapezoid into two triangles: one triangle with base <code>b_1 = <var>B1</var></code>, and another triangle with base <code>b_2 = <var>B2</var></code>. Both triangles have height <code>h = <var>H</var></code>.</p>
+ <p>The area of the trapezoid is equal to the sum of the areas of the two trapezoids.</p>
+ <p><code>A = \dfrac12 \cdot b_1 \cdot h + \dfrac12 \cdot b_2 \cdot h</code></p>
+ <p>Factor out <code>\dfrac12 \cdot h</code> to get the formula for the area of a trapezoid:</p>
+ <p><code>A = \dfrac12 \cdot h \cdot (b_1 + b_2) = \dfrac12 \cdot (b_1 + b_2) \cdot h</code></p>
+ </div>
+ </div>
+ <div>
+ <p>Now use this formula to calculate the trapezoid&#39;s area.</p>
+ <p><code>b_1 = <var>B1</var></code></p>
+ <p><code>b_2 = <var>B2</var></code></p>
+ <p><code>h = <var>H</var></code></p>
+ <p><code>A = \dfrac12 \cdot (<var>B1</var> + <var>B2</var>) \cdot <var>H</var> = <var>K</var></code></p>
+ </div>
+ </div>
+ </div>
+
+ <div id="kite">
+ <div class="vars" data-ensure="D1 &gt; SH">
+ <var id="D1">randRange(1, 7) * 2</var>
+ <var id="D2">randRange(1, 7) * 2</var>
+
+ <var id="ORIENT">randFromArray(["v", "h"])</var>
+ <var id="SH">rand(3) !== 0 ? randRange(1, 5) : D1/2</var>
+
+ <var id="K">1/2 * D1 * D2</var>
+
+ <var id="RHOMBUS">SH === D1/2</var>
+ </div>
+
+ <div class="question">What is the area of this figure?</div>
+
+ <div class="graphie" id="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 });
+ </div>
+
+ <div class="solution" data-type="multiple">
+ <span class="sol"><var>K</var></span>
+ square <var>plural(UNIT_TEXT)</var>
+ </div>
+
+ <div class="hints">
+ <div>
+ <p>This figure is a quadrilateral with perpendicular diagonals and two pairs of congruent, adjacent sides, so it is a kite.</p>
+ <p data-if="SH === D1/2">In fact, because this shape's sides are all congruent, it is also a rhombus.</p>
+ </div>
+ <div>
+ <p>
+ area of a kite <code>= \dfrac12 \cdot d_1 \cdot d_2</code>
+ [<a href="#" class="show-subhint" data-subhint="area-kite">Show me why</a>]
+ </p>
+ <div class="subhint" id="area-kite">
+ <p>The <span data-if="ORIENT === 'h'">horizontal</span><span data-else>vertical</span> diagonal in the center splits the kite into two congruent triangles.</p>
+ <div class="graphie" data-update="figure">
+ 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();
+ </div>
+ <p>Let <code>d_1 = <var>D1</var></code>, the diagonal that bisects the kite. Then let <code>d_2 = <var>D2</var></code>.</p>
+ <p>Notice that <code>d_1</code> is the base of both triangles, and <code>d_2</code> is the combined height of the two triangles, so <code>\dfrac{d_2}{2}</code> is the height of each triangle.</p>
+ <p>So the area of each triangle is:</p>
+ <p><code>A_T = \dfrac12 \cdot b \cdot h = \dfrac12 \cdot d_1 \cdot \dfrac{d_2}{2} = \dfrac14 \cdot d_1 \cdot d_2</code></p>
+ <p>The area of both triangles combined, <code>2A_T</code>, is the total area of the kite:</p>
+ <p><code>2A_T = 2(\dfrac14 \cdot d_1 \cdot d_2) = \dfrac12 \cdot d_1 \cdot d_2 = A</code></p>
+ </div>
+ </div>
+ <div>
+ <p>Now use this formula to calculate the kite's area.</p>
+ <p><code>d_1 = <var>D1</var></code></p>
+ <p><code>d_2 = <var>D2</var></code></p>
+ <p><code>A = \dfrac12 \cdot <var>D1</var> \cdot <var>D2</var> = <var>K</var></code></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
View
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),

0 comments on commit b41affc

Please sign in to comment.
Something went wrong with that request. Please try again.