Author Topic: Aligning Python Script overlay with particle coordinates  (Read 150 times)

MS

  • Newbie
  • *
  • Posts: 5
Aligning Python Script overlay with particle coordinates
« on: April 06, 2018, 09:41:43 AM »
I am trying to plot a python script overlay of a single blue ring to represent a boundary on top of some particle data. Using the example I have the ring scaled correctly using this line: 

RingRadScaled = 0.5 * RingRad * painter.window().height() / args['fov']

I thought this line would centre the circle at (0,0)

rect = QRectF((0 + widthWindow/2)-(diameter/2) , (0 + heightWindow/2)-(diameter/2), diameter, diameter)

but it looks like there is some offset between ring and particles (see attached image).
The ring has a radius of 11.25 and I've plotted particles at (0,0),(+/- 11.25,0),(0,+/-11.25).

My Script looks like this:
from PyQt5.QtCore import *
from PyQt5.QtGui import *

RingRad = 11.25#mm

# Parameters:
circle_color = QColor(0,0,255)#Blue

# This function is called by OVITO on every viewport update.
def render(painter, **args):
    if args['is_perspective']:
       raise Exception("This only works with non-perspective viewports.")
   
   
    # Define geometry of circular boundary in screen space
    heightWindow = painter.window().height()
    widthWindow = painter.window().width()
    RingRadScaled = 0.5 * RingRad * painter.window().height() / args['fov']
    diameter = 2*RingRadScaled
   
   #Draw circle on top
    rect = QRectF((0 + widthWindow/2)-(diameter/2) , (0 + heightWindow/2)-(diameter/2), diameter, diameter)
    painter.setPen(QPen(circle_color));
    painter.drawEllipse(rect)


I could fudge the offset but I'm guessing this would change with resolution etc so wanted to understand how to centre it.

Alexander Stukowski

  • Administrator
  • Sr. Member
  • *****
  • Posts: 465
Re: Aligning Python Script overlay with particle coordinates
« Reply #1 on: April 06, 2018, 11:45:46 AM »
Hi,

You script accounts for the zoom factor of the viewport ("fov" value) and correctly computes the radius of the circle in screen space, but it currently does not take into account the position of the viewport camera. Since the viewport camera is in general not located at the origin, always drawing the circle at the center of the screen is wrong and leads to the apparent offset.

I suggest you make use of the project_point() and project_radius() helper functions that are given in the last script example on the doc page. The project_radius() function does what your own script is doing: it determines the correct radius in screen space given a radius in 3d space. The project_point() function allows you to determine the center of the circle in 2d screen space given a center point in 3d space.

Here is how the new code should look like:

Code: [Select]
    # Define geometry of circular boundary in screen space
    origin = (0,0,0)
    RingRadScaled = project_radius(origin, RingRad, painter, args)
    origin_screen = project_point(origin, painter, args)
    diameter = RingRadScaled*2
   
    #Draw circle on top
    rect = QRectF(origin_screen[0]-RingRadScaled, origin_screen[1]-RingRadScaled, diameter, diameter)
    ...