view#screen_coords and Z coordinate
view#screen_coords returns the 2D coordinate of a 3D point.
However, the Z coordinate is not set to zero. Instead it has a value (usually 2.54, or 0.713 inches, but not even constant).
Is there a reason for that?
Actually, the issue is that you often use calculations with 3D methods, mixing points coming from view.screen_coords and points which are calculated by other means and have their Z value set to 0. This it is the source of problems when you forget to set the Z value to 0, when coming from a view.screen_coords.
On my side, I have a method which does that, but it's a little bit a pity.... (and I often forget and use the native method)
IMO, ... the View#screen_coords method should never have returned a Geom::Point3d object.
It should have returned a two element Array of Integer. Mainly because the data is 2D with an origin at the top left, whereas SketchUp 3D coordinates are based upon an origin at lower left in Length values.
This all predated the LayOut API, which implemented a Geom::Point2d class which is more like screen coordinates having the origin at top left, but again coordinates in Length values.
Last month (or so) I myself thought about this and began boiler plating up class ideas for UI::ScreenCoords, UI::ScreenBounds, UI::TextBounds classes. These can't be written as refinements as modules cannot be refined. Also wondering if a UI::Pixel subclass of Integer might be beneficial? (ie, with conversion between physical and logical pixels values.)
It is meant to be a brainstorming exercise. I had not yet finished the file, but here it is if you're interested ...
Actually, it is very convenient that view.screen_coords returns a Geom::Point3d object, because we can use the usual methods on it (transform, offset, etc...). Every thing is fine, since the Z coordinates is constant (and ideally 0).
In my experience of Layout API, it is painful to have Geom::Point2d, BoundingBox2d, etc..., because many API methods are missing and this is another structure to deal with.
Actually, it is very convenient that
view.screen_coordsreturns aGeom::Point3dobject, because we can use the usual methods on it (transform, offset, etc...).
The API adds these methods to the Array class.
Your comment made me think that UI::ScreenCoords could be implemented as a subclass of Array.
I think there is a more general issue of updating the API to consistently and logically use Geom::Point3d and Geom::Point2d classes.
I came across this whilst writing an Overlay to display labels on the screen plane with a white background:
- To get the screen position of the label, I call
view#screen_coords()which then returns aGeom::Point3d - To draw the label text I then use
view#draw_text() - In order to put a background behind the text, I call
view#text_bounds(), which returns a Geom::Bounds2d object, consisting of 2 Geom::Point2d - To draw the background face, I must then break apart the
Geom::Point2ddata and create newGeom::Point3dasview#draw2d()expectsGeom::Point3d
I know it is a legacy of the how the different classes were added over time, but it is quite bizarre when you look at it in retrospect.
However, the Z coordinate is not set to zero. Instead it has a value (usually 2.54, or 0.713 inches, but not even constant).
Is there a reason for that?
I had a quick look into the source code:
// In Viewport coordinates, Z=0 on the near clip plane and
// Z=1 on the far clip plane.
And internally we have a function that can map that coordinate back into model space.
So it's not random, nor uninitialized. Not sure we want to change that now. Someone might have figured out this related to the depth and made use of it. But at the very least it should be better documented as the non-zero Z component can catch you off guard if you are doing other operations on them.
I think there is a more general issue of updating the API to consistently and logically use Geom::Point3d and Geom::Point2d classes.
Can you start a new issue to discuss this please?