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 |
lengthlengthu= |
Đọ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
