I create images with write_image that is exported (automatically by our extension) to another system.
I want to imprint the images with a text in the bottom of the image.
I had a solution using add_note, however I was using scale_factor to get it to the size I wanted it, and discovered that scale_factor affects other things, like how edges are drawn, so that didn’t work out.
I have now made a solution using add_3d_text, and place it the text in a position close to the camera so it renders in the bottom of the view.
I’m using pickray to find the place in the model for its, and transform_by_vectors to “stretch” the text in order to compensate for the perspective (so the text appear as it was rendered in 2d onto the image).
model = Sketchup.active_model
view = model.active_view
textDistanceFromCamera = 5
textHeightAsPartOfView = 0.05
bottomLeft = view.pickray(0,view.vpheight)
bottomLeft = bottomLeft[0].offset(bottomLeft[1],textDistanceFromCamera)
topLeft = view.pickray(0,(1-textHeightAsPartOfView)*view.vpheight)
topLeft = topLeft[0].offset(topLeft[1],textDistanceFromCamera)
topRight = view.pickray(view.vpwidth,(1-textHeightAsPartOfView)*view.vpheight)
topRight = topRight[0].offset(topRight[1],textDistanceFromCamera)
bottomRight = view.pickray(view.vpwidth,view.vpheight)
bottomRight = bottomRight[0].offset(bottomRight[1],textDistanceFromCamera)
bottomTextWidth = bottomLeft.distance(bottomRight)
topTextWidth = topLeft.distance(topRight)
textHeight = bottomLeft.distance_to_line([topLeft, topRight])
textgroup = model.entities.add_group
textgroup.entities.add_3d_text(
"Hello world ÅHg",
TextAlignLeft,
"arial",
false, #is_bold
false, #is_italic
textHeight*0.65, #letter_height
0.0, #tolerance
0.0, #z
true, #is_filled
0.0 #extrusion
)
vertices = textgroup.entities.select{|e|e.is_a?(Sketchup::Edge)}.map(&:explode_curve).flat_map{|edge|[edge.start, edge.end]}.uniq
vectors = vertices.map{|vertex| [vertex.position.y/textHeight * (vertex.position.x-bottomTextWidth/2)/bottomTextWidth * (topTextWidth-bottomTextWidth), 0, 0]}
textgroup.entities.transform_by_vectors(vertices,vectors)
textgroup.transform!(Geom::Transformation.new(bottomLeft,(bottomRight-bottomLeft),(topLeft-bottomLeft)))
This seems to work for my application, but it’s kind of a “workaround solution”.
So what is my question ?
In general, is there some obvious better/less complicated way of doing this ?
Also, I’m assuming pickray returns a ray originating from the camera eye (/“camera plane” for parallell projection), is this a reasonable assumption?