Array (Bài trước)

Biểu diễn điểm trong không gian dùng lớp Geom::Point3d, vector thì dùng lớp Geom::Vector3d, cũng có thể biểu diễn chúng đơn giản bằng cách dùng mảng Array ở bài trước.

Lớp Geom::Point3d

Lớp Geom::Point3d biểu diễn điểm trong không gian với ba tọa độ x,y,z. Khởi tạo một đối tượng này có mấy cách như:

# Khởi tạo không tham số, điểm có tọa độ [0,0,0]
pt1 = Geom::Point3d.new

# Tạo điểm có tọa độ x = 100, y = 200, z = 300
pt2 = Geom::Point3d.new(100,200,300)

# Cũng có thể tạo điểm bằng cách sử dụng mảng
pt3 = [100,200,300]
linear_combination linear_combination(weight1, point1, weight2, point2)
Tạo một điểm mới bằng cách nội suy giữa hai điểm, điểm nội suy nằm trên đường giữa hai điểm point1 và point2 với trọng số giữa hai điểm tương ứng. Giống như tìm trọng tâm với hai điểm có khối lượng, công thức để nội suy là:
point = weight1 * point1 + weight2 * point2
point1 = Geom::Point3d.new(10,10,0)
point2 = [20,20,0]
point = Geom::Point3d.linear_combination(0.2, point1, 0.8, point2) # Point3d(18, 18, 0)
+
-
Cộng/trừ tọa độ cho một vector
point1 = Geom::Point3d.new(1, 2, 3)
vector = Geom::Vector3d.new(4, 5, 6)
point2 = point1 + vector # Point3d(5, 7, 9)
< Kiểm tra xem điểm nào gần gốc tọa độ hơn
pt1 = Geom::Point3d.new(0,0,10)
pt2 = Geom::Point3d.new(0,0,20)
result = pt1 < pt2 # true - pt1 gần gốc tọa độ hơn
== Kiểm tra xem hai điểm có tọa độ trùng nhau không
[] Toán tử lấy tọa độ điểm theo chỉ số, 0 là x [0], 1 là y [1]
.clone Khởi tạo điểm mới giống tọa độ điểm ban đầu
distance Xác định khoảng cách hai điểm, giống ở phần mảng Array
distance_to_line Khoảng cách điểm đến đường, xem phần mảng Array
distance_to_plane Khoảng cách điểm đến mặt, xem phần mảng Array
inspect Lấy chuỗi thông tin đối tượng
offset offset(vector, length = vector.length)
dịch chuyển điểm một đoạn theo hướng một vector
point1 = Geom::Point3d.new(10,10,10)
vector = Geom::Vector3d.new(0, 0, 1)
point2 = point1.offset(vector) # Point3d(10, 10, 11)
offset! Giống offset, nhưng biến đối chính đối tượng ban đầu
on_line?(line) Kiểm tra điểm có thuộc một đường, xem phần Array
on_plane?(plane) Kiểm tra điểm thuộc mặt, xem phần Array
project_to_line(line) Chiếu điểm xuống đường, xem Array
project_to_plane(plane) Chiếu điểm xuống mặt, xem Array
set! Thiết lập giá trị các thành phần tọa độ
to_a Chuyển Point3d về mảng Array
to_s Lấy chuỗi biểu diễn điểm
transform(transform) Biến đổi điểm theo một Transform
tr = Geom::Transformation.translation([1,1,1]) # dịch chuyển một đoạn bằng vector [1,1,1]
point1 = Geom::Point3d.new(1,1,1)
point2 = point1.transform(tr)
transform!(transform) Giống transform(transform) nhưng biến đổi đối tượng gốc
vector_to Tạo vector tới điểm thứ 2
x, y, z Lấy các thành phần tọa độ
x=, y=, z= Gán các thành phần tọa độ

Lớp Geom::Vector3d

Lớp Geom::Vector3d biểu diễn vector trong không gian, có các phương thức tham khảo ở phần Array và Point3d, trong đó lưu ý:

% Tích vô hướng hai vector
cross Tích có hướng hai vector
+, - Cộng, trừ hai vector
< Kiểm tra các thành phần x,y hoặc z nhỏ hơn vector so sánh
== Kiểm tra hai vector bằng nhau không
[]
[]=
Đọc / gán thành phần tọa độ của vector
angle_between Tính góc giữa hai vector (Radian)
vector1 = Geom::Vector3d.new(1,1,0)
vector2 = Geom::Vector3d.new(0,1,0)
angle = vector1.angle_between vector2
angle.radians
axes Lấy mảng chứa 3 vector biểu diễn ba trục tọa độ, trong đó trục z trùng với vector đã cho
clone Sinh vector mới từ vector ban đầu
cross giống * Tích hai vector
dot Tích vô hướng
length
lengthu=
Đọc, gán Chiều dài vector
normalize Đưa về chiều dài đơn vị
normalize! Giống normalize nhưng biến đổi đối tượng gốc
parallel? Kiểm tra hai vector song song (cùng phương)
perpendicular?(vector2) Kiểm tra hai vector vuông góc nhau
reverse Tạo vector ngược chiều
reverse! Biến đổi thành vector ngược chiều
samedirection? Kiểm tra hai vector cùng phương, cùng hướng
unitvector? Kiểm tra có phải vector đơn vị
valid? Kiểm tra vector hợp lệ (dài khác 0)

Phương thức trong Module Geom

Các phương thức trong module Geom có tham số là các đường và các mặt, nhưng không có một lớp cụ thể nào biểu diễn đường và mặt. Một đường có thể biểu diễn bằng một mảng gồm một điểm và một vector, hoặc một mảng hai điểm. Ví dụ như:

line1 = [Geom::Point3d.new(0, 0, 0), Geom::Vector3d.new(0, 0, 1)]
line2 = [Geom::Point3d.new(0, 0, 0), Geom::Point3d.new(0, 0, 100)]

Một mặt có thể biểu diễn bởi một mảng gồm 1 điểm và một vector (là pháp tuyến).

plane1 = [Geom::Point3d.new(0, 0, 0), Geom::Vector3d.new(0, 0, 1)]

Mặt còn biểu diễn bởi mảng là các tham số của phương trình đại số biểu diễn mặt Ax + By + Cz + D = 0

plane2 = [0, 0, 1, 0] # A= 0, B = 0, C = 1, D = 0

Các phương thức lớp

closest_points .closest_points(line1, line2) ⇒ Array(Geom::Point3d, Geom::Point3d)
Điềm điểm gần nhất trên hai đường, điểm thứ nhất nằm trên đường 1 và điểm thứ 2 nằm trên đường 2
fit_plane_to_points Tính toán trả về mặt biểu diễn bởi mảng gồm điểm và vector pháp tuyến Array(Geom::Point3d, Geom::Vector3d)

Tìm mặt bởi các điểm, nếu trả về mảng 4 phần tử thì nó là tham số của phương trình mặt phẳng

intersect_line_line Giao của hai đường intersect_line_line(line1, line2) ⇒ Geom::Point3d?
intersect_line_plane Giao giữa đường và mặt intersect_line_plane(line, plane) ⇒ Geom::Point3d?
intersect_plane_plane Tìm giao của hai mặt intersect_plane_plane(plane1, plane2) ⇒ Array(Geom::Point3d, Geom::Vector3d)
linear_combination Nội suy điểm hoặc vector
point_in_polygon_2D Kiểm tra điểm thuộc đa giác polygon, các điểm có z = 0 point_in_polygon_2D(point, polygon, check_border)
point = Geom::Point3d.new(5, 0, 10)
triangle = []
triangle << Geom::Point3d.new(0, 0, 0)
triangle << Geom::Point3d.new(10, 0, 0)
triangle << Geom::Point3d.new(0, 10, 0)

hits_on_border_count = true
status = Geom.point_in_polygon_2D(point, triangle, hits_on_border_count)

Ví dụ sau vẽ đường tròn qua ba điểm

# 30.circle3point.rb
# load "/Users/xuanthulab/Desktop/learn-ruby/sketchup/30.circle3point.rb"
require 'sketchup.rb'
require 'extensions.rb'


class Circle3Point

  # Phương thức vẽ đường tròn từ ba điểm (khác nhau, không thẳng hàng)
  # @param [Geom::Point3d] a
  # @param [Geom::Point3d] b
  # @param [Geom::Point3d] c
  def circle_3point(a, b, c)
    ents = Sketchup.active_model.entities

    lineab = [a,b]
    linebc = [b,c]

    projecta_bc = a.project_to_line linebc
    projectc_ab = c.project_to_line lineab
    normal_bc = (projecta_bc.vector_to a).normalize
    normal_ab = (projectc_ab.vector_to c).normalize

    mab = Geom::Point3d.linear_combination 0.5, a, 0.5, b
    mbc = Geom::Point3d.linear_combination 0.5, b, 0.5, c
    ab_center = [mab, normal_ab]
    bc_center = [mbc, normal_bc]
    center = Geom.intersect_line_line ab_center, bc_center
    radius = center.distance a
    normal = (a.vector_to b) * (b.vector_to c).normalize
    ents.add_circle center, normal, radius, 900
  end

  # Gọi khi kích hoạt công cụ
  def activate
    puts 'Kích hoạt Tool'
    # InputPoint để nhấn chuột chọn các Entity
    @input  = Sketchup::InputPoint.new
    @point1 = nil
    @point2 = nil
    @point3 = nil
    @pointmove = nil
    # Hiện thông báo VCB
    Sketchup.set_status_text "Nhập điểm 1", SB_VCB_LABEL
  end
  # Gọi khi hủy chọn công cụ
  def deactivate(view)
    puts "Bất hoạt tool: #{view}"
  end

  def onCancel(reason, view)
    puts "Hủy chọn tool ##{reason} trong view: #{view}"
  end

  # @param [Sketchup::View] view
  def draw(view)
    options = {
      :font => "Arial",
      :size => 20,
      :bold => true,
      :align => TextAlignRight
    }
    point = Geom::Point3d.new(200, 200, 0)
    view.draw_text(point, "Vẽ hình tròn có 3 điểm", options)

    view.drawing_color = Sketchup::Color.new(255, 0, 0, 64)
    if !@pointmove.nil?
        # Vẽ điểm tại chuột
        status = view.draw_points @pointmove, 10, 2, "red"
    end
    view.draw_points(@point1,10,2, "red") if !@point1.nil?
    view.draw_points(@point2,10,2, "red") if !@point2.nil?
    view.draw_points(@point3,10,2, "red") if !@point3.nil?
  end

  # Bắt sự kiện di chuyển chuột
    def onMouseMove(flags, x, y, view)
        # Hiện thị tọa độ trong VCB
        @input.pick view, x, y
        @pointmove = @input.position
        # Hiện thị tooltip điểm
        view.tooltip = @input.tooltip
        view.invalidate
    end

    # Bắt sự kiện nhấn chuột trái
    def onLButtonDown flags, x, y, view
        @input.pick view, x, y

        if @point1.nil?
          @point1 = @input.position
          Sketchup.set_status_text "Nhập điểm 2", SB_VCB_LABEL
        elsif @point2.nil?
          tempoint = @input.position
          if !(tempoint == @point1)
            @point2 = tempoint
            Sketchup.set_status_text "Nhập điểm 3", SB_VCB_LABEL
          else
            puts "Hai điểm trùng nhau"
          end
        elsif @point3.nil?
          tempoint = @input.position
          if !((tempoint == @point1) || (tempoint == @point2))
            @point3 = tempoint if !tempoint.on_line? [@point1, @point2]
            if (@point3.nil?)
              UI.messagebox("Ba điểm không được thẳng hàng")
            else
              circle_3point(@point1, @point2, @point3)
              Sketchup.active_model.select_tool nil
            end
          else
            puts "Hai điểm trùng nhau"
          end
        end
    end

end

if( not file_loaded? "30.circle3point.rb" )
    # Tạo menu chọn công cụ
    simple_cmd = UI::Command.new("Circle 3 Point") {
        # Chọn công cụ
        Sketchup.active_model.select_tool Circle3Point.new
    }
    tool_menu = UI.menu "Tools"
    tool_menu.add_separator
    tool_menu.add_item simple_cmd
    file_loaded "30.circle3point.rb"
end

Đăng ký nhận bài viết mới
Array (Bài trước)