Distance in pixel?

Is possible calculate the distance between 2 vertex in pixel? Like I see on the screen:
https://lh4.googleusercontent.com/-Pesb06h5E18/TeutU4fNV0I/AAAAAAAAAy8/O9m8vimBTSs/s144/Distance2D.png

The first thing that comes to mind is some kind of ray casting approach.
You also have the bounding box information of the object which gives you a rough idea in Blender units how large the area is.

You will have to determine what your screen size is. Then some kind of formula of distance times basic unit size divided by output width and or height?

Until you lock down the frame size, the result will vary. The same pixel distance will be different on the exact same scene depending upon how large the final render is. Correct?

I need it not in render image but in 3D view.
I thought to use matrix math. Something like .matrix_world or .perspective_matrix or .view_matrix, or some OpenGL function.
But I don’t know much about they.

Thanks

Yes, there are Python possibilities to find out (x,y) screen coordinates (I was busy with something like that 3 weeks ago and then my HD became unstable … two weeks no Blender ;-( …) I will have a look to back into what I saved (and remember!), if found I let you know …

It is too around \2.57\scripts\startup\bl_ui space_view3d.py (I think …) ( = where blender.exe lives on Vista)

Oh I think I have it …


....
def location_3d_to_region_2d(region, rv3d, coord):
    """
    Return the *region* relative 2d location of a 3d position.

    :arg region: region of the 3D viewport, typically bpy.context.region.
    :type region: :class:`Region`
    :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: :class:`RegionView3D`
    :arg coord: 3d worldspace location.
    :type coord: 3d vector
    :return: 2d location
    :rtype: :class:`Vector`
    """
    prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix
    print("projectionvector of coord 
",coord,"
is
",prj)
    if prj.w > 0.0:
        width_half = region.width / 2.0
        height_half = region.height / 2.0

        return Vector((width_half + width_half * (prj.x / prj.w),
                       height_half + height_half * (prj.y / prj.w),
                       ))
    else:
        return None

...

Thanks PKHG but I have some problem with arg. rv3d
How I must set it?

In a Class it it is like this


    def execute(self, context):
        v3d = context.space_data
        rv3d = v3d.region_3d

Better late than never :slight_smile:
Working example.
The 3D coordinate is hard coded, but is only a proof of concept

Thanks to PKHG

Ciao
Valter


import bpy
from bpy.props import IntProperty, FloatProperty
from mathutils import Vector
 
def location_3d_to_region_2d(region, rv3d, coord):
    """
    Return the *region* relative 2d location of a 3d position.
    :arg region: region of the 3D viewport, typically bpy.context.region.
    :type region: :class:`Region`
    :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: :class:`RegionView3D`
    :arg coord: 3d worldspace location.
    :type coord: 3d vector
    :return: 2d location
    :rtype: :class:`Vector`
    """
    prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix
    print("projectionvector of coord 
",coord,"
is
",prj)
    if prj.w > 0.0:
        width_half = region.width / 2.0
        height_half = region.height / 2.0
        return Vector((width_half + width_half * (prj.x / prj.w),
                       height_half + height_half * (prj.y / prj.w),
                       ))
    else:
        return None
 
class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"
    rv3d=None
    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':
            #Print 2D location of the point 0.0.0
            print(location_3d_to_region_2d(bpy.context.region, self.rv3d, Vector((0,0,0)) ))
        elif event.type == 'LEFTMOUSE':
            return {'FINISHED'}
        elif event.type in ('RIGHTMOUSE', 'ESC'):
            return {'CANCELLED'}
        return {'RUNNING_MODAL'}
    def invoke(self, context, event):
        if context.object:
            context.window_manager.modal_handler_add(self)
            v3d = context.space_data
            self.rv3d = v3d.region_3d
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "No active object, could not finish")
            return {'CANCELLED'}
 
def register():
    bpy.utils.register_class(ModalOperator)
 
def unregister():
    bpy.utils.unregister_class(ModalOperator)
 
if __name__ == "__main__":
    register()

Hi Valter,
Yes, this is like it works … maybe the Vector(0,0,0) should/could be replaced by e.g. selected points of the active mesh-object (one, or all, if all in a loop)??

By the way, the thanks has to go to ideasman_42, who showed me the important knoff hoff!