#!ruby -Ku # -*- mode: ruby; coding: utf-8 -*- # Last updated: <2016/05/08 12:01:19 +0900> # # 線分の交点を求める処理のテスト # 線の始点終点をマウスドラッグして結果を確認できる # # 参考ページ # # 4点からなる交点の求め方 画像処理ソリューション # http://imagingsolution.blog107.fc2.com/blog-entry-137.html # # 線分交差判定 - Qiita # http://qiita.com/ykob/items/ab7f30c43a0ed52d16f2 # もっと簡単に−線分交差判定− # http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/Intersection.htm require 'dxruby' # 座標記録用クラス class Point attr_accessor :x, :y def initialize(x, y) @x = x @y = y end def on_mouse(x, y) d = 4 return (@x - d <= x and x <= @x + 3 and @y - d <= y and y <= @y + 3)? true :false end def draw(col) d = 4 Window.drawBoxFill(@x-d, @y-d, @x+d, @y+d, col) end # 2つの線分が交差するか調べる # @param p0 [Object] 線分Aの始点 # @param p1 [Object] 線分Aの終点 # @param p2 [Object] 線分Bの始点 # @param p3 [Object] 線分Bの終点 # @return [true, false] trueなら交差、falseなら交差してない def self.check_crossing(p0, p1, p2, p3) ta = (p2.x - p3.x) * (p0.y - p2.y) + (p2.y - p3.y) * (p2.x - p0.x) tb = (p2.x - p3.x) * (p1.y - p2.y) + (p2.y - p3.y) * (p2.x - p1.x) if ta * tb < 0 tc = (p0.x - p1.x) * (p2.y - p0.y) + (p0.y - p1.y) * (p0.x - p2.x) td = (p0.x - p1.x) * (p3.y - p0.y) + (p0.y - p1.y) * (p0.x - p3.x) return true if tc * td < 0 end return false end # 2つの線分の交点を取得 # @param p0 [Object] 線分Aの始点 # @param p1 [Object] 線分Aの終点 # @param p2 [Object] 線分Bの始点 # @param p3 [Object] 線分Bの終点 # @return [Object] 交点を Pointクラスで返す #def self.get_crossing_pos(p1, p3, p2, p4) def self.get_crossing_pos(p0, p1, p2, p3) s1 = ((p3.x - p2.x) * (p0.y - p2.y) - (p3.y - p2.y) * (p0.x - p2.x)) / 2.0 s2 = ((p3.x - p2.x) * (p2.y - p1.y) - (p3.y - p2.y) * (p2.x - p1.x)) / 2.0 cx = p0.x + (p1.x - p0.x) * s1 / (s1 + s2) cy = p0.y + (p1.y - p0.y) * s1 / (s1 + s2) return Point.new(cx, cy) end end fnt = Font.new(16) p = [] 4.times do p.push(Point.new(rand(640), rand(480))) end drag_idx = -1 Window.loop do break if Input.keyPush?(K_ESCAPE) # 制御点のドラッグ処理 mx = Input.mousePosX my = Input.mousePosY if drag_idx < 0 # 制御点をドラッグしてない if Input.mousePush?(M_LBUTTON) p.length.times do |i| next unless p[i].on_mouse(mx, my) drag_idx = i break end end else # 制御点をドラッグ中 p[drag_idx].x = mx p[drag_idx].y = my drag_idx = -1 unless Input.mouseDown?(M_LBUTTON) end # 制御点を描画 p.each do |v| v.draw((v.on_mouse(mx, my))? C_RED : C_CYAN) end # 交差してたら描画色を変更 col = C_GREEN hitfg = false if Point.check_crossing(p[0], p[1], p[2], p[3]) col = C_MAGENTA hitfg = true end # 線分を描画 Window.drawLine(p[0].x, p[0].y, p[1].x, p[1].y, col) Window.drawLine(p[2].x, p[2].y, p[3].x, p[3].y, col) # 交点を描画 if hitfg c = Point.get_crossing_pos(p[0], p[1], p[2], p[3]) d = 4 Window.drawBoxFill(c.x - d, c.y - d, c.x + d, c.y + d, C_WHITE) end Window.drawFont(4, 4, "Please drag", fnt) end