diff --git a/Rakefile b/Rakefile index 2d95954..697427c 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,6 @@ require 'rake/testtask' desc 'Test' task :test do - sh 'jruby test/pbisector_test.rb' sh 'jruby test/circumcircle_test.rb' sh 'jruby test/triangle_points_test.rb' end diff --git a/lib/math_demo/circumcircle.rb b/lib/math_demo/circumcircle.rb index a10a42c..86a48cc 100644 --- a/lib/math_demo/circumcircle.rb +++ b/lib/math_demo/circumcircle.rb @@ -1,5 +1,5 @@ # Circumcircle from 3 points -require_relative './pbisector' +require 'matrix' class Circumcircle attr_reader :center, :radius, :points @@ -8,29 +8,36 @@ def initialize(points) end def calculate - ab = PBisector.new(points[0], points[1]) # find 2 midpoints - bc = PBisector.new(points[1], points[2]) - @center = circumcenter(ab, bc) + @center = Vec2D.new(-(bx / am), -(by / am)) @radius = center.dist(points[2]) # points[2] = c end private - Vect = Struct.new(:x, :y, :z) + # Matrix math see matrix_math.md and in detail + # http://mathworld.wolfram.com/Circumcircle.html - def circumcenter(pb1, pb2) - # equation of the first bisector (ax - y = -b) - a0 = Math.tan pb1.angle - v0 = pb1.midpoint - a1 = Math.tan pb2.angle - v1 = pb2.midpoint - eq0 = Vect.new(a0, -1, -1 * (v0.y - v0.x * a0)) - eq1 = Vect.new(a1, -1, -1 * (v1.y - v1.x * a1)) - # calculate x and y coordinates of the circumcenter - ox = (eq1.y * eq0.z - eq0.y * eq1.z) / - (eq0.x * eq1.y - eq1.x * eq0.y) - oy = (eq0.x * eq1.z - eq1.x * eq0.z) / - (eq0.x * eq1.y - eq1.x * eq0.y) - Vec2D.new(ox, oy) + def am + 2 * Matrix[ + [points[0].x, points[0].y, 1], + [points[1].x, points[1].y, 1], + [points[2].x, points[2].y, 1] + ].determinant + end + + def bx + -Matrix[ + [points[0].x * points[0].x + points[0].y * points[0].y, points[0].y, 1], + [points[1].x * points[1].x + points[1].y * points[1].y, points[1].y, 1], + [points[2].x * points[2].x + points[2].y * points[2].y, points[2].y, 1] + ].determinant + end + + def by + Matrix[ + [points[0].x * points[0].x + points[0].y * points[0].y, points[0].x, 1], + [points[1].x * points[1].x + points[1].y * points[1].y, points[1].x, 1], + [points[2].x * points[2].x + points[2].y * points[2].y, points[2].x, 1] + ].determinant end end diff --git a/lib/math_demo/matrix_math.md b/lib/math_demo/matrix_math.md new file mode 100644 index 0000000..56729c8 --- /dev/null +++ b/lib/math_demo/matrix_math.md @@ -0,0 +1,17 @@ +### Matrix Math ### + +For detailed workings see [Circumcircle at Mathworld Wolfram.com][circumcircle] + + +a = {{x1 y1 1}, {x2 y2 1}, {x3 y3 1}} + +bx = -{{x12 + y12 y1 1}, {x22 + y22 y2 1}, {x32 + y32 y3 1}} + +by = {{x12 + y12 x1 1}, {x22 + y22 x2 1}, {x32 + y32 x3 1}} + +xo = -bx / 2 * a + +yo = -by / 2 * a + + +[circumcircle]:http://mathworld.wolfram.com/Circumcircle.html diff --git a/lib/math_demo/pbisector.rb b/lib/math_demo/pbisector.rb deleted file mode 100644 index da68edb..0000000 --- a/lib/math_demo/pbisector.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'propane' - -# Perpendicular Bisector class, takes two points as Vec2D objects -class PBisector - attr_reader :midpoint, :angle - def initialize(a, b) - @midpoint = (a + b) / 2.0 - dvector = b - a - @angle = Math.atan2(dvector.y, dvector.x) - Math::PI / 2 - end -end diff --git a/lib/math_demo/version.rb b/lib/math_demo/version.rb index 07d65ed..8de73a7 100644 --- a/lib/math_demo/version.rb +++ b/lib/math_demo/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true # A wrapper for version module MathDemo - VERSION = '0.0.1'.freeze + VERSION = '0.1.0'.freeze end diff --git a/test/pbisector_test.rb b/test/pbisector_test.rb deleted file mode 100644 index f95a2b1..0000000 --- a/test/pbisector_test.rb +++ /dev/null @@ -1,28 +0,0 @@ -require_relative './test_helper' -require_relative '../lib/math_demo/pbisector' - -METHODS = %i(midpoint angle).freeze - -class PBisectorTest < Minitest::Test - def setup - @bisector = PBisector.new(Vec2D.new(100, 50), Vec2D.new(500, 350)) - end - - def test_respond - METHODS.each do |method_string| - assert_respond_to @bisector, method_string - end - end - - def test_midpoint - assert_equal @bisector.midpoint, Vec2D.new(300, 200) - end - - def test_angle # Angle of bisector to the 3, 4, 5 triangle - assert_in_delta @bisector.angle, 36.87.radians - Math::PI / 2 - end - - def tear_down - @bisector = nil? - end -end