Fix axes graphical bug in clusterviewer.

X, Y, Z axes were not in the right-hand orientation and the
Z-stack for drawing axes was not updated resulting in strange
graphical output (axis could "jump" over another instead of being
drawn behind)
This commit is contained in:
Sylvain Tricot 2020-07-22 14:09:51 +02:00
parent 54fc166eb4
commit 3a20719d19
1 changed files with 28 additions and 26 deletions

View File

@ -26,7 +26,7 @@ class ClusterViewer(wx.Window):
MODE_SELECTION_TOGGLE = 0b0001000 MODE_SELECTION_TOGGLE = 0b0001000
MODE_TRANSLATION = 0b0010000 MODE_TRANSLATION = 0b0010000
MODE_ROTATION = 0b0100000 MODE_ROTATION = 0b0100000
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN
wx.Window.__init__(self, *args, **kwargs) wx.Window.__init__(self, *args, **kwargs)
@ -108,7 +108,7 @@ class ClusterViewer(wx.Window):
This will translate the model to the center of mass, move the model center This will translate the model to the center of mass, move the model center
to the center of screen and adjust the scale to the largest dimension of the to the center of screen and adjust the scale to the largest dimension of the
model model
:param rescale: if True, the zoom is computed to view the atoms; if False, a fixed zoom value is used :param rescale: if True, the zoom is computed to view the atoms; if False, a fixed zoom value is used
""" """
if atoms is None: if atoms is None:
@ -160,7 +160,7 @@ class ClusterViewer(wx.Window):
n_mat[0, 0] = n_mat[2, 2] = np.cos(np.radians(ty)) n_mat[0, 0] = n_mat[2, 2] = np.cos(np.radians(ty))
n_mat[0, 2] = -np.sin(np.radians(ty)) n_mat[0, 2] = -np.sin(np.radians(ty))
n_mat[2, 0] = np.sin(np.radians(ty)) n_mat[2, 0] = np.sin(np.radians(ty))
self.rotation_matrix = np.dot(m_mat, n_mat) self.rotation_matrix = np.dot(m_mat, n_mat)
self.update_model_matrix() self.update_model_matrix()
self.scale_atoms(self.scale) self.scale_atoms(self.scale)
@ -281,7 +281,7 @@ class ClusterViewer(wx.Window):
if self.mode == self.MODE_TRANSLATION: if self.mode == self.MODE_TRANSLATION:
self.mode ^= self.MODE_TRANSLATION self.mode ^= self.MODE_TRANSLATION
self.update_drawing(light=False) self.update_drawing(light=False)
def __evt_right_up_cb(self, event): def __evt_right_up_cb(self, event):
@ -478,7 +478,7 @@ class ClusterViewer(wx.Window):
def create_background_sprite(self, w, h): def create_background_sprite(self, w, h):
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
ctx = cairo.Context(surface) ctx = cairo.Context(surface)
if True: # pylint: disable=using-constant-test if True: # pylint: disable=using-constant-test
g = cairo.LinearGradient(0, 0, 0, h) g = cairo.LinearGradient(0, 0, 0, h)
g.add_color_stop_rgba(0.0, 1.0, 1.0, 1.0, 1.0) g.add_color_stop_rgba(0.0, 1.0, 1.0, 1.0, 1.0)
@ -522,15 +522,15 @@ class ClusterViewer(wx.Window):
ctx.restore() ctx.restore()
self.background_sprite = surface self.background_sprite = surface
@classmethod @classmethod
def create_v2p_matrix(cls, left, right, bottom, top, near, far): def create_v2p_matrix(cls, left, right, bottom, top, near, far):
""" """
creates the matrix that transforms coordinates from view space (space defined by the bounding box passed as argument) to projection space creates the matrix that transforms coordinates from view space (space defined by the bounding box passed as argument) to projection space
this transformation is a scale and offset that maps [left; right], [bottom; top], [near; far] to [-1;1], [-1;1], [0;1] this transformation is a scale and offset that maps [left; right], [bottom; top], [near; far] to [-1;1], [-1;1], [0;1]
""" """
v2p_matrix = np.eye(4) v2p_matrix = np.eye(4) * -1
v2p_matrix[0, 0] = 2. / (right - left) v2p_matrix[0, 0] = 2. / (right - left)
v2p_matrix[1, 1] = 2. / (right - left) v2p_matrix[1, 1] = 2. / (right - left)
v2p_matrix[2, 2] = 1. / (near - far) v2p_matrix[2, 2] = 1. / (near - far)
@ -612,19 +612,23 @@ class ClusterViewer(wx.Window):
d = 20 d = 20
offset = 12 offset = 12
origin = np.array([0, 0, 0, 1]) # @UnusedVariable points = np.array([[d, 0, 0, 1, 0],
x_axis = np.array([d, 0, 0, 1]) [0, d, 0, 1, 1],
y_axis = np.array([0, d, 0, 1]) [0, 0, d, 1, 2]])
z_axis = np.array([0, 0, d, 1])
# translation = np.array([[1, 0, 0, d + offset], # @UnusedVariable # project onto viewport
# [0, 1, 0, h - offset], projections = np.dot(points[:, :4], m_matrix)
# [0, 0, 1, 1 ], projections /= projections[:, -1, None]
# [0, 0, 0, 1 ]]) # add the other columns
projections = np.c_[projections, points[:, 4:]]
# and sort by Z
projections = projections[projections[:,2].argsort()[::-1]]
red = (1, 0, 0) red = (1, 0, 0)
green = (0, 0.7, 0) green = (0, 0.7, 0)
blue = (0, 0, 1) blue = (0, 0, 1)
colors = (red, green, blue)
labels = ('X', 'Y', 'Z')
# draw a white circle # draw a white circle
so = np.array([d + offset, h - d - offset, 0]) so = np.array([d + offset, h - d - offset, 0])
@ -637,19 +641,17 @@ class ClusterViewer(wx.Window):
ctx.set_source_rgba(0.95, 0.95, 0.95, 1) ctx.set_source_rgba(0.95, 0.95, 0.95, 1)
ctx.fill() ctx.fill()
for axis, color, label in ((x_axis, red, 'X'), for x, y, z, w, n in projections:
(y_axis, green, 'Y'), n = int(n)
(z_axis, blue, 'Z')):
axis = np.dot(axis, m_matrix)
axis /= axis[-1]
ctx.move_to(*so[:2]) ctx.move_to(*so[:2])
ctx.rel_line_to(*axis[:2]) ctx.rel_line_to(x, y)
ctx.set_source_rgb(*color) ctx.set_source_rgb(*colors[n])
ctx.set_line_width(2) ctx.set_line_width(2)
ctx.set_font_size(10) ctx.set_font_size(10)
ctx.show_text(label) ctx.show_text(labels[n])
ctx.stroke() ctx.stroke()
def render_atoms(self, ctx): def render_atoms(self, ctx):
try: try:
atoms = self.atoms atoms = self.atoms
@ -732,7 +734,7 @@ class ClusterViewer(wx.Window):
ctx.set_source_rgb(0, 0, 0) ctx.set_source_rgb(0, 0, 0)
ctx.set_font_size(14) ctx.set_font_size(14)
ctx.show_text("%d" % index) ctx.show_text("%d" % index)
# save the rendering # save the rendering
self.atoms_sprite = surface self.atoms_sprite = surface
ctx.set_source_surface(surface, self.im_ox, self.im_oy) ctx.set_source_surface(surface, self.im_ox, self.im_oy)
@ -869,7 +871,7 @@ class ClusterViewer(wx.Window):
#print "scale = ", self.scale, "scale0 = ", self.scale0 #print "scale = ", self.scale, "scale0 = ", self.scale0
#self.scale_atoms(1.) #self.scale_atoms(1.)
if center: if center:
self.translate_atoms(w / 2, h / 2) self.translate_atoms(w / 2, h / 2)