lib/cossincalc/triangle/calculator.rb in cossincalc-1.0.6 vs lib/cossincalc/triangle/calculator.rb in cossincalc-1.0.7

- old
+ new

@@ -27,86 +27,68 @@ @equations ||= [] @equations << [latex, variables] end private - def each(*args, &block) - @triangle.each(*args, &block) + # Returns the first variable in the given array and the rest of the variables separately. + def first(vars) + return vars.first, rest(vars.first) end def sq(value) value.is_a?(Array) ? value.map { |n| n * n } : (value * value) end # Calculates all three angles when all three sides are known. def calculate_three_angles - each do |v, r| - unless angle(v) - angle[v] = calculate_angle_by_sides(v, r) - equation('@1=\arccos\left(\frac{$2^2+$3^2-$1^2}{2 * $2 * $3}\right)', v, *r) - end + each(angles.unknown) do |v, r| + angle[v] = calculate_angle_by_sides(v, r) + equation('@1=\arccos\left(\frac{$2^2+$3^2-$1^2}{2 * $2 * $3}\right)', v, *r) end end # Calculates two unknown angles when two sides and one angle are known. def calculate_two_angles - each do |v, r| - if angle(v) - unless side(v) - side[v] = sqrt sq(sides(r)).inject(&:+) - - 2 * sides(r).inject(&:*) * cos(angle(v)) - equation('$1=\sqrt{$2^2+$3^2-2 * $2 * $3 * \cos(@1)}', v, *r) - calculate_three_angles - break - end - - each(r) do |v2| - if side(v2) - angle[v2] = asin sin(angle(v)) * side(v2) / side(v) - equation('@2=\arcsin\left(\frac{\sin(@1) * $2}{$1}\right)', v, v2) - - if ambiguous_case?(v, v2) - @alt = CosSinCalc::Triangle.new(sides, angles, self) - @alt.angle[v2] = PI - angle(v2) - @alt.equation('@2=@pi-\arcsin\left(\frac{\sin(@1) * $2}{$1}\right)', v, v2) - @alt.calculate_side_and_angle - end - - calculate_two_sides - break - end - end - break - end + v, r = first(angles.known) + + unless side(v) + side[v] = sqrt sq(sides(r)).inject(&:+) - + 2 * sides(r).inject(&:*) * cos(angle(v)) + equation('$1=\sqrt{$2^2+$3^2-2 * $2 * $3 * \cos(@1)}', v, *r) + calculate_three_angles + return end + + v2, r2 = first sides.known(r) + angle[v2] = asin sin(angle(v)) * side(v2) / side(v) + equation('@2=\arcsin\left(\frac{\sin(@1) * $2}{$1}\right)', v, v2) + + if ambiguous_case?(v, v2) + @alt = CosSinCalc::Triangle.new(sides, angles, self) + @alt.angle[v2] = PI - angle(v2) + @alt.equation('@2=@pi-\arcsin\left(\frac{\sin(@1) * $2}{$1}\right)', v, v2) + @alt.calculate_side_and_angle + end + + calculate_two_sides end # Calculates up to two unknown sides when at least one side and two angles are known. def calculate_two_sides calculate_last_angle - - each do |v, r| - if side(v) - each(r) do |v2| - unless side(v2) - side[v2] = sin(angle(v2)) * side(v) / sin(angle(v)) - equation('$2=\frac{\sin(@2) * $1}{\sin(@1)}', v, v2) - end - end - break - end + v, r = first(sides.known) + + each sides.unknown(r) do |v2| + side[v2] = sin(angle(v2)) * side(v) / sin(angle(v)) + equation('$2=\frac{\sin(@2) * $1}{\sin(@1)}', v, v2) end end # Calculates the last unknown angle. def calculate_last_angle - each do |v, r| - unless angle(v) - angle[v] = PI - angles(r).inject(&:+) - equation('@1=@pi-@2-@3', v, *r) - break - end - end + v, r = first(angles.unknown) + angle[v] = PI - angles(r).inject(&:+) + equation('@1=@pi-@2-@3', v, *r) end # Calculates and returns whether the triangle has multiple solutions. # See http://en.wikipedia.org/wiki/Law_of_sines#The_ambiguous_case def ambiguous_case?(v1, v2)