Hi everyone!
i try to devep plugin and have some problem with it.
The plug-in implements the following functional:
- fixing the position of points and normal vectors on model surfaces;
- set sphere(circuit);
- calculation of the point of intersection of the vector of the normal and the sphere;
- visualization of the trajectory from the point on the sphere to the point on the surface of the model;
The problem in the calculated value of the intersection point:
radius and center point refers to sphereā parameters.
sphere pos (same as point2) - intesection point.
Z value of point bigger then sphere (at picture). I think this may depend on the units of measurement but I donāt know how to check it.
point_tool.rb
require 'sketchup.rb'
module Examples
module CustomTool
class PointTool
def activate
puts('Activate vector')
@mouse_ip = Sketchup::InputPoint.new
update_ui
end
def deactivate(view)
puts('Deactivate vector')
view.invalidate
end
def resume(view)
update_ui
view.invalidate
end
def onCancel(_reason, view)
puts('Canceled vector')
view.invalidate
end
# If you are on a face, then the degrees_of_freedom will be 2 meaning that you can only move on the plane of the
# face.
# If you are on an Edge or an axis, then the degrees_of_freedom will be 1 meaning that you can only move in the
# direction of the edge or axis.
# If you get an end point of an Edge, or an intersection point, then the degrees_of_freedom will be 0.
def onMouseMove(_flags, x, y, view)
@mouse_ip.pick(view, x, y, @mouse_ip)
dof = @mouse_ip.degrees_of_freedom
view.tooltip = @mouse_ip.tooltip if @mouse_ip.valid? && dof < 3
view.invalidate
end
def onLButtonDown(_flags, _x, _y, view)
puts('OnLButtonDown vector')
dof = @mouse_ip.degrees_of_freedom
get_vector_normal if @mouse_ip.valid? && dof < 3
update_ui
view.invalidate
end
# Here we have hard coded a special ID for the pencil cursor in SketchUp.
# Normally you would use `UI.create_cursor(cursor_path, 0, 0)` instead
# with your own custom cursor bitmap:
#
# CURSOR_PENCIL = UI.create_cursor(cursor_path, 0, 0)
CURSOR_POINT = 632
def onSetCursor
UI.set_cursor(CURSOR_POINT)
end
def draw(view)
draw_preview(view)
@mouse_ip.draw(view) if @mouse_ip.display?
end
private
def update_ui
Sketchup.status_text = 'Select point on plane.'
end
def draw_preview(view)
view.draw(GL_POINTS, @mouse_ip)
end
def calc_intersection_point(pos, normal)
r = SafeSphere.radius
return nil if r == 0
xc, yc, zc = SafeSphere.center_point.to_a
a, b, g = normal.to_a
x, y, z = pos
puts "===========calculation============"
puts "radius = #{r}"
puts "center point = #{xc} #{yc} #{zc}"
puts "line vector = #{normal.to_a}"
puts "point = #{pos}"
puts "=================================="
root = root(a,b,g,xc,yc,zc,x,y,z,r)
coef = coefficient(a, b, g)
t = coef*(-a*x + a*xc - b*y + b*yc + g*z + 0.5 * root - g*zc)
puts "t = #{t}"
if t < 0
t = coef*(-a*x + a*xc - b*y + b*yc + g*z - 0.5 * root - g*zc)
puts "t = #{t}"
end
xs = x + a*t
ys = y + b*t
zs = z + g*t
puts "xs = #{xs} ys = #{ys} zs = #{zs}"
Geom::Point3d.new(xs, ys, zs)
end
def root(a,b,g,xc,yc,zc,x,y,z,r)
(4*(a*(x - xc) + b*(y - yc) + g*((z - zc))**2) -
4*((a*2) + (b**2)+ (g**2))*(-(r**2) + ((x - xc)**2) + ((y - yc)**2) + ((z - zc)**2)))**0.5
end
def coefficient(a, b, g)
(1/((a**2) + (b**2) + (g**2)))
end
def visualize(point1, point2)
puts 'visualize'
puts "=====visualize_begin====="
puts "point1 = #{point1}"
puts "point2 = #{point2}"
puts "========================="
model = Sketchup.active_model
model.start_operation('Edge', true)
edge = model.active_entities.add_line(point1, point2)
model.commit_operation
puts "=====visualize_end====="
puts "point1 = #{point1}"
puts "point2 = #{point2}"
puts "======================="
end
def get_vector_normal
puts('Get vector normal')
face = @mouse_ip.face
normal = face.normal
# vector3d.axes
# The axes method is used to compute an arbitrary set of axes with the given vector as the z-axis direction.
# Returns an Array of three vectors [xaxis, yaxis, zaxis].
#
# The position method is used to get the 3D point from the input point.
# The values are specified as [x,y,z].
axes = normal.axes
pos = @mouse_ip.position
puts "pose on surface = #{pos.to_a}"
sphere_pos = calc_intersection_point(pos.to_a, normal)
return 0 if sphere_pos.nil?
puts "sphere pos = #{sphere_pos.to_a}"
visualize(pos, sphere_pos)
puts("#{pos[0]},#{pos[1]},#{pos[2]},#{normal[0]},#{normal[1]},#{normal[2]}")
puts("#{sphere_pos[0]},#{sphere_pos[1]},#{sphere_pos[2]},#{normal[0]},#{normal[1]},#{normal[2]}")
file = File.open(ENV['HOME'] + '/Desktop/points.txt', 'a')
file.puts("Vector\n#{pos[0]},#{pos[1]},#{pos[2]},#{normal[0]},#{normal[1]},#{normal[2]}")
file.puts("#{sphere_pos[0].to_mm}, #{sphere_pos[1].to_mm}, #{sphere_pos[2].to_mm}, #{normal[0].to_mm}, #{normal[1].to_mm},#{normal[2].to_mm}")
file.close
end
def draw_safe_circle
puts('draw_safe_circle')
end
end # class PointTool
end
end
safe_sphere.rb
require 'sketchup.rb'
module Examples
module CustomTool
class SafeSphere
@@radius = 0
def self.radius
@@radius
end
def self.center_point
@@center_point
end
def activate
@mouse_ip = Sketchup::InputPoint.new
@picked_first_ip = Sketchup::InputPoint.new
update_ui
end
def deactivate(view)
view.invalidate
end
def resume(view)
update_ui
view.invalidate
end
def onCancel(_reason, view)
reset_tool
view.invalidate
end
def onMouseMove(_flags, x, y, view)
if picked_first_point?
puts 'picked_first_point? valid'
@mouse_ip.pick(view, x, y, @picked_first_ip)
puts @mouse_ip
else
@mouse_ip.pick(view, x, y)
end
view.tooltip = @mouse_ip.tooltip if @mouse_ip.valid?
view.invalidate
end
def onLButtonDown(_flags, _x, _y, view)
puts 'onLButtonDown'
num_new_faces = 0
if picked_first_point?
puts("num_new_faces = create_edge")
num_new_faces = create_edge
end
if num_new_faces > 0
puts("reset_tool")
else
puts("@picked_first_ip.copy!(@mouse_ip)")
@picked_first_ip.copy!(@mouse_ip)
end
update_ui
view.invalidate
end
# Here we have hard coded a special ID for the pencil cursor in SketchUp.
# Normally you would use `UI.create_cursor(cursor_path, 0, 0)` instead
# with your own custom cursor bitmap:
#
# CURSOR_PENCIL = UI.create_cursor(cursor_path, 0, 0)
CURSOR_PENCIL = 632
def onSetCursor
# Note that `onSetCursor` is called frequently so you should not do much
# work here. At most you switch between different cursors representing
# the state of the tool.
UI.set_cursor(CURSOR_PENCIL)
end
# The `draw` method is called every time SketchUp updates the viewport.
# You should take care to do as little work in this method as possible.
# If you need to calculate things to draw it is best to cache the data in
# order to get better frame rates.
def draw(view)
draw_preview(view)
@mouse_ip.draw(view) if @mouse_ip.display?
end
# When you use `view.draw` and draw things outside the boundingbox of
# the existing model geometry you will see that things get clipped.
# In order to make sure everything you draw is visible you must return
# a boundingbox here which defines the 3d model space you draw to.
# def getExtents
# bb = Geom::BoundingBox.new
# bb.add(picked_points)
# bb
# end
# In this example we put all the logic in the tool class itself. For more
# complex tools you probably want to move that logic into its own class
# in order to reduce complexity. If you are familiar with the MVC pattern
# then consider a tool class a controller - you want to keep it short and
# simple.
private
def update_ui
Sketchup.status_text = if picked_first_point?
'Select radius.'
else
'Select Ńenter point.'
end
end
def reset_tool
@picked_first_ip.clear
update_ui
end
def picked_first_point?
@picked_first_ip.valid?
end
def picked_points
points = []
points << @picked_first_ip.position if picked_first_point?
points << @mouse_ip.position if @mouse_ip.valid?
points
end
def draw_preview(view)
points = picked_points
return unless points.size == 2
view.set_color_from_line(*points)
view.line_width = 1
view.line_stipple = ''
view.draw(GL_LINE_LOOP, points)
end
# start_operation(op_name, disable_ui = false, next_transparent = false, transparent = false) ā Boolean
def create_edge
model = Sketchup.active_model
model.start_operation('Edge', true)
@@center_point = picked_points[0]
normal = @@center_point.vector_to(picked_points[1])
normal.length = 1
@@radius = @@center_point.vector_to(picked_points[1]).length
puts("Center: #{@@center_point}\nRadius: #{@@radius}")
edge = model.active_entities.add_circle(@@center_point, normal, @@radius, 100)
file = File.open(ENV['HOME'] + '/Desktop/points.txt', 'w')
file.puts("Sphere\n#{@@center_point[0].to_mm},#{@@center_point[1].to_mm},#{@@center_point[2].to_mm}\n#{@@radius.to_mm}\n")
file.close
model.commit_operation
1
end
end # class SafeSphere
end
end