# View.draw examples using GL_LINES for multiple lines at a time

Barry, he never asked about materials or faces which are not supported for view drawing within a tool.

I know he didn’t. I was asking,as I said, “a related question”.
So now I finally know the answer.
Has it ever been suggested? It would seem to me to have great benefits.

I’m getting so close! i have all the lines working and drawing right. i must not understand the method Geom::Transformation.axes because no matter how many times i try to apply the transformation to each point. the drawing goes all over the place.

it seems to work ‘best’ at the model ORIGIN, (still not working right) but once my first input point is off the origin it draws the shape outline a good distance away from my cursor.

But without attempting to apply the transformation to each point it works pretty well. other than they all stay on the XZ plane.

is there anyone who can elaborate on the Transformation.axes method?

here is basically what i’m working with to get a 10 x 10 square. i can not seem to figure out how to apply the right transformation to each array of points to keep them on the plane perpendicular to the vector created by the 1st input point and the cursor location

``````def draw_geometry(pt1, pt2)
vec = pt2 - pt1
plane = [pt1, vec]

trans1 = Geom::Transformation.axes pt1, vec.axes[0], vec.axes[1], vec.axes[1] #set the transformation origin at the 1st input point location
trans2 = Geom::Transformation.axes pt2, vec2.axes[0], vec2.axes[1], vec.axes[1] #set the transformation origin at 2nd input location

ip1points = [ #points in reference to 1st input point
a1 = Geom::Point3d.new(pt1[0] + 5, pt1[1], pt1[2]),
a2 = Geom::Point3d.new(pt1[0] + 5, pt1[1], pt1[2] + 10),
a3 = Geom::Point3d.new(pt1[0] - 5, pt1[1], pt1[2] + 10),
a4 = Geom::Point3d.new(pt1[0] - 5, pt1[1], pt1[2])
]

ip2points = [ #points in reference to 2nd inputpoint
b1 =  Geom::Point3d.new(pt2[0] + 5, pt2[1], pt2[2]),
b2 =  Geom::Point3d.new(pt2[0] + 5, pt2[1], pt2[2] + 10),
b3 =  Geom::Point3d.new(pt2[0] - 5, pt2[1], pt2[2] + 10),
b4 =  Geom::Point3d.new(pt2[0] - 5, pt2[1], pt2[2])
]

ip1points.each {|p| p.transform! trans1} #apply the transformation to the 1st set of points
ip2points.each {|p| p.transform! trans2} #apply the transformation to the 2nd set of points

all_points = ip1points.zip(ip2points).flatten

all_points.push pt1, pt2, a1, a2, a2, a3, a3, a4, a4, a1, b1, b2, b2, b3, b3, b4, b4, b1 #add the input points and both ends outline points in the right sequence

view.line_width = 1
view.draw(GL_LINES, all_points)
end``````

Yes i want to draw on angular faces as well.and i’m getting there, i dont have a background much in mathematics so matrices and transformations have seemed to be one of the bigger hurdles for me to grasp. but i’m learning![quote=“maxB, post:19, topic:31599”]
apply the transformation on the vertices of each edge (from 1) and put the resulting points into a point array. I iterated through the edges and for each edge I iterated though its vertices and for each position of a vertex I applied the transformation (point 3) and put the result into the point array,
[/quote]

How are you applying the transformation to each vertex? i’m not asking how to iterate through them, but properly applying them. I must be misunderstanding the transformation to each. i suspect its with the 3 vectors that the method takes as arguments.

I see several problems in your test code. I made a small example myself. Its more easy if you have the complete code. Have a look at it and it should help you changing your code.

Note: I’m just a amateur coder. Proper educated coders might/will have some suggestions for adjustment.
Note2: Its just some rough code. Lots of checks need to be put into it to function well without any warnings (for instance: detect length of @vx when @ip1 and @ip2 are overlapping, etc)

Save the code to a ruby file and find it in your extensions named Ghost. It should look like in the pic.

``````####Ghost example
require 'sketchup.rb'

module MB
class MB::Ghost
def initialize
@vx = Geom::Vector3d.new 1,0,0
@vy = Geom::Vector3d.new 0,1,0
@vz = Geom::Vector3d.new 0,0,1
@picked_points = 0
@ip = Sketchup::InputPoint.new
@ip1 = Sketchup::InputPoint.new
@ip2 = Sketchup::InputPoint.new
@pts_arr = [[0,0,0],[10,0,0],[10,10,0],[0,10,0],[0,0,10],[10,0,10],[10,10,10],[0,10,10],[0,0,0],[0,10,0],[0,10,10],[0,0,10]]
end

def onMouseMove(flags, x, y, view)
case @picked_points
when 0
@ip.pick(view, x, y)
if @ip.valid? && @ip != @ip1
@ip1.copy!(@ip)
end
when 1
@ip.pick(view, x, y, @ip1)
if @ip.valid? && @ip != @ip2
@ip2.copy!(@ip)
end
when 2
@ip.pick(view, x, y, @ip2)
end
if @picked_points > 0
@vx = @ip1.position.vector_to @ip2.position
@vy = @vx.axes[0]
@vz = @vx.axes[1]
end
@trans = Geom::Transformation.axes @ip1.position, @vx, @vy, @vz
view.invalidate
end

def onLButtonDown(flags, x, y, view)
case @picked_points
when 0
@picked_points = 1
when 1
@picked_points = 2
end
view.invalidate
end

def draw(view)
pts =[]
@pts_arr.each{|p| pts << p.transform(@trans)}
view.drawing_color = "orange"
view.line_width = 2
view.draw(GL_LINES,pts)
end
end #class

end

end #module``````

Any progress on this one?

I made a quick translation of the line tool with the code of maxB. Just to see of you can make a followme from a simple box.

But when you use it you only see the orange lines at ip1.position and it rotates with the mouse. But how can you let a simple box follow the line from ip1 to ip2. Thats the part i can’t seem to figure out.

Test line.rb (5.9 KB)

Haven’t tested your code but my code above does exactly what you want. One corner is at ip1, the second is at ip2. One edge of the box is on that line.
Maybe you’re asking: ‘how can you attach a simple box to the mouse to have it follow you everywhere with a fixed orientation?’ My code already does that too when you just started it.

Maybe you can clarify?

Yes u tried your code and it greates the box. But then the box shape must follow the line untill the second point, like profile builder does. I think it’s the same thing bckwdsmn is looking for.

Still not clear. what would following the line from p1 to p2 do the box? You mean stretch the box?

If so; you have to dynamically adjust the points in the pts_array OR apply a transformation-scale as well to @trans.

I’m very short on time at the moment so can’t help you now adjusting the code. With these suggestions though, you hopefully know where to look further.

Oke clear,

Going to look for it but last question. How can you apply a transformation scale to @trans

When you do that i get the error: Error: #<ArgumentError: Cannot convert argument to Sketchup::Point3d

Thanks

You can multiply transformations. So if you have a scaling transformation @ts as well (see below) you could apply that in my code above by doing

`p.transform(@trans*@ts)`

Without proper context it’s very hard to find out why you have that error. For instance this works fine:

``````pt = [100,200,300]
@ts = Geom::Transformation.scaling 10
pt.transform!(@ts)``````

@vanlion

Had a short moment to spare. Here’s a code example where the shape scales after you picked the first point. Its just 3 (extra) lines:

1. declaring a variable @scale = Geom::Transformation.scaling 1

2. after picking the first point, updating the scale when moving the mouse: @scale = Geom::Transformation.scaling (@vx.length/10)
note: The /10 is the width of my cube.

3. Applying the scale as well: @pts_arr.each{|p| pts << p.transform(@trans*@scale)}

require ‘sketchup.rb’

module MB
class MB::Ghost
def initialize
@vx = Geom::Vector3d.new 1,0,0
@vy = Geom::Vector3d.new 0,1,0
@vz = Geom::Vector3d.new 0,0,1
@picked_points = 0
@ip = Sketchup::InputPoint.new
@ip1 = Sketchup::InputPoint.new
@ip2 = Sketchup::InputPoint.new
@pts_arr = [[0,0,0],[10,0,0],[10,10,0],[0,10,0],[0,0,10],[10,0,10],[10,10,10],[0,10,10],[0,0,0],[0,10,0],[0,10,10],[0,0,10]]
@scale = Geom::Transformation.scaling 1
end

`````` def onMouseMove(flags, x, y, view)
case @picked_points
when 0
@ip.pick(view, x, y)
if @ip.valid? && @ip != @ip1
@ip1.copy!(@ip)
end
when 1
@ip.pick(view, x, y, @ip1)
if @ip.valid? && @ip != @ip2
@ip2.copy!(@ip)
end
when 2
@ip.pick(view, x, y, @ip2)
end
if @picked_points > 0
@vx = @ip1.position.vector_to @ip2.position
@scale = Geom::Transformation.scaling (@vx.length/10)
@vy = @vx.axes[0]
@vz = @vx.axes[1]
end
@trans = Geom::Transformation.axes @ip1.position, @vx, @vy, @vz
view.invalidate
end

def onLButtonDown(flags, x, y, view)
case @picked_points
when 0
@picked_points = 1
when 1
@picked_points = 2
end
view.invalidate
end

def draw(view)
pts =[]
@pts_arr.each{|p| pts << p.transform(@trans*@scale)}
view.drawing_color = "orange"
view.line_width = 2
view.draw(GL_LINES,pts)
end
``````

end #class