パッポスの定理の図示
screen.rb
require 'bundler/setup' require 'cairo' require './cairo_gtk' include Math Width = 400; Height = 300 Xrange = [-10.0, 10.0] ScaleX = ScaleY = Width / (Xrange[1] - Xrange[0]) CPX = 0; CPY = 0 Surface = Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32, Width, Height) C = Cairo::Context.new(Surface) C.set_source_rgb(0, 0, 0) C.rectangle(0, 0, Width, Height) C.fill class WPoint def initialize(x, y) @x = x; @y = y end attr_reader :x, :y #WPointからPointを得る def get_point x = CPX + (@x - Width / 2) / ScaleX y = CPY - (@y - Height / 2) / ScaleY Point.new(x, y) end end class Point def initialize(x, y) @x = x; @y = y end attr_reader :x, :y def self.wo WPoint.new(0, 0).get_point end def self.limit WPoint.new(Width, Height).get_point end def self.o Point.new(0, 0) end def *(n) Point.new(@x * n, @y * n) end def +(po) Point.new(@x + po.x, @y + po.y) end def -(po) Point.new(@x - po.x, @y - po.y) end #PointからWPointを得る def get_wpoint x = Width / 2 + (@x - CPX) * ScaleX y = Height / 2 - (@y - CPY) * ScaleY WPoint.new(x, y) end def draw(color: [1, 0, 0]) po = get_wpoint C.set_source_rgb(color[0], color[1], color[2]) C.arc(po.x, po.y, 3, 0, 2 * Math::PI) C.fill self end end class Line def initialize(point, n) #point, nはPointクラス(pointは直線上の一点、nは直線の方向ベクトル) @point = point @lx = point.x; @ly = point.y a = sqrt(n.x ** 2 + n.y ** 2) raise LineError, "The line does not exist." if a.zero? @nx = n.x / a; @ny = n.y / a @n = Point.new(@nx, @ny) end attr_reader :point, :n, :lx, :ly, :nx, :ny def draw(color: [1, 1, 1]) p1 = (@point - @n * 1000).get_wpoint p2 = (@point + @n * 1000).get_wpoint C.set_source_rgb(color[0], color[1], color[2]) C.move_to(p1.x, p1.y) C.line_to(p2.x, p2.y) C.stroke self end end class LineError < StandardError end #2点p1, p2を通る直線を与える def points_make_line(p1, p2) Line.new(p1, p2 - p1) end #2直線l1, l2の交点を与える def linecross_point(l1, l2) dt = l2.nx * l1.ny - l1.nx * l2.ny return nil if dt.zero? px = ((l2.nx * l2.ly - l2.ny * l2.lx) * l1.nx + (l1.ny * l1.lx - l1.nx * l1.ly) * l2.nx) / dt py = ((l2.ny * l1.lx + l2.nx * l2.ly) * l1.ny - (l1.nx * l1.ly + l1.ny * l2.lx) * l2.ny) / dt Point.new(px, py) end #引数のすべてのオブジェクトを表示 def objects_draw(*args) args.each {|po| po.draw} end #main gray = [0.5, 0.5, 0.5] blue = [0, 0, 1] a1 = Point.new(-8, 3) c1 = Point.new( 8, 7) b1 = (a1 + c1) * 0.5 a2 = Point.new(-8, -6) c2 = Point.new( 9, -5) b2 = (a2 + c2) * 0.5 points_make_line(a1, c1).draw points_make_line(a2, c2).draw l1 = points_make_line(a1, b2).draw(color: gray) l2 = points_make_line(a1, c2).draw(color: gray) l3 = points_make_line(b1, c2).draw(color: gray) l4 = points_make_line(b1, a2).draw(color: gray) l5 = points_make_line(c1, a2).draw(color: gray) l6 = points_make_line(c1, b2).draw(color: gray) p = linecross_point(l1, l4) q = linecross_point(l2, l5) r = linecross_point(l3, l6) points_make_line(p, r).draw(color: blue) objects_draw(a1, b1, c1, a2, b2, c2, p, q, r) cairo_gtk(Surface, Width, Height)
パッポスの定理(その2)
上と異なっている部分のみ載せる。
b1 = Point.new(-6, 1) c1 = Point.new( 8, 3) a1 = b1 * 0.8 + c1 * 0.2 a2 = Point.new(-8, -6) c2 = Point.new( 9, -6) b2 = (a2 + c2) * 0.5