Path: blob/main/tools/contributed/sumopy/agilepy/lib_wx/ogleditor.py
169689 views
#!/usr/bin/env python1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.3# SUMOPy module4# Copyright (C) 2012-2021 University of Bologna - DICAM5# This program and the accompanying materials are made available under the6# terms of the Eclipse Public License 2.0 which is available at7# https://www.eclipse.org/legal/epl-2.0/8# This Source Code may also be made available under the following Secondary9# Licenses when the conditions for such availability set forth in the Eclipse10# Public License 2.0 are satisfied: GNU General Public License, version 211# or later which is available at12# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html13# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1415# @file ogleditor.py16# @author Joerg Schweizer17# @date 20121819"""OpenGL editor"""20import types21import os22import sys23from toolbox import *24from wxmisc import *25from agilepy.lib_base.geometry import *26import agilepy.lib_base.arrayman as am27import agilepy.lib_base.classman as cm28from wx.lib.buttons import GenBitmapTextButton, GenBitmapButton29from wx import glcanvas30from collections import OrderedDict31import wx32if __name__ == '__main__':33__version__ = "0.3"34__licence__ = """licensed under the GPL."""35__copyright__ = "(c) 2012-2018 University of Bologna - DICAM"36__author__ = "Joerg Schweizer"3738__usage__ = """USAGE:39from command line:40python ogleditor.py41python ogleditor.py <scenariobasename> <scenariodir>4243use for debugging44python ogleditor.py --debug > debug.txt 2>&145"""46print __copyright__4748###############################################################################49# IMPORTS5051#import wxversion52# wxversion.select("2.8")5354try:55from OpenGL.GL import *56from OpenGL.GLU import * # project , unproject , tess57from OpenGL.GLUT import *58from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, \59glBindVertexArray6061from OpenGL.arrays import vbo62import numpy as np6364except ImportError:65raise ImportError, "Required dependencies numpy or OpenGL not present"6667if __name__ == '__main__':68try:69FILEDIR = os.path.dirname(os.path.abspath(__file__))70except:71FILEDIR = os.path.dirname(os.path.abspath(sys.argv[0]))72sys.path.append(os.path.join(FILEDIR, "..", ".."))73#IMAGEDIR = os.path.join(APPDIR,"lib_base","images")7475IMAGEDIR = os.path.join(os.path.dirname(__file__), "images")767778# wx gui stuff798081FLATHEAD = 082BEVELHEAD = 183TRIANGLEHEAD = 284ARROWHEAD = 385LEFTTRIANGLEHEAD = 486RIGHTTRIANGLEHEAD = 58788LINEHEADS = { # 'flat':0,# not a style89'bevel': BEVELHEAD,90'triangle': TRIANGLEHEAD,91'arrow': ARROWHEAD,92'lefttriangle': LEFTTRIANGLEHEAD,93'righttriangle': RIGHTTRIANGLEHEAD,94}9596# to be deleted9798###############################################################################99# vbo test100vertices = [101[0.1, 0.1, 0], # 0102[0.1, 0.5, 0.5], # 1103[0, 0.9, 0], # 2104[0.2, 0.0, 0], # 3105[0.5, 0.0, 0], # 4106[0.9, 0, 0], # 5107[0.2, 0.2, 0.5], # 6108[0.5, 0.5, 0.5], # 7109[0.9, 0.9, 0], # 8110]111112indexes = [1130, 1,1142, 7,1155, 6,116]117118colors = [119[0.9, 0.9, 0.0, 0.9], # 0120[0.9, 0.9, 0.0, 0.9], # 1121[0.9, 0.0, 0.9, 0.9], # 2122[0.9, 0.0, 0.9, 0.9], # 3123[0.0, 0.9, 0.9, 0.9], # 4124[0.0, 0.9, 0.9, 0.9], # 5125[0.0, 0.9, 0.9, 0.9], # 6126[0.9, 0.0, 0.9, 0.9], # 7127[0.9, 0.0, 0.9, 0.9], # 8128]129130# Create the VBO131vertexarray = np.array(vertices, dtype=np.float32)132indexarray = np.array(indexes, dtype=np.int32)133134vertexvbo = vbo.VBO(vertexarray)135indexvbo = vbo.VBO(indexarray, target=GL_ELEMENT_ARRAY_BUFFER)136137colorarray = np.array(colors, dtype=np.float32)138colorvbo = vbo.VBO(colorarray)139140###############################################################################141142143#import test_glcanvas as testogl144# class TestVbo(Vbo):145# def draw(self, resolution):146##147##148##149# print 'draw',self.get_ident(),self150# glEnableClientState(GL_VERTEX_ARRAY)151# glEnableClientState(GL_COLOR_ARRAY)152##153# self._colorvbo.bind()154## glColorPointer(4, GL_FLOAT, 0, None)155##156# self._vertexvbo.bind()157# self._indexvbo.bind()158## glVertexPointer(3, GL_FLOAT, 0, None)159##160# print ' self._n_vpo *(self._n_vpo-1)*self._n_drawobjs',self._n_vpo *(self._n_vpo-1)*self._n_drawobjs161# print ' len(self._vertexvbo)',len(self._vertexvbo)162# print ' len(self._colorvbo)',len(self._colorvbo)163# n_vpo = len(self._vertexvbo)/self._n_vpe/self._n_drawobjs+1164# glDrawElements(self._glelement, self._n_vpo *(self._n_vpo-1)*self._n_drawobjs, GL_UNSIGNED_INT, None)165## glDrawElements(self._glelement, len(self._vertexvbo), GL_UNSIGNED_INT, None)166##167# glDisableClientState(GL_VERTEX_ARRAY)168# glDisableClientState(GL_COLOR_ARRAY)169##170# self._vertexvbo.unbind()171# self._indexvbo.unbind()172# self._colorvbo.unbind()173174def normalize(v):175norm = np.linalg.norm(v)176if norm == 0:177return v178return v/norm179180181class Vbo:182def __init__(self, ident, glelement, n_vpe, objtype=''):183self._ident = ident184self._glelement = glelement185self._n_vpe = n_vpe186self._objtype = objtype187self.reset()188189def reset(self):190self._vertexvbo = None191self._indexvbo = None192self._colorvbo = None193self._inds = None194195def get_objtype(self):196return self._objtype197198def is_fill(self):199return self._objtype == 'fill'200201def get_ident(self):202return self._ident203204def get_vpe(self):205return self._n_vpe206207def update_vertices(self, vertices, n=None, inds=None):208"""209210n = number of draw objects211"""212self._inds = inds213# print 'update_vertices',self.get_ident(),n214self._n_drawobjs = n215#216#vertices = np.zeros((self._n_elem_fill, self._n_vpe_fill * 3),dtype=np.float32)217# len(vertices) = n_elem = (n_vpo-1)*n218#n_elem = len(vertices)/n_drawobjs+self._noncyclic219220# n_vpo = vertex per draw object221# n_elem = (n_vpo-1)*n_drawobjs222# n_vpo = vertex per draw object223#self._n_vpo = n_elem/n_drawobjs+1224#n_vert = len(self._vertexvbo_fill)/self._n_vpe_fill/len(self)+1225#n_elem_fill = (n_vert-1)*n226# len(_vertexvbo_fill) = self._n_vpe * self._n_elem_fill = self._n_vpe * (n_vert-1)*n227# print ' len(vertices),n_vpo,n_elem',len(vertices),self._n_vpo,n_elem228229#glDrawElements(GL_TRIANGLES, self._n_vert*self._n_elem_fill, GL_UNSIGNED_INT, None)230# self._n_vert*self._n_elem_fill = n_vert * (n_vert-1)*n231# repeat for each of the n objects: self._n_vpe_fill*(n_vert-1)232# print ' vertices=\n',vertices233# print ' vertices.reshape((-1,3))=\n',vertices.reshape((-1,3))234self._vertexvbo = vbo.VBO(vertices.reshape((-1, 3)))235self._indexvbo = vbo.VBO(np.arange(len(self._vertexvbo), dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)236#self._indexvbo = vbo.VBO(np.arange(len(vertices.reshape((-1,3)) ), dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)237238def destroy(self):239del self._vertexvbo240del self._indexvbo241del self._colorvbo242self.reset()243244def update_colors(self, colors):245246if self._vertexvbo is None:247return248# print 'update_colors',self._n_drawobjs,len(colors)249if len(colors) == 0:250return251if self._n_drawobjs is None:252n_repreat = len(self._vertexvbo)/len(self._inds) # self._n_drawobjs253self._colorvbo = vbo.VBO(np.repeat(colors[self._inds], n_repreat, 0))254else:255n_repreat = len(self._vertexvbo)/self._n_drawobjs256self._colorvbo = vbo.VBO(np.repeat(colors, n_repreat, 0))257258def draw(self, resolution):259260# glEnableClientState(GL_VERTEX_ARRAY)261# glEnableClientState(GL_COLOR_ARRAY)262if self._vertexvbo is None:263return264# print 'Vbo.draw',self.get_ident(),self._n_drawobjs,len(self._vertexvbo)265# if self._n_drawobjs in (0,None): return266if self._n_drawobjs == 0:267return268self._colorvbo.bind()269glColorPointer(4, GL_FLOAT, 0, None)270271self._vertexvbo.bind()272self._indexvbo.bind()273glVertexPointer(3, GL_FLOAT, 0, None)274275# print ' self._n_vpo *(self._n_vpo-1)*self._n_drawobjs',self._n_vpo *(self._n_vpo-1)*self._n_drawobjs276# print ' len(self._vertexvbo)',len(self._vertexvbo)277# print ' len(self._indexvbo)',len(self._indexvbo)278# print ' len(self._colorvbo)',len(self._colorvbo)279#n_vpo = len(self._vertexvbo)/self._n_vpe/self._n_drawobjs+1280#glDrawElements(self._glelement, self._n_vpo *(self._n_vpo-1)*self._n_drawobjs, GL_UNSIGNED_INT, None)281glDrawElements(self._glelement, len(self._vertexvbo), GL_UNSIGNED_INT, None)282283# glDisableClientState(GL_VERTEX_ARRAY)284# glDisableClientState(GL_COLOR_ARRAY)285286self._vertexvbo.unbind()287self._indexvbo.unbind()288self._colorvbo.unbind()289290291class SelectToolMixin(BaseTool):292"""293Mixin for Selection tools for OGL canvas.294"""295296def _init_select(self, is_show_selected=False, detectwidth=0.1, detectpix=5):297"""298Define selection specific attributes.299"""300self.detectpix = detectpix301self.detectwidth = detectwidth # in meter302self.is_show_selected = is_show_selected303304if is_show_selected:305groupnames = ['options']306else:307groupnames = ['_private_']308self.add_col(am.TabIdsArrayConf('drawobjects',309groupnames=groupnames,310name='Object',311info='Selected Draw objects with id',312))313314def activate_select(self, canvas=None):315"""316This call by metacanvas signals that the tool has been317activated and can now interact with metacanvas.318"""319BaseTool.activate(self, canvas)320self._idcounter = 0321322def deactivate_select(self):323"""324This call by metacanvas signals that the tool has been325deactivated and can now interact with metacanvas.326"""327drawing = self._canvas.get_drawing()328329if len(self) > 0:330# ungighlight selected objects331is_draw = False332for drawobj, _id in self.drawobjects.value: # drawing.get_drawobjs():333is_draw |= drawobj.unhighlight([_id], is_update=True)334if is_draw:335self._canvas.draw()336337# remove selected objects338self.del_rows(self.get_ids())339340BaseTool.deactivate(self)341342def iterate_selection(self):343self.unhighlight_current()344self._idcounter += 1345if self._idcounter == len(self):346self._idcounter = 0347self.highlight_current()348349def on_left_down_select(self, event):350# print 'on_left_down_select',len(self)>0,event.ShiftDown(),'is_show_selected',self.is_show_selected351is_draw = False352353if len(self) > 0:354# print ' len(self)',len(self)355if event.ShiftDown():356# print ' ShiftDown'357self.iterate_selection()358self.on_change_selection(event)359is_draw = True360else:361# print ' on_execute_selection 1'362is_draw |= self.on_execute_selection(event)363is_draw |= self.unselect_all()364if self.is_show_selected:365self.parent.refresh_optionspanel(self)366367else:368# print ' no selection len(self)',len(self)369is_draw |= self.pick_all(event)370self.highlight_current()371372if not event.ShiftDown():373# print ' no shift down'374if self.is_preselected():375# print ' is_preselected len(self)',len(self)376self.coord_last = self._canvas.unproject(event.GetPosition())377# print ' on_execute_selection 2'378is_draw |= self.on_execute_selection(event)379# attention: on_execute_selection must take care of selected380# objects in list with self.unselect_all()381382else:383# print ' shift down'384self.coord_last = self._canvas.unproject(event.GetPosition())385386if self.is_show_selected:387# print ' is_show_selected',self.is_show_selected388self.parent.refresh_optionspanel(self)389390return is_draw391392def is_preselected(self):393"""394Check if there are preselected drawobjects in the list.395"""396return len(self) > 0397398def on_execute_selection(self, event):399"""400Definively execute operation on currently selected drawobjects.401"""402self.set_objbrowser()403404return False405406def on_change_selection(self, event):407"""408Called after selection has been changed with SHIFT-click409Do operation on currently selected drawobjects.410"""411self.set_objbrowser()412return False413414def set_objbrowser(self):415pass416417def aboard_select(self, event):418# print 'aboard',self.ident419is_draw = self.unselect_all()420return is_draw421422def get_current_selection(self):423if len(self) > 0:424(drawobj, _id) = self.drawobjects[self.get_ids()[self._idcounter]]425return drawobj, _id426else:427return None, -1428429def is_tool_allowed_on_selection(self):430drawobj, _id = self.get_current_selection()431if drawobj is not None:432return drawobj.is_tool_allowed(self, _id)433else:434False435436def pick_all(self, event):437"""438Pick all objets with id, that are near the pointer439coordinates.440"""441442p = self._canvas.unproject_event(event)443444if self.detectpix > 0:445# detect pixel sensitivity is given446# calculate detectwidth based on current resolution447self.detectwidth = self._canvas.get_resolution()*self.detectpix448449print 'pick_all', self.detectwidth, self.detectpix, self._canvas.get_resolution()450451self._idcounter = 0452is_draw = False453drawing = self._canvas.get_drawing()454# print ' ',drawing.get_drawobjs()455for drawobj in drawing.get_drawobjs():456if drawobj.is_visible():457ids_pick = drawobj.pick(p, detectwidth=self.detectwidth)458# print ' pick',drawobj.get_ident(),ids_pick459if len(ids_pick) > 0:460for id_pick in ids_pick:461is_draw |= self.add_selection(drawobj, id_pick, event)462463return is_draw464465def unhighlight_current(self):466# print 'unhighlight_current',len(self),self._idcounter467if len(self) > 0:468(drawobj, _id) = self.drawobjects[self.get_ids()[self._idcounter]]469drawobj.unhighlight([_id])470471def highlight_current(self):472# print 'highlight_current',len(self),self._idcounter473if len(self) > 0:474(drawobj, _id) = self.drawobjects[self.get_ids()[self._idcounter]]475drawobj.highlight([_id])476477def unselect_all(self):478# print 'unselect_all',len(self)479self._idcounter = 0480if len(self) > 0:481is_draw = True482for drawobj, _id in self.drawobjects.value:483if _id in drawobj:484drawobj.unhighlight([_id])485486self.del_rows(self.get_ids())487else:488is_draw = False489490if is_draw:491self.parent.refresh_optionspanel(self)492# print ' len should be 0:',len(self),is_draw493return is_draw494495def add_selection(self, drawobj, id_pick, event=None):496is_draw = False497drawobjid = self.drawobjects.convert_type((drawobj, id_pick))498ids_match = self.select_ids(self.drawobjects.value == drawobjid)499if len(ids_match) == 0:500self.add_rows(1, drawobjects=[(drawobj, id_pick)])501is_draw = True502return is_draw503504505class AddLineTool(BaseTool):506"""507Mixin for Selection tools for OGL canvas.508"""509510def __init__(self, parent, mainframe=None):511self.init_common('add_line', parent, 'Add line tool',512info='Click on canvas to add a line. Double click to finish, right click to aboard.',513is_textbutton=False,514)515self.init_options()516517def init_options(self):518self.add(cm.AttrConf('width', 0.2,519groupnames=['options'],520perm='rw',521name='Width',522is_save=True,523info='Line width',524))525526self.add(cm.AttrConf('color', np.array([1.0, 0.0, 0.0, 0.8], dtype=np.float32),527groupnames=['options'],528perm='rw',529metatype='color',530name='Fill color',531is_save=True,532info='Line color with format [r,g,b,a]',533))534535# self.add(cm.AttrConf( 'color_fill', np.array([1.0,0.0,0.0,0.8], dtype=np.float32),536# groupnames = ['options'],537# perm='rw',538# metatype = 'color',539# name = 'Fill color',540# is_save = True,541# info = 'Object fill color with format [r,g,b,a]',542# ))543544def set_button_info(self, bsize=(32, 32)):545# print 'set_button_info select tool'546self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'line_24px.png'), wx.BITMAP_TYPE_PNG)547self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'line_24px.png'), wx.BITMAP_TYPE_PNG)548549def set_cursor(self):550# http://www.wxpython.org/docs/api/wx.Cursor-class.html551if self._canvas is not None:552self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))553554def activate(self, canvas=None):555"""556This call by metacanvas??TooldsPallet signals that the tool has been557activated and can now interact with metacanvas.558"""559# print 'activate',self.ident560self._is_active = True561self._canvas = canvas562# self._canvas.del_handles()563canvas.activate_tool(self)564self.set_cursor()565self.is_animated = False566567def deactivate(self):568"""569This call by metacanvas??? ToolePallet signals that the tool has been570deactivated and can now interact with metacanvas.571"""572573is_draw = self.aboard()574self._canvas.deactivate_tool()575self._canvas = None576self._is_active = False577return is_draw578579def on_left_down(self, event):580if not self.is_animated:581return self.begin_animation(event)582583def on_left_dclick(self, event):584if self.is_animated:585return self.end_animation(event)586587def on_motion(self, event):588if self.is_animated:589return self.animate(event)590else:591return False592593def begin_animation(self, event):594# print 'AddLineTool'595#self.drawobj_anim, _id, self.ind_vert = self.get_current_vertexselection()596self.drawobj_anim = self._canvas.get_drawing().get_drawobj_by_ident('fancylines')597self.coord_last = self._canvas.unproject(event.GetPosition())598vert = np.concatenate((self.coord_last, self.coord_last), 1).reshape((2, 3))599# print ' vert ',vert#,self.width.get_value(),self.color.get_value(),600_id = self.drawobj_anim.add_drawobj(vert,601self.width.get_value(), # width602self.color.get_value(),603beginstyle=TRIANGLEHEAD,604endstyle=TRIANGLEHEAD,605)606self.ind_vert = 1607self.drawobj_anim.begin_animation(_id)608609# http://www.wxpython.org/docs/api/wx.Cursor-class.html610self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))611self.is_animated = True612613self.parent.refresh_optionspanel(self)614return True # True for redrawing615616def end_animation(self, event):617self.drawobj_anim.end_animation(is_del_last_vert=False)618# http://www.wxpython.org/docs/api/wx.Cursor-class.html619self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))620621del self.drawobj_anim622#del self.id_anim623self.is_animated = False624self.parent.refresh_optionspanel(self)625return True # True for redrawing626627def animate(self, event):628# print 'animate'629is_draw = False630coords = self._canvas.unproject(event.GetPosition())631vertex_delta = coords-self.coord_last632if np.any(np.abs(vertex_delta) > 0):633is_draw = self.drawobj_anim.stretch_animation(coords, vertex_delta, self.ind_vert)634if is_draw:635self.coord_last = coords636return is_draw637638def aboard(self, event=None):639# print 'aboard',self.ident640641is_draw = False642if self.is_animated:643#id_admin = self.drawobj_anim.get_id_admin()644self.drawobj_anim.del_animation(is_del_main=True)645del self.drawobj_anim646self.is_animated = False647is_draw = True648self.parent.refresh_optionspanel(self)649return is_draw # True for redrawing650651# def set_objbrowser(self):652# pass653654def get_optionspanel(self, parent, size=(200, -1)):655"""656Return tool option widgets on given parent657"""658if self.is_animated:659# show option of currently selected drawobj660self._optionspanel = ObjPanel(parent, obj=self.drawobj_anim,661id=self.drawobj_anim.get_id_anim(),662attrconfigs=None,663#tables = None,664# table = None, id=None, ids=None,665groupnames=['options'],666func_change_obj=None,667show_groupnames=False, show_title=True, is_modal=False,668mainframe=self.parent.get_mainframe(),669pos=wx.DefaultPosition, size=size, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,670func_apply=self.on_apply_option,671immediate_apply=False, panelstyle='default', # 'instrumental'672standartbuttons=['apply', 'restore'])673else:674675self._optionspanel = ObjPanel(parent, obj=self,676id=None,677attrconfigs=None,678#tables = None,679# table = None, id=None, ids=None,680groupnames=['options'],681func_change_obj=None,682show_groupnames=False, show_title=True, is_modal=False,683mainframe=self.parent.get_mainframe(),684pos=wx.DefaultPosition, size=size, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,685func_apply=self.on_apply_option,686immediate_apply=False, panelstyle='default', # 'instrumental'687standartbuttons=['apply', 'restore'])688689return self._optionspanel690691def on_apply_option(self, drawobj, id, ids):692# print '\n\n\non_apply_option drawobj, id, ids',drawobj, id, ids693if self.is_animated:694if drawobj == self.drawobj_anim:695drawobj._update_colorvbo()696drawobj._update_vertexvbo()697698self._canvas.draw()699700701class AddCircleTool(AddLineTool):702"""703Mixin for Selection tools for OGL canvas.704"""705706def __init__(self, parent, mainframe=None):707self.init_common('add_circle', parent, 'Add circle tool',708info='Click on canvas to add a circle. Double click to finish, right click to aboard.',709is_textbutton=False,710)711self.init_options()712713def init_options(self):714715self.add(cm.AttrConf('color', np.array([1.0, 0.0, 0.0, 0.8], dtype=np.float32),716groupnames=['options'],717perm='rw',718metatype='color',719name='Color',720is_save=True,721info='Line color with format [r,g,b,a]',722))723724self.add(cm.AttrConf('color_fill', np.array([1.0, 0.0, 0.0, 0.8], dtype=np.float32),725groupnames=['options'],726perm='rw',727metatype='color',728name='Fill color',729is_save=True,730info='Circle fill color with format [r,g,b,a]',731))732733def set_button_info(self, bsize=(32, 32)):734# print 'set_button_info select tool'735self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'circle_empty_24px.png'), wx.BITMAP_TYPE_PNG)736self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'circle_empty_24px.png'), wx.BITMAP_TYPE_PNG)737738def begin_animation(self, event):739# print 'AddLineTool'740#self.drawobj_anim, _id, self.ind_vert = self.get_current_vertexselection()741self.drawobj_anim = self._canvas.get_drawing().get_drawobj_by_ident('circles')742self.coord_last = self._canvas.unproject(event.GetPosition())743#vert = np.concatenate((self.coord_last,self.coord_last),1).reshape((2,3))744# print ' vert ',vert#,self.width.get_value(),self.color.get_value(),745746_id = self.drawobj_anim.add_drawobj(1.0*self.coord_last,7470.0,748self.color.get_value(),749self.color_fill.get_value(),750)751752self.drawobj_anim.begin_animation(_id)753754# http://www.wxpython.org/docs/api/wx.Cursor-class.html755self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))756self.is_animated = True757758self.parent.refresh_optionspanel(self)759return True # True for redrawing760761def end_animation(self, event):762self.drawobj_anim.end_animation(is_del_last_vert=False)763# http://www.wxpython.org/docs/api/wx.Cursor-class.html764self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))765766del self.drawobj_anim767#del self.id_anim768self.is_animated = False769self.parent.refresh_optionspanel(self)770return True # True for redrawing771772def animate(self, event):773# print 'animate'774is_draw = False775coords = self._canvas.unproject(event.GetPosition())776vertex_delta = coords-self.coord_last777if np.any(np.abs(vertex_delta) > 0):778is_draw = self.drawobj_anim.stretch_animation(coords, vertex_delta, 1)779if is_draw:780self.coord_last = coords781return is_draw782783784class AddPolylineTool(AddLineTool):785"""786Mixin for Selection tools for OGL canvas.787"""788789def __init__(self, parent, mainframe=None):790self.init_common('add_polyline', parent, 'Add polyline tool',791info='Click on canvas to add a poly line. Add a vertex with a single click, double click to finish, right click to aboard.',792is_textbutton=False,793)794self.init_options()795796def set_button_info(self, bsize=(32, 32)):797# print 'set_button_info select tool'798self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'polyline_24px.png'), wx.BITMAP_TYPE_PNG)799self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'polyline_24px.png'), wx.BITMAP_TYPE_PNG)800801def on_left_down(self, event):802if not self.is_animated:803return self.begin_animation(event)804else:805# add vertex806return self.append_vert_to_anim(event)807808def begin_animation(self, event):809# print 'AddLineTool.begin_animation'810#self.drawobj_anim, _id, self.ind_vert = self.get_current_vertexselection()811self.drawobj_anim = self._canvas.get_drawing().get_drawobj_by_ident('polylines')812self.coord_last = self._canvas.unproject(event.GetPosition())813#vertices = [list(self.coord_last),list(self.coord_last) ]814vertices = [1.0*self.coord_last, 1.0*self.coord_last] # attention, we need copies here!!815# print ' vertices ',vertices#,self.width.get_value(),self.color.get_value(),816817_id = self.drawobj_anim.add_drawobj(vertices,818self.width.get_value(), # width819self.color.get_value(),820beginstyle=TRIANGLEHEAD,821endstyle=TRIANGLEHEAD,822)823self.ind_vert = 1824self.drawobj_anim.begin_animation(_id)825826# http://www.wxpython.org/docs/api/wx.Cursor-class.html827self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))828self.is_animated = True829830self.parent.refresh_optionspanel(self)831return True # True for redrawing832833def end_animation(self, event):834self.drawobj_anim.end_animation(is_del_last_vert=True)835# http://www.wxpython.org/docs/api/wx.Cursor-class.html836self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))837838del self.drawobj_anim839#del self.id_anim840self.is_animated = False841self.parent.refresh_optionspanel(self)842return True # True for redrawing843844def append_vert_to_anim(self, event):845self.coord_last = self._canvas.unproject(event.GetPosition())846847self.ind_vert = self.drawobj_anim.append_vert_to_animation(self.coord_last)848849return True850851852class AddPolygonTool(AddPolylineTool):853"""854Mixin for Selection tools for OGL canvas.855"""856857def __init__(self, parent, mainframe=None):858self.init_common('add_polygon', parent, 'Add polygon tool',859info='Click on canvas to add a polygon. Add a vertex with a single click, double click to finish, right click to aboard.',860is_textbutton=False,861)862self.init_options()863864def init_options(self):865self.add(cm.AttrConf('color', np.array([1.0, 0.0, 0.0, 0.8], dtype=np.float32),866groupnames=['options'],867perm='rw',868metatype='color',869name='Fill color',870is_save=True,871info='Line color with format [r,g,b,a]',872))873874# self.add(cm.AttrConf( 'color_fill', np.array([1.0,0.0,0.0,0.8], dtype=np.float32),875# groupnames = ['options'],876# perm='rw',877# metatype = 'color',878# name = 'Fill color',879# is_save = True,880# info = 'Object fill color with format [r,g,b,a]',881# ))882883def set_button_info(self, bsize=(32, 32)):884# print 'set_button_info select tool'885self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'polygon2_24px.png'), wx.BITMAP_TYPE_PNG)886self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'polygon2_24px.png'), wx.BITMAP_TYPE_PNG)887888def begin_animation(self, event):889# print 'AddLineTool.begin_animation'890#self.drawobj_anim, _id, self.ind_vert = self.get_current_vertexselection()891self.drawobj_anim = self._canvas.get_drawing().get_drawobj_by_ident('polygons')892self.coord_last = self._canvas.unproject(event.GetPosition())893#vertices = [list(self.coord_last),list(self.coord_last) ]894vertices = [1.0*self.coord_last, 1.0*self.coord_last, ] # attention, we need copies here!!895# print ' vertices ',vertices#,self.width.get_value(),self.color.get_value(),896897_id = self.drawobj_anim.add_drawobj(vertices,898color=self.color.get_value(),899)900self.ind_vert = 1901self.drawobj_anim.begin_animation(_id)902903# http://www.wxpython.org/docs/api/wx.Cursor-class.html904self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))905self.is_animated = True906907self.parent.refresh_optionspanel(self)908return True # True for redrawing909910911class SelectTool(SelectToolMixin):912"""913Selection tool for OGL canvas.914"""915916def __init__(self, parent, detectwidth=0.1, detectpix=5, mainframe=None):917"""918To be overridden by specific tool.919"""920self.init_common('select', parent, 'Selection tool',921info='Select objects in canvas',922is_textbutton=False,923)924self._init_select(is_show_selected=True, detectwidth=detectwidth, detectpix=detectpix)925926def set_button_info(self, bsize=(32, 32)):927# print 'set_button_info select tool' Select_32px928929# wx.ART_INFORMATION930self._bitmap = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_TOOLBAR)931self._bitmap_sel = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_TOOLBAR)932933#self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR,'Cursor-Click-icon_24px.png'),wx.BITMAP_TYPE_PNG)934# self._bitmap_sel=wx.Bitmap(os.path.join(IMAGEDIR,'Cursor-Click-icon_24px.png'),wx.BITMAP_TYPE_PNG)935936#self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR,'selectIcon.bmp'),wx.BITMAP_TYPE_BMP)937# self._bitmap_sel=wx.Bitmap(os.path.join(IMAGEDIR,'selectIconSel.bmp'),wx.BITMAP_TYPE_BMP)938939def set_cursor(self):940# http://www.wxpython.org/docs/api/wx.Cursor-class.html941if self._canvas is not None:942self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_QUESTION_ARROW))943944def deactivate(self):945"""946This call by metacanvas signals that the tool has been947deactivated and can now interact with metacanvas.948"""949self.deactivate_select()950self._is_active = False951952def activate(self, canvas=None):953"""954This call by metacanvas signals that the tool has been955activated and can now interact with metacanvas.956"""957self.activate_select(canvas) # calls also set_cursor958self._is_active = True959960def on_left_down(self, event):961return self.on_left_down_select(event)962963def aboard(self, event):964# print 'aboard',self.ident965return self.aboard_select(event)966967968class ConfigureTool(SelectToolMixin):969"""970Selection tool for OGL canvas.971"""972973def __init__(self, parent, detectwidth=0.1, detectpix=5, mainframe=None):974"""975To be overridden by specific tool.976"""977self.init_common('configure', parent, 'Configure tool',978info='Drawing options.',979is_textbutton=False,980)981982self._init_select(is_show_selected=False, detectwidth=detectwidth, detectpix=detectpix)983984# self.drawing =985#attrsman.add( cm.ObjConf( Nodes(self) ) )986987# self.add_col(am.TabIdsArrayConf( 'drawobjects',988# groupnames = ['options'],989# name = 'Object',990# info = 'Selected Draw objects with id',991# ))992993def set_button_info(self, bsize=(32, 32)):994# print 'set_button_info select tool'995self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'gtk_configure_24px.png'), wx.BITMAP_TYPE_PNG)996self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'gtk_configure_24px.png'), wx.BITMAP_TYPE_PNG)997998def set_cursor(self):999# http://www.wxpython.org/docs/api/wx.Cursor-class.html1000if self._canvas is not None:1001self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_QUESTION_ARROW))10021003def deactivate(self):1004"""1005This call by metacanvas signals that the tool has been1006deactivated and can now interact with metacanvas.1007"""1008self.deactivate_select()1009self._is_active = False10101011def activate(self, canvas=None):1012"""1013This call by metacanvas signals that the tool has been1014activated and can now interact with metacanvas.1015"""1016self.activate_select(canvas) # calls also set_cursor1017self._is_active = True10181019def on_left_down(self, event):1020return self.on_left_down_select(event)10211022def aboard(self, event):1023# print 'aboard',self.ident1024return self.aboard_select(event)10251026def set_objbrowser(self):1027self.parent.refresh_optionspanel(self)10281029def get_optionspanel(self, parent):1030"""1031Return tool option widgets on given parent1032"""1033drawobj, _id = self.get_current_selection()1034if drawobj is None:1035# no current selection-> show options of whole drawing1036size = (200, -1)1037self._optionspanel = NaviPanel(parent, obj=self._canvas.get_drawing(),1038attrconfigs=None,1039#tables = None,1040# table = None, id=None, ids=None,1041groupnames=['options'],1042mainframe=self.parent.get_mainframe(),1043#pos=wx.DefaultPosition, size=size, style = wx.MAXIMIZE_BOX|wx.RESIZE_BORDER,1044func_apply=self.on_apply_option,1045immediate_apply=False, panelstyle='default', # 'instrumental'1046standartbuttons=['apply', 'restore'])1047else:1048# show option of currently selected drawobj1049size = (200, -1)1050self._optionspanel = ObjPanel(parent, obj=drawobj,1051id=_id,1052attrconfigs=None,1053#tables = None,1054# table = None, id=None, ids=None,1055groupnames=['options'],1056func_change_obj=None,1057show_groupnames=False, show_title=True, is_modal=False,1058mainframe=self.parent.get_mainframe(),1059pos=wx.DefaultPosition, size=size, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,1060func_apply=self.on_apply_option,1061immediate_apply=False, panelstyle='default', # 'instrumental'1062standartbuttons=['apply', 'restore'])10631064return self._optionspanel10651066def on_apply_option(self, drawobj, id, ids):1067# print '\n\n\non_apply_option drawobj, id, ids',drawobj, id, ids1068drawing = self._canvas.get_drawing()1069drawobjs = drawing.get_drawobjs(is_anim=True)10701071if drawobj in drawobjs:1072drawobj._update_colorvbo()1073drawobj._update_vertexvbo()10741075self._canvas.draw()107610771078class HandleTool(SelectTool):1079"""1080General tool to help select handles.1081"""10821083def __init__(self, parent, detectwidth=0.1, detectpix=5, mainframe=None):1084"""1085To be overridden by specific tool.1086"""1087self.init_common('select_handles', parent, 'Handle selection',1088info='Select handles on canvas',1089is_textbutton=False,1090)10911092self._init_select(detectwidth=detectwidth, detectpix=detectpix)10931094def _init_select(self, is_show_selected=True, detectwidth=0.1, detectpix=5):10951096SelectTool._init_select(self, is_show_selected, detectwidth=detectwidth, detectpix=detectpix)1097self.add_col(am.ArrayConf('inds_vertex', -1,1098groupnames=['options'], # ['_private_'], #'options',1099name='Vertex index',1100info='Vertex index.',1101))11021103def set_button_info(self, bsize=(32, 32)):1104# print 'set_button_info select tool' Select_32px11051106# wx.ART_INFORMATION1107self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'Cursor-Click-icon_24px.png'), wx.BITMAP_TYPE_PNG)1108self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'Cursor-Click-icon_24px.png'), wx.BITMAP_TYPE_PNG)11091110#self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR,'selectIcon.bmp'),wx.BITMAP_TYPE_BMP)1111# self._bitmap_sel=wx.Bitmap(os.path.join(IMAGEDIR,'selectIconSel.bmp'),wx.BITMAP_TYPE_BMP)11121113def set_cursor(self):1114# http://www.wxpython.org/docs/api/wx.Cursor-class.html1115if self._canvas is not None:1116self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_RIGHT_ARROW))11171118def get_current_vertexselection(self):1119if len(self) > 0:1120id_selected = self.get_ids()[self._idcounter]1121(drawobj, _id) = self.drawobjects[id_selected]1122ind_vertex = self.inds_vertex[id_selected]1123return drawobj, _id, ind_vertex1124else:1125return None, -1, -111261127def pick_all(self, event):1128"""1129Pick all objets with id and vertex index, that are near the pointer1130coordinates.1131"""1132# print 'HandleTool.pick_all'1133p = self._canvas.unproject_event(event)11341135if self.detectpix > 0:1136# detect pixel sensitivity is given1137# calculate detectwidth based on current resolution1138self.detectwidth = self._canvas.get_resolution()*self.detectpix11391140self._idcounter = 01141is_draw = False1142drawing = self._canvas.get_drawing()1143# print ' ',drawing.get_drawobjs()1144for drawobj in drawing.get_drawobjs():1145# print ' ',drawobj,drawobj.get_ident()1146# experiment1147if drawobj.is_visible():1148handles = drawobj.pick_handle(p, detectwidth=self.detectwidth)1149# print ' handles',handles1150if len(handles) > 0:1151# print ' handles',drawobj.get_ident(),handles1152for id_handle, ind_vertex in handles:1153is_draw |= self.add_selection(drawobj, id_handle, ind_vertex, event)1154#is_draw |= self.select(drawobj,id_pick, event)1155# break1156return is_draw11571158def add_selection(self, drawobj, id_handle, ind_vertex, event):1159is_draw = False1160drawobjid = self.drawobjects.convert_type((drawobj, id_handle))1161ids_match = self.select_ids(self.drawobjects.value == drawobjid)1162if len(ids_match) == 0:1163self.add_rows(1, drawobjects=[(drawobj, id_handle)], inds_vertex=[ind_vertex])1164is_draw = True1165return is_draw116611671168class DeleteTool(SelectTool):1169"""1170Delete tool for OGL canvas.1171"""11721173def __init__(self, parent, detectwidth=0.1, detectpix=5, mainframe=None):1174"""1175To be overridden by specific tool.1176"""1177self.init_common('delete', parent, 'Delete tool',1178info='Select and delete objects in canvas.',1179is_textbutton=False,1180)1181self._init_select(is_show_selected=True, detectwidth=detectwidth, detectpix=detectpix)11821183def set_button_info(self, bsize=(32, 32)):1184self._bitmap = wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR)1185self._bitmap_sel = wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR)11861187def set_cursor(self):1188# http://www.wxpython.org/docs/api/wx.Cursor-class.html1189if self._canvas is not None:1190# self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_RIGHT_ARROW))1191pass11921193def on_execute_selection(self, event):1194"""1195Definively execute operation on currently selected drawobjects.1196"""1197if self.is_tool_allowed_on_selection():1198drawobj, _id = self.get_current_selection()11991200if drawobj is not None:1201drawobj.del_drawobj(_id)1202self.unselect_all()1203is_draw = True1204else:1205is_draw = False1206return is_draw1207else:1208return False12091210def on_change_selection(self, event):1211"""1212Called after selection has been changed with SHIFT-click1213Do operation on currently selected drawobjects.1214"""1215return False121612171218class MoveTool(SelectTool):1219"""1220Move tool for OGL canvas.1221"""12221223def __init__(self, parent, detectwidth=0.1, detectpix=5, mainframe=None):1224"""1225To be overridden by specific tool.1226"""1227self.drawobj_anim, self.id_anim = (None, -1)12281229self.init_common('move', parent, 'Move tool',1230info='Select and drag objects in canvas.',1231is_textbutton=False,1232)1233self._init_select(is_show_selected=True, detectwidth=detectwidth, detectpix=detectpix)12341235def set_button_info(self, bsize=(32, 32)):1236self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'arrow_cursor_drag_24px.png'), wx.BITMAP_TYPE_PNG)1237self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'arrow_cursor_drag_24px.png'), wx.BITMAP_TYPE_PNG)12381239def activate(self, canvas=None):1240"""1241This call by metacanvas signals that the tool has been1242activated and can now interact with metacanvas.1243"""1244self.activate_select(canvas)1245self.is_animated = False1246self._is_active = True12471248def set_cursor(self):1249# http://www.wxpython.org/docs/api/wx.Cursor-class.html1250if self._canvas is not None:1251self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))12521253def deactivate(self):1254"""1255This call by metacanvas signals that the tool has been1256deactivated and can now interact with metacanvas.1257"""1258# self.deactivate_select()1259#self.is_animated = False1260is_draw = self.aboard()1261self._canvas.deactivate_tool()1262self._canvas = None1263self._is_active = False1264return is_draw12651266def on_left_down(self, event):1267if self.is_animated:1268return self.end_animation(event)1269else:1270return self.on_left_down_select(event)12711272def on_motion(self, event):1273if self.is_animated:1274return self.animate(event)1275else:1276return False12771278def on_execute_selection(self, event):1279"""1280Definively execute operation on currently selected drawobjects.1281"""1282if self.is_tool_allowed_on_selection():1283if not self.is_animated:1284return self.begin_animation(event)1285else:1286return self.end_animation(event)12871288else:1289return False12901291def on_change_selection(self, event):1292"""1293Called after selection has been changed with SHIFT-click1294Do operation on currently selected drawobjects.1295"""1296return False12971298def begin_animation(self, event):1299self.drawobj_anim, _id = self.get_current_selection()1300#self.drawobj_anim, self.id_anim = drawobj.get_anim(_id)1301self.drawobj_anim.begin_animation(_id)13021303# done in select method1304#self.coord_last = self._canvas.unproject(event.GetPosition())13051306# http://www.wxpython.org/docs/api/wx.Cursor-class.html1307self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))1308self.is_animated = True1309return True # True for redrawing13101311def end_animation(self, event):1312#drawobj, _id = self.get_current_selection()1313#drawobj.set_anim(_id, (self.drawobj_anim, self.id_anim))1314self.drawobj_anim.end_animation()1315# http://www.wxpython.org/docs/api/wx.Cursor-class.html1316self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))13171318del self.drawobj_anim1319#del self.id_anim1320self.is_animated = False13211322self.unselect_all()1323return True # True for redrawing13241325def animate(self, event):1326is_draw = False1327coords = self._canvas.unproject(event.GetPosition())1328vertex_delta = coords-self.coord_last1329if np.any(np.abs(vertex_delta) > 0):1330is_draw = self.drawobj_anim.move_animation(coords, vertex_delta)1331if is_draw:1332self.coord_last = coords1333return is_draw13341335def aboard(self, event=None):1336# print 'aboard',self.ident13371338is_draw = False1339if self.is_animated:1340self.drawobj_anim.del_animation()1341del self.drawobj_anim1342self.is_animated = False1343is_draw = True13441345is_draw |= self.aboard_select(event)1346return is_draw # True for redrawing134713481349class StretchTool(HandleTool):1350"""1351Stretch tool for OGL canvas.1352"""13531354def __init__(self, parent, detectwidth=0.1, detectpix=5, mainframe=None):1355"""1356To be overridden by specific tool.1357"""1358self.drawobj_anim, self.id_anim = (None, -1)13591360self.init_common('stretch', parent, 'Stretch tool',1361info='Select vertex and stretch object in canvas.',1362is_textbutton=False,1363)13641365self._init_select(is_show_selected=True, detectwidth=detectwidth, detectpix=detectpix)13661367def set_button_info(self, bsize=(32, 32)):1368# print 'set_button_info select tool' Select_32px13691370self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'move_vertex_24px.png'), wx.BITMAP_TYPE_PNG)1371self._bitmap_sel = wx.Bitmap(os.path.join(IMAGEDIR, 'move_vertex_24px.png'), wx.BITMAP_TYPE_PNG)13721373# self._bitmap = wx.Bitmap(os.path.join(IMAGEDIR,'Cursor-Click-icon_24px.png'),wx.BITMAP_TYPE_PNG)1374# self._bitmap_sel=wx.Bitmap(os.path.join(IMAGEDIR,'Cursor-Click-icon_24px.png'),wx.BITMAP_TYPE_PNG)13751376def set_cursor(self):1377# http://www.wxpython.org/docs/api/wx.Cursor-class.html1378if self._canvas is not None:1379self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))13801381def activate(self, canvas=None):1382"""1383This call by metacanvas signals that the tool has been1384activated and can now interact with metacanvas.1385"""1386self.activate_select(canvas)1387self.is_animated = False1388self._is_active = True13891390def deactivate(self):1391"""1392This call by metacanvas signals that the tool has been1393deactivated and can now interact with metacanvas.1394"""1395is_draw = self.aboard()1396self._canvas.deactivate_tool()1397self._canvas = None1398self._is_active = False1399return is_draw1400# self.deactivate_select()1401#self.is_animated = False14021403def on_left_down(self, event):1404if self.is_animated:1405return self.end_animation(event)1406else:1407# this call will set self.last_coord1408# and call self.on_execute_selection1409# in case a suitable object has been selected1410return self.on_left_down_select(event)14111412def on_motion(self, event):1413if self.is_animated:1414return self.animate(event)1415else:1416return False14171418def on_execute_selection(self, event):1419"""1420Definively execute operation on currently selected drawobjects.1421"""1422print 'Stretch', self.is_tool_allowed_on_selection()1423if self.is_tool_allowed_on_selection():1424if not self.is_animated:1425return self.begin_animation(event)1426else:1427return self.end_animation(event)1428else:1429return False14301431def on_change_selection(self, event):1432"""1433Called after selection has been changed with SHIFT-click1434Do operation on currently selected drawobjects.1435"""1436return False14371438def begin_animation(self, event):1439# print 'Stretchtool.begin_animation'1440self.drawobj_anim, _id, self.ind_vert = self.get_current_vertexselection()14411442# print ' self.drawobj_anim, _id, self.ind_vert=',self.drawobj_anim, _id, self.ind_vert1443#self.drawobj_anim, self.id_anim = drawobj.get_anim(_id)1444self.drawobj_anim.begin_animation(_id)1445self.coord_last = self._canvas.unproject(event.GetPosition())14461447# http://www.wxpython.org/docs/api/wx.Cursor-class.html1448self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))1449self.is_animated = True1450return True # True for redrawing14511452def end_animation(self, event):1453#drawobj, _id = self.get_current_selection()1454#drawobj.set_anim(_id, (self.drawobj_anim, self.id_anim))1455self.drawobj_anim.end_animation()1456# http://www.wxpython.org/docs/api/wx.Cursor-class.html1457self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_HAND))14581459del self.drawobj_anim1460#del self.id_anim1461self.is_animated = False14621463self.unselect_all()1464return True # True for redrawing14651466def animate(self, event):1467# print 'animate'1468is_draw = False1469coords = self._canvas.unproject(event.GetPosition())1470vertex_delta = coords-self.coord_last1471if np.any(np.abs(vertex_delta) > 0):1472is_draw = self.drawobj_anim.stretch_animation(coords, vertex_delta, self.ind_vert)1473if is_draw:1474self.coord_last = coords1475return is_draw14761477def aboard(self, event=None):1478# print 'aboard',self.ident14791480is_draw = False1481if self.is_animated:1482self.drawobj_anim.del_animation()1483del self.drawobj_anim1484self.is_animated = False1485is_draw = True14861487is_draw |= self.aboard_select(event)1488return is_draw # True for redrawing148914901491class DrawobjMixin(am.ArrayObjman):1492def init_common(self, ident, parent=None, name=None,1493linewidth=1,1494is_parentobj=False,1495is_outline=True, # show outline1496is_fill=False,1497is_fillable=True,1498n_vert=2, # number of vertex per draw object1499c_highl=0.3, **kwargs):15001501self._init_objman(ident, parent=parent, name=name, **kwargs)15021503self._vbos = OrderedDict()15041505self._n_vert = n_vert15061507# ident of drawobject used for animations1508self._ident_drawobj_anim = 'anim_lines'15091510self.add(am.AttrConf('color_anim', np.array([0.9, 0.9, 0.9, 0.5], dtype=np.float32),1511groupnames=['_private_'],1512perm='rw',1513metatype='color',1514name='Anim. color',1515is_save=True,1516info='Color of animated object(s) in [r,g,b,a]',1517))15181519# TODO: these 2 could be eliminated and replaced by function1520# self._n_elem = 0# will be adjusted in update_vertexvbo1521#self._n_elem_fill = 0#15221523self.add(cm.AttrConf('_is_visible', True,1524groupnames=['options'],1525perm='wr',1526is_save=True,1527is_plugin=False,1528name='Visible?',1529info='If True, object are visible, otherwise it is not drwan.',1530))15311532if is_fillable > 0:1533# objects can potentially be filled1534self.add(cm.AttrConf('_is_fill', is_fill,1535groupnames=['_private'],1536perm='wr',1537is_save=True,1538is_plugin=False,1539name='Fill',1540info='If True, object are filled.',1541))1542self.add(cm.AttrConf('_is_outline', is_outline,1543groupnames=['_private'],1544perm='rw',1545is_save=True,1546is_plugin=False,1547name='Outline',1548info='If True, outline of object is shown.',1549))15501551self.add_col(am.ArrayConf('colors_fill', np.zeros(4, dtype=np.float32),1552dtype=np.float32,1553groupnames=['options'],1554perm='rw',1555metatype='color',1556name='Fill color',1557is_save=True,1558info='Object fill color with format [r,g,b,a]',1559))15601561self.add_col(am.ArrayConf('colors_fill_highl', np.zeros(4, dtype=np.float32),1562dtype=np.float32,1563groupnames=['_private'],1564perm='rw',1565metatype='color',1566name='Fill color highl',1567is_save=False,1568info='Object fill color when highlighting with format [r,g,b,a]',1569))15701571else:1572# no filling foreseen1573self.add(cm.AttrConf('_is_fill', False,1574groupnames=['_private'],1575perm='r',1576is_save=True,1577is_plugin=False,1578name='Filled',1579info='If True, object is filled.',1580))15811582self.add(cm.AttrConf('_is_outline', True,1583groupnames=['_private'],1584perm='r',1585is_save=True,1586is_plugin=False,1587name='Outline',1588info='If True, outline of object is shown.',1589))1590if is_outline:1591self.add_col(am.ArrayConf('colors', np.zeros(4, dtype=np.float32),1592dtype=np.float32,1593groupnames=['options'],1594perm='rw',1595metatype='color',1596name='Color',1597is_save=True,1598info='Object Vertex color with format [r,g,b,a]',1599))16001601self.add_col(am.ArrayConf('colors_highl', np.zeros(4, dtype=np.float32),1602dtype=np.float32,1603groupnames=['_private'],1604perm='rw',1605metatype='color',1606name='Color highl',1607is_save=False,1608info='Added object color when highlighting with format [r,g,b,a]',1609))16101611self.add(cm.AttrConf('linewidth', linewidth,1612groupnames=['options'],1613perm='wr',1614is_save=True,1615is_plugin=False,1616name='Line width',1617info='Line width in pixel',1618))16191620# print 'init_common',self.format_ident(),self._is_fill.value,self._is_outline.value16211622self.add(cm.AttrConf('c_highl', c_highl,1623groupnames=['_private'],1624perm='wr',1625is_save=True,1626is_plugin=False,1627name='Highl. const.',1628info='Highlight constant takes values beteewn 0 and 1 and is the amount of brightness added for highlighting',1629))16301631self.add_col(am.ArrayConf('are_highlighted', False,1632dtype=np.bool,1633groupnames=['options'],1634perm='rw',1635name='highlighted',1636is_save=False,1637info='If true, object is highlighted',1638))1639# self.add_col(am.ArrayConf( 'have_handles', False,1640# dtype=np.bool,1641# groupnames = ['options'],1642# perm='rw',1643# name = 'has handles',1644# is_save = False,1645# info = 'If true, object has handles',1646# ))16471648if is_parentobj:1649self.add_col(am.IdsArrayConf('ids_parent', parent,1650is_save=True,1651name=parent.format_ident()+'[ID]',1652info='ID of '+parent.get_name()+' object.',1653))16541655def get_vertices_array(self):1656return self.vertices.value16571658def get_vertices(self, ids):1659return self.vertices[ids]16601661def set_vertices(self, ids, vertices, is_update=True):1662self.vertices[ids] = vertices1663if is_update:1664self._update_vertexvbo()16651666def is_tool_allowed(self, tool, id_drawobj=-1):1667"""1668Returns True if this tool can be applied to this drawobj.1669Optionally a particular drawobj can be specified with id_drawobj.1670"""1671# basic tools:1672#tool.ident in 'configure','select_handles','delete','move','stretch'1673return True16741675def is_outline(self):1676return self._is_outline.get_value()16771678def is_fill(self):1679return self._is_fill.get_value()16801681def is_visible(self):1682return self._is_visible.value16831684def set_visible(self, is_visible):1685self._is_visible.set_value(is_visible)1686# print 'set_visible',self._is_visible.value16871688def del_drawobj(self, _id, is_update=True):1689self.del_row(_id)1690if is_update:1691self._update_vertexvbo()1692self._update_colorvbo()16931694def begin_animation(self, id_target):1695# print 'begin_animation',id_target1696# print ' self.vertices.value',self.vertices.value1697# print ' ids',self.get_ids()1698self._id_target = id_target1699self._drawobj_anim = self.parent.get_drawobj_by_ident(self._ident_drawobj_anim)1700self.id_anim = self._drawobj_anim.add_drawobj(np.array(self.vertices[id_target]),1701self.color_anim.value,1702)1703return True17041705def end_animation(self, is_del_last_vert=False):1706# print 'end_animation',self.ident,self._id_target1707# print ' verices =',self._drawobj_anim.vertices[self.id_anim]1708self.set_vertices(self._id_target, self._drawobj_anim.get_vertices(self.id_anim)) # .copy()1709self.del_animation()1710# self._drawobj_anim.del_drawobj(self.id_anim)1711self._update_vertexvbo()1712self._update_colorvbo()1713return True17141715def del_animation(self, is_del_main=False):1716# print 'end_animation',self.ident,_id,self._drawobj_anim1717self._drawobj_anim.del_drawobj(self.id_anim)1718self._drawobj_anim = None17191720if is_del_main:1721self.del_drawobj(self._id_target)17221723self.id_anim = -11724return True17251726def move_animation(self, vertex, vertex_delta):17271728# if self.ident == 'polylines':1729# print 'move_animation',self.ident,self._id_target, vertex_delta1730# print ' before self._drawobj_anim.vertices[self.id_anim]',self._drawobj_anim.vertices[self.id_anim]1731# ans = self._drawobj_anim.move(self.id_anim, vertex, vertex_delta)1732# print ' after self._drawobj_anim.vertices[self.id_anim]',self._drawobj_anim.vertices[self.id_anim]1733# return ans1734# else:1735return self._drawobj_anim.move(self.id_anim, vertex, vertex_delta)17361737def get_id_anim(self):1738return self._id_target17391740def stretch_animation(self, vertex, vertex_delta, ind_vertex):1741# print 'stretch',self.ident,_id1742# print ' ',vertex,vertex_delta,ind_vertex1743# if self.ident == 'polylines':1744# print 'stretch_animation',self.ident,self._id_target, ind_vertex, vertex_delta1745# print ' before self._drawobj_anim.vertices[self.id_anim]',self._drawobj_anim.vertices[self.id_anim]1746# ans = self._drawobj_anim.stretch(self.id_anim,vertex, vertex_delta, ind_vertex)1747# print ' after self._drawobj_anim.vertices[self.id_anim]',self._drawobj_anim.vertices[self.id_anim]1748# return ans1749# else:1750return self._drawobj_anim.stretch(self.id_anim, vertex, vertex_delta, ind_vertex)17511752def get_anim(self, _id):1753drawobj_anim = self.parent.get_drawobj_by_ident('anim_lines')17541755id_anim = drawobj_anim.add_drawobj(np.array(self.vertices[_id]),1756[0.9, 0.9, 0.9, 0.5]1757)1758# print 'get_anim',self.ident,_id,self.vertices[_id]1759return drawobj_anim, id_anim17601761def set_anim(self, _id, drawobjelem_anim):1762# print 'set_anim',self.ident,_id,drawobjelem_anim1763(drawobj_anim, id_anim) = drawobjelem_anim1764# print ' self.vertices[_id]=',self.vertices[_id]1765# print ' drawobj_anim.vertices[id_anim]=',drawobj_anim.vertices[id_anim]1766self.vertices[_id] = drawobj_anim.vertices[id_anim] # .copy()1767drawobj_anim.del_drawobj(id_anim)1768self._update_vertexvbo()1769return True17701771def move(self, _id, vertex, vertex_delta):1772# print 'move',self.ident,_id, vertex_delta1773self.vertices[_id] += vertex_delta1774# print ' vertices[id_anim]=',self.vertices[_id]1775self._update_vertexvbo()1776return True17771778def stretch(self, _id, vertex, vertex_delta, ind_vertex):1779# print 'stretch',self.ident,_id,ind_vertex1780# print ' vertex_delta',vertex_delta1781# print ' before vertices[_id]=',self.vertices[_id]1782self.vertices[_id][ind_vertex] += vertex_delta1783# print ' after vertices[_id]=',self.vertices[_id]1784self._update_vertexvbo()1785return True17861787def add_vbo(self, vbo):1788self._vbos[vbo.get_ident()] = vbo17891790def get_vbo(self, ident):1791return self._vbos[ident]17921793def get_vbos(self):1794return self._vbos.values()17951796def del_vbo(self, key):1797del self._vbos[key]17981799def get_n_vert(self):1800return self._n_vert18011802def _get_colors_highl(self, colors):1803return np.clip(colors+self.c_highl.value*np.ones(colors.shape, dtype=np.float32), 0, 1)-colors18041805def set_colors(self, ids, colors, colors_highl=None, is_update=True):1806self.colors[ids] = colors1807if colors_highl is None:1808self.colors_highl[ids] = self._get_colors_highl(colors)1809else:1810self.colors_highl[ids] = colors_highl1811if is_update:1812self._update_colorvbo()18131814def _update_colorvbo(self):1815n = len(self)1816if n == 0:1817for _vbo in self.get_vbos():1818_vbo.destroy()1819#n_vert = self.get_n_vert()1820# print '_update_colorvbo fancyline'18211822if self._is_outline.value:1823colors = self.colors.value + self.are_highlighted.value.reshape(n, 1)*self.colors_highl.value1824for _vbo in self.get_vbos():1825if not _vbo.is_fill():1826_vbo.update_colors(colors)18271828if self._is_fill.value:1829colors = self.colors_fill.value + self.are_highlighted.value.reshape(n, 1)*self.colors_fill_highl.value1830for _vbo in self.get_vbos():1831if _vbo.is_fill():1832_vbo.update_colors(colors)18331834def draw(self, resolution=1.0):1835# print 'draw n=',id(self),self.ident,len(self),self._is_visible.value1836if len(self) == 0:1837return1838if self._is_visible.value:1839glLineWidth(self.linewidth.value)1840glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)1841glEnable(GL_BLEND)18421843# main drawing1844glEnableClientState(GL_VERTEX_ARRAY)1845glEnableClientState(GL_COLOR_ARRAY)18461847# print 'draw',self.format_ident(), self._is_fill.value, self._is_outline.value18481849for _vbo in self.get_vbos():1850_vbo.draw(resolution)18511852# draw handles1853glDisableClientState(GL_VERTEX_ARRAY)1854glDisableClientState(GL_COLOR_ARRAY)18551856def highlight(self, ids, is_update=True):1857# print 'highlight=',ids1858# print ' inds',self._inds1859# print ' inds[ids]=',self._inds[ids]1860if len(ids) > 0:1861self.are_highlighted.value[self._inds[ids]] = True1862is_draw = True1863else:1864is_draw = False18651866if is_update:1867self._update_colorvbo()18681869return is_draw18701871def unhighlight(self, ids=None, is_update=True):18721873if ids is None:1874if np.any(self.are_highlighted.value):1875inds_highl = self._inds # np.flatnonzero(self.are_highlighted.value)1876self.are_highlighted.value[:] = False1877is_draw = True1878else:1879is_draw = False1880else:1881inds_highl = self._inds[ids]1882if np.any(self.are_highlighted.value[inds_highl]):1883self.are_highlighted.value[inds_highl] = False1884is_draw = True1885else:1886is_draw = False18871888# print 'unhighlight' , inds_highl1889# print ' self.are_highlighted.value',self.are_highlighted.value18901891if is_update:1892self._update_colorvbo()1893return is_draw18941895def pick_handle(self, coord):1896"""1897Retuns list [ id, ind_vert] when handle is near coord,1898otherwise []18991900"""1901return []190219031904class Lines(DrawobjMixin):1905def __init__(self, ident, parent, name='Lines',1906is_parentobj=False,1907n_vert=2, # 2 verts for line draw obj1908c_highl=0.3,1909linewidth=3,1910**kwargs):19111912self.init_common(ident, parent=parent, name=name,1913linewidth=linewidth,1914is_parentobj=is_parentobj,1915n_vert=n_vert,1916c_highl=c_highl,1917is_fillable=False,1918**kwargs)19191920# ident of drawobject used for animations1921# must be defined AFTER init_common1922self._ident_drawobj_anim = 'anim_lines'19231924self.add_vbo(Vbo('line', GL_LINES, 2, objtype='outline')) # 2 verts for OGL line element19251926self.add_col(am.ArrayConf('vertices', np.zeros((n_vert, 3), dtype=np.float32),1927dtype=np.float32,1928groupnames=['_private'],1929perm='rw',1930name='Vertex',1931unit='m',1932is_save=True,1933info='Vertex coordinate vectors of points. Example with 2 vertex: [[[x11,y11,z11],[x12,y12,z12]],[[x21,y21,z21],[x22,y22,z122]],...]',1934))19351936def get_boundingbox(self):1937if len(self) == 0:1938return None1939vv = self.get_vertices_array() # self.get_vertices.value1940# TODOD: can be done faster1941return np.array([[np.min(vv[:, :, 0]), np.min(vv[:, :, 1]), np.min(vv[:, :, 2])],1942[np.max(vv[:, :, 0]), np.max(vv[:, :, 1]), np.max(vv[:, :, 2])]1943], float)19441945def add_drawobj(self, vertices, color, color_highl=None, is_update=True):1946if color_highl is None:1947colors_highl = self._get_colors_highl(np.array([color]))19481949_id = self.add_row(vertices=vertices,1950colors=color,1951colors_highl=colors_highl[0],1952)1953if is_update:1954self._update_vertexvbo()1955self._update_colorvbo()1956return _id19571958def add_drawobjs(self, vertices, colors, colors_highl=None, is_update=True):1959if colors_highl is None:1960colors_highl = self._get_colors_highl(colors)19611962ids = self.add_rows(len(vertices),1963vertices=vertices,1964colors=colors,1965colors_highl=colors_highl,1966)1967if is_update:1968self._update_vertexvbo()1969self._update_colorvbo()1970return ids19711972def _update_vertexvbo(self):1973self.get_vbo('line').update_vertices(self.get_vertices_array().reshape((-1, 6)), len(self))19741975def _make_handlevbo(self, x, y, resolution):1976# print '_get_handlevbo'1977# print ' x =\n',x1978# print ' y =\n',y1979dx = resolution * 5.01980dy = resolution * 5.01981z = np.zeros(x.shape, dtype=np.float32)1982n = len(z)1983hvertices = np.concatenate((x-dx, y-dy, z, x+dx, y-dy, z, x+dx, y+dy, z, x-dx, y+dy, z, ), 1).reshape(-1, 4, 3)1984# print ' hvertices =\n',hvertices1985self._vertexvbo_handles = vbo.VBO(hvertices.reshape((-1, 3)))1986self._indexvbo_handles = vbo.VBO(np.arange(4*n, dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)19871988colors = np.repeat(np.array([[0.9, 0.8, 0.7, 0.5]], dtype=np.float32), n, 0)1989self._colorvbo_handles = vbo.VBO(colors[np.array(np.arange(0, n, 1.0/4), int)])19901991def pick(self, p, detectwidth=0.1):1992"""1993Returns a binary vector which is True values for lines that have been selected1994by point p.19951996In particular, an element of this vector is True if the minimum distance1997between the respective line to point p is less than detectwidth1998"""1999# print 'pick',self.get_ident(),len(self)2000if len(self) == 0:2001return np.array([], np.int)20022003vertices = self.get_vertices_array()2004# print ' vertices',vertices2005x1 = vertices[:, 0, 0]2006y1 = vertices[:, 0, 1]20072008x2 = vertices[:, 1, 0]2009y2 = vertices[:, 1, 1]20102011return self._ids[get_dist_point_to_segs(p, x1, y1, x2, y2, is_ending=True) < detectwidth**2]20122013def pick_handle(self, coord, detectwidth=0.1):2014"""2015Retuns list [ id, ind_vert] when handle is near coord,2016otherwise []20172018"""2019# print 'pick_handle',self.get_ident(),len(self)2020dw = detectwidth**220212022if len(self) == 0:2023return np.zeros((0, 2), np.int)20242025if self.ident not in ['lines', 'fancylines']:2026return np.zeros((0, 2), np.int)20272028vertices = self.get_vertices_array()2029handles = []2030# print ' vertices',vertices2031# print ' vertices.shape',vertices.shape2032dx = vertices[:, 0, 0]-coord[0]2033dy = vertices[:, 0, 1]-coord[1]20342035ids = self._ids[dx*dx+dy*dy < dw]2036handle1 = np.ones((len(ids), 2), np.int)2037handle1[:, 0] = ids2038handle1[:, 1] = 02039# print ' ',d,handle120402041dx = vertices[:, 1, 0]-coord[0]2042dy = vertices[:, 1, 1]-coord[1]2043ids = self._ids[dx*dx+dy*dy < dw]2044handle2 = np.ones((len(ids), 2), np.int)2045handle2[:, 0] = ids2046handle2[:, 1] = 12047# print ' ',d,handle22048handles = np.concatenate((handle1, handle2), 0)20492050return handles20512052def draw_old_handles(self, resolution=1.0):2053# print 'draw n=',len(self)2054glLineWidth(self.linewidth.value)20552056glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)2057glEnable(GL_BLEND)20582059# main drawing2060glEnableClientState(GL_VERTEX_ARRAY)2061glEnableClientState(GL_COLOR_ARRAY)20622063self._colorvbo.bind()2064glColorPointer(4, GL_FLOAT, 0, None)20652066self._vertexvbo.bind()2067self._indexvbo.bind()2068glVertexPointer(3, GL_FLOAT, 0, None)20692070glDrawElements(GL_LINES, self._n_vert*len(self), GL_UNSIGNED_INT, None)20712072glDisableClientState(GL_VERTEX_ARRAY)2073glDisableClientState(GL_COLOR_ARRAY)2074self._vertexvbo.unbind()2075self._indexvbo.unbind()2076self._colorvbo.unbind()20772078# draw handles2079if 1:2080vertices = self.vertices.value2081x1 = vertices[:, 0, 0]2082y1 = vertices[:, 0, 1]20832084x2 = vertices[:, 1, 0]2085y2 = vertices[:, 1, 1]2086self._make_handlevbo(x2.reshape(-1, 1), y2.reshape(-1, 1), resolution)20872088glLineWidth(2)2089glEnableClientState(GL_VERTEX_ARRAY)2090glEnableClientState(GL_COLOR_ARRAY)20912092self._colorvbo_handles.bind()2093glColorPointer(4, GL_FLOAT, 0, None)20942095self._vertexvbo_handles.bind()2096self._indexvbo_handles.bind()2097glVertexPointer(3, GL_FLOAT, 0, None)20982099# GL_LINE_STRIP, GL_QUADS, GL_LINES, GL_LINE_LOOP, GL_POINTS2100glDrawElements(GL_QUADS, 4*len(self), GL_UNSIGNED_INT, None)21012102glDisableClientState(GL_VERTEX_ARRAY)2103glDisableClientState(GL_COLOR_ARRAY)2104self._vertexvbo_handles.unbind()2105self._indexvbo_handles.unbind()2106self._colorvbo_handles.unbind()210721082109class Rectangles(Lines):2110def __init__(self, ident, parent, name='Rectangles',2111is_parentobj=False,2112is_fill=True,2113is_outline=True, # currently only fill implemented2114c_highl=0.3,2115linewidth=3,2116**kwargs):21172118self.init_common(ident, parent=parent, name=name,2119linewidth=linewidth, # for outline only2120is_parentobj=is_parentobj,2121is_fill=is_fill,2122is_outline=is_outline,2123n_vert=1, # vertex points for ending2124c_highl=c_highl,2125**kwargs)21262127# ident of drawobject used for animations2128# must be defined AFTER init_common2129self._ident_drawobj_anim = 'anim_rectangles'21302131# if is_outline:2132# self.add_vbo(Vbo('outline',GL_LINES,2, noncyclic = 0))21332134if is_fill:2135self.add_vbo(Vbo('rectangle_filled', GL_QUADS, 4, objtype='fill'))2136if is_outline:2137self.add_vbo(Vbo('rectangle_outline', GL_LINES, 2, objtype='outline'))21382139self.add_col(am.ArrayConf('offsets', np.zeros(3, dtype=np.float32),2140dtype=np.float32,2141groupnames=['_private'],2142perm='rw',2143name='Offset',2144unit='m',2145is_save=True,2146info='Offset of lower left corner',2147))21482149self.add_col(am.ArrayConf('widths', 0.5,2150dtype=np.float32,2151groupnames=['option'],2152perm='rw',2153name='Width',2154unit='m',2155is_save=True,2156info='Rectangle width',2157))21582159self.add_col(am.ArrayConf('lengths', 0.5,2160dtype=np.float32,2161groupnames=['option'],2162perm='rw',2163name='length',2164unit='m',2165is_save=True,2166info='Rectangle length',2167))21682169self.add_col(am.ArrayConf('rotangles_xy', 0.0,2170dtype=np.float32,2171groupnames=['option'],2172perm='rw',2173name='xy rot. angle',2174is_save=True,2175info='Counter clockwise rotation angle in xy plane',2176))21772178def add_drawobj(self, offset, width, length, rotangle_xy,2179color, color_fill=None,2180color_highl=None, color_fill_highl=None,2181is_update=True):2182# print 'Fancylines.add_drawobj'2183if color_highl is None:2184color_highl = self._get_colors_highl(np.array([color]))[0]21852186if color_fill is None:2187color_fill = color21882189if color_fill_highl is None:2190color_fill_highl = self._get_colors_highl(np.array([color_fill]))[0]21912192# print ' ids',self.get_ids()2193_id = self.add_row(offsets=offset,2194widths=width,2195lengths=length,2196rotangles_xy=rotangle_xy,2197colors=color,2198colors_highl=color_highl,2199colors_fill=color_fill,2200colors_fill_highl=color_fill_highl,2201)2202if is_update:2203self._update_vertexvbo()2204self._update_colorvbo()2205return _id22062207def add_drawobjs(self, offsets, widths, lengths, rotangles_xy,2208colors, colors_fill=None,2209colors_highl=None, colors_fill_highl=None,2210is_update=True):2211# print 'add_drawobjs'2212if colors_highl is None:2213colors_highl = self._get_colors_highl(colors)22142215n = len(offsets)2216if colors_fill_highl is None:2217colors_fill_highl = self._get_colors_highl(colors_fill)2218ids = self.add_rows(n,2219offsets=offsets,2220widths=widths,2221lengths=lengths,2222rotangles_xy=rotangles_xy,2223colors=colors,2224colors_highl=colors_highl,2225colors_fill=colors_fill,2226colors_fill_highl=colors_fill_highl,2227)2228# self.print_attrs()2229if is_update:2230self._update_vertexvbo()2231self._update_colorvbo()2232return ids22332234def begin_animation(self, id_target):22352236self._id_target = id_target2237self._drawobj_anim = self.parent.get_drawobj_by_ident(self._ident_drawobj_anim)2238self.id_anim = self._drawobj_anim.add_drawobj(1.0*self.offsets[id_target],22391.0*self.widths[id_target],22401.0*self.lengths[id_target],22411.0*self.rotangles_xy[id_target],2242color=self.color_anim.value,2243)2244# print 'begin_animation',self.ident,_id,self._drawobj_anim2245return True22462247def end_animation(self, is_del_last_vert=False):2248# print 'end_animation',self.ident,self._id_target2249# print ' verices =',self._drawobj_anim.vertices[self.id_anim]2250self.set_offsets(self._id_target, self._drawobj_anim.get_offsets(self.id_anim)) # .copy()2251self.del_animation()2252# self._drawobj_anim.del_drawobj(self.id_anim)2253self._update_vertexvbo()2254self._update_colorvbo()2255return True22562257def set_anim(self, _id, drawobjelem_anim):2258# print 'set_anim',self.ident,_id,drawobjelem_anim2259(drawobj_anim, id_anim) = drawobjelem_anim2260# print ' self.vertices[_id]=',self.vertices[_id]2261# print ' drawobj_anim.vertices[id_anim]=',drawobj_anim.vertices[id_anim]2262self.vertices[_id] = drawobj_anim.vertices[id_anim] # .copy()2263drawobj_anim.del_drawobj(id_anim)2264self._update_vertexvbo()2265return True22662267def move(self, _id, vertex, vertex_delta):2268# print 'move',self.ident,_id, vertex_delta2269self.offsets[_id] += vertex_delta2270# print ' vertices[id_anim]=',self.vertices[_id]2271self._update_vertexvbo()2272return True22732274def stretch(self, _id, vertex, vertex_delta, ind_vertex):2275# print 'stretch',self.ident,_id,ind_vertex2276# print ' vertex_delta',vertex_delta2277# print ' before vertices[_id]=',self.vertices[_id]2278#self.vertices[_id][ind_vertex] += vertex_delta2279# print ' after vertices[_id]=',self.vertices[_id]2280self._update_vertexvbo()2281return True22822283def get_offsets_array(self):2284return self.offsets.value22852286def get_offsets(self, ids):2287return self.offsets[ids]22882289def set_offsets(self, ids, values):2290self.offsets[ids] = values22912292def get_widths_array(self):2293return self.widths.value22942295def get_widths(self, ids):2296return self.widths[ids]22972298def set_widths(self, ids, values):2299self.widths[ids] = values23002301def get_lengths_array(self):2302return self.lengths.value23032304def get_lengths(self, ids):2305return self.lengths[ids]23062307def set_lengths(self, ids, values):2308self.lengths[ids] = values23092310def get_rotangles_xy_array(self):2311return self.rotangles_xy.value23122313def get_rotangles_xy(self, ids):2314return self.rotangles_xy[ids]23152316def set_rotangles_xy(self, ids, values):2317self.rotangles_xy[ids] = values23182319def _update_vertexvbo(self):2320# print '_update_vertexvbo',self.format_ident()2321self._make_lines()2322n = len(self)2323if self.is_fill():2324self.get_vbo('rectangle_filled').update_vertices(self._vertices, n)2325if self.is_outline():2326self.get_vbo('rectangle_outline').update_vertices(self._linevertices, n)23272328def _make_lines(self):2329# print '_make_lines'23302331vertices = self.get_vertices_array()23322333n = len(self)2334n_lpe = 4 # lines per element (here 4 lines for a rectangle)2335n_lines_tot = n*n_lpe23362337linevertices = np.zeros((n, 2*n_lpe, 3), np.float32)23382339# fix first and last point of each rectangle2340linevertices[:, 0, :] = vertices[:, 0, :]2341linevertices[:, -1, :] = vertices[:, 0, :]2342# do rest of the vertices by doubling orginal2343linevertices[:, 1:-1, :] = np.repeat(vertices[:, 1:, :], 2, 1)2344# print ' linevertices\n',linevertices23452346#vertexinds = np.zeros((n_lines_tot,2),np.int32)2347inds = self.get_inds()2348vertexinds = np.repeat(inds, 2*n_lpe).reshape((n_lines_tot, 2))2349# print ' vertexinds\n',vertexinds2350#rectinds = np.zeros(n_lines_tot,np.int32)2351rectinds = np.repeat(inds, n_lpe)23522353self._vertices = vertices2354self._linevertices = linevertices.reshape((2*n_lines_tot, 3))2355# print ' self._linevertices',self._linevertices2356self._rectinds = rectinds2357self._vertexinds = vertexinds23582359def get_vertices_array(self):2360# print 'Rectangles.get_vertices_array'2361n = len(self)2362offsets = self.get_offsets_array()2363widths = self.get_widths_array()2364lengths = self.get_lengths_array()2365alphas = self.get_rotangles_xy_array()2366# print 'widths',widths2367# print 'lengths',lengths2368# print ' alphas',alphas2369sin_alphas = np.sin(alphas)2370cos_alphas = np.cos(alphas)23712372zeros = np.zeros(n, np.float32)2373vertices = np.zeros((n, 4, 3), np.float32)23742375vertices[:, 0, :] = offsets2376vertices[:, 1, :] = offsets2377vertices_rot = rotate_vertices(widths, zeros,2378sin_alphas=sin_alphas,2379cos_alphas=cos_alphas,2380is_array=True,2381)23822383# print ' vertices_rot = ',vertices_rot.shape,vertices_rot,2384vertices[:, 1, :2] += rotate_vertices(widths, zeros,2385sin_alphas=sin_alphas,2386cos_alphas=cos_alphas,2387is_array=True,2388)23892390vertices[:, 2, :] = offsets2391vertices[:, 2, :2] += rotate_vertices(widths, lengths,2392sin_alphas=sin_alphas,2393cos_alphas=cos_alphas,2394is_array=True,2395)23962397vertices[:, 3, :] = offsets2398vertices[:, 3, :2] += rotate_vertices(zeros, lengths,2399sin_alphas=sin_alphas,2400cos_alphas=cos_alphas,2401is_array=True,2402)24032404return vertices24052406def pick(self, p, detectwidth=0.1):2407"""2408Returns a binary vector which is True values for lines that have been selected2409by point p.24102411"""2412# print 'pick'2413if len(self) == 0:2414return np.array([], np.int)24152416vertices = self.get_vertices_array()2417# print ' vertices.shape',vertices.shape,'\n',vertices2418inds1 = is_inside_triangles(p, vertices[:, 0, 0], vertices[:, 0, 1],2419vertices[:, 1, 0], vertices[:, 1, 1],2420vertices[:, 2, 0], vertices[:, 2, 1])24212422inds2 = is_inside_triangles(p, vertices[:, 0, 0], vertices[:, 0, 1],2423vertices[:, 2, 0], vertices[:, 2, 1],2424vertices[:, 3, 0], vertices[:, 3, 1])24252426return self._ids[np.flatnonzero(inds1 | inds2)]242724282429class Triangles(Lines):2430def __init__(self, ident, parent, name='Triangles',2431is_parentobj=False,2432is_fill=True,2433is_outline=True, # currently only fill implemented2434c_highl=0.3,2435linewidth=3,2436**kwargs):24372438n_vert = 3 # 3 verts for triangle draw obj2439self.init_common(ident, parent=parent, name=name,2440linewidth=linewidth, # for outline only2441is_parentobj=is_parentobj,2442is_fill=is_fill,2443is_outline=is_outline,2444n_vert=n_vert,2445c_highl=c_highl,2446**kwargs)24472448# ident of drawobject used for animations2449# must be defined AFTER init_common2450self._ident_drawobj_anim = 'anim_triangles'24512452# if is_outline:2453# self.add_vbo(Vbo('outline',GL_LINES,2, noncyclic = 0))24542455if is_fill:2456self.add_vbo(Vbo('triangle_filled', GL_TRIANGLES, 3, objtype='fill'))2457if is_outline:2458self.add_vbo(Vbo('triangle_outline', GL_LINES, 2, objtype='outline'))24592460self.add_col(am.ArrayConf('vertices', np.zeros((n_vert, 3), dtype=np.float32),2461dtype=np.float32,2462groupnames=['_private'],2463perm='rw',2464name='Vertex',2465unit='m',2466is_save=True,2467info='Triangle vertex coordinate vectors of points: [[[x11,y11,z11],[x12,y12,z12],[x13,y13,z13]],[[x21,y21,z21],[x22,y22,z122],[x13,y13,z13]],...]',2468))24692470def add_drawobj(self, vertex,2471color, color_fill=None,2472color_highl=None, color_fill_highl=None,2473is_update=True):2474# print 'Fancylines.add_drawobj'2475if color_highl is None:2476color_highl = self._get_colors_highl(np.array([color]))[0]24772478if color_fill is None:2479color_fill = color24802481if color_fill_highl is None:2482color_fill_highl = self._get_colors_highl(np.array([color_fill]))[0]24832484# print ' ids',self.get_ids()2485_id = self.add_row(vertices=vertex,2486colors=color,2487colors_highl=color_highl,2488colors_fill=color_fill,2489colors_fill_highl=color_fill_highl,2490)2491if is_update:2492self._update_vertexvbo()2493self._update_colorvbo()2494return _id24952496def add_drawobjs(self, vertices,2497colors, colors_fill=None,2498colors_highl=None, colors_fill_highl=None,2499is_update=True):2500# print 'add_drawobjs'2501if colors_highl is None:2502colors_highl = self._get_colors_highl(colors)25032504n = len(vertices)2505if colors_fill_highl is None:2506colors_fill_highl = self._get_colors_highl(colors_fill)2507ids = self.add_rows(n,2508vertices=vertices,2509colors=colors,2510colors_highl=colors_highl,2511colors_fill=colors_fill,2512colors_fill_highl=colors_fill_highl,2513)2514# self.print_attrs()2515if is_update:2516self._update_vertexvbo()2517self._update_colorvbo()2518return ids25192520def _update_vertexvbo(self):2521if self.is_fill():2522self.get_vbo('triangle_filled').update_vertices(self.get_vertices_array().reshape((-1, 3*3)), len(self))2523if self.is_outline():2524self.get_vbo('triangle_outline').update_vertices(self._get_linevertices(), len(self))25252526def _get_linevertices(self):2527# print '_make_lines'25282529vertices = self.get_vertices_array()25302531n = len(self)2532n_lpe = 3 # lines per element (here 4 lines for a rectangle)2533n_lines_tot = n*n_lpe25342535linevertices = np.zeros((n, 2*n_lpe, 3), np.float32)25362537# fix first and last point of each rectangle2538linevertices[:, 0, :] = vertices[:, 0, :]2539linevertices[:, -1, :] = vertices[:, 0, :]2540# do rest of the vertices by doubling orginal2541linevertices[:, 1:-1, :] = np.repeat(vertices[:, 1:, :], 2, 1)2542# print ' linevertices\n',linevertices25432544#vertexinds = np.zeros((n_lines_tot,2),np.int32)2545#inds = self.get_inds()2546#vertexinds = np.repeat(inds,2*n_lpe).reshape((n_lines_tot,2))2547# print ' vertexinds\n',vertexinds2548#rectinds = np.zeros(n_lines_tot,np.int32)2549#rectinds = np.repeat(inds,n_lpe)25502551#self._vertices = vertices2552return linevertices.reshape((2*n_lines_tot, 3))2553# print ' self._linevertices',self._linevertices2554#self._rectinds = rectinds2555#self._vertexinds = vertexinds25562557def pick(self, p, detectwidth=0.1):2558"""2559Returns a binary vector which is True values for lines that have been selected2560by point p.25612562"""2563# print 'pick'2564if len(self) == 0:2565return np.array([], np.int)25662567vertices = self.get_vertices_array()2568# print ' vertices.shape',vertices.shape,'\n',vertices2569inds = is_inside_triangles(p, vertices[:, 0, 0], vertices[:, 0, 1],2570vertices[:, 1, 0], vertices[:, 1, 1],2571vertices[:, 2, 0], vertices[:, 2, 1])25722573return self._ids[np.flatnonzero(inds)]25742575def pick_handle(self, coord, detectwidth=0.1):2576"""2577Retuns list [ id, ind_vert] when handle is near coord,2578otherwise []25792580"""2581# print 'Triangles.pick_handle',self.get_ident(),len(self)2582dw = detectwidth**225832584if len(self) == 0:2585return np.zeros((0, 2), np.int)25862587vertices = self.get_vertices_array()2588handles = []2589# print ' vertices',vertices2590# print ' vertices.shape',vertices.shape2591dx = vertices[:, 0, 0]-coord[0]2592dy = vertices[:, 0, 1]-coord[1]25932594ids = self._ids[dx*dx+dy*dy < dw]2595handle1 = np.ones((len(ids), 2), np.int)2596handle1[:, 0] = ids2597handle1[:, 1] = 02598# print ' ',d,handle125992600dx = vertices[:, 1, 0]-coord[0]2601dy = vertices[:, 1, 1]-coord[1]2602ids = self._ids[dx*dx+dy*dy < dw]2603handle2 = np.ones((len(ids), 2), np.int)2604handle2[:, 0] = ids2605handle2[:, 1] = 126062607dx = vertices[:, 2, 0]-coord[0]2608dy = vertices[:, 2, 1]-coord[1]2609ids = self._ids[dx*dx+dy*dy < dw]2610handle3 = np.ones((len(ids), 2), np.int)2611handle3[:, 0] = ids2612handle3[:, 1] = 226132614# print ' ',d,handle22615handles = np.concatenate((handle1, handle2, handle3), 0)26162617return handles261826192620class Fancylines(Lines):2621def __init__(self, ident, parent, name='Fancy lines',2622is_parentobj=False,2623is_fill=True,2624is_outline=False, # currently only fill implemented2625arrowstretch=2.5,2626arrowlength=0.5,2627is_lefthalf=True,2628is_righthalf=True,2629c_highl=0.3,2630linewidth=3,2631**kwargs):26322633self.init_common(ident, parent=parent, name=name,2634linewidth=linewidth, # for outline only2635is_parentobj=is_parentobj,2636is_fill=is_fill,2637is_outline=is_outline,2638n_vert=3, # vertex points for ending2639c_highl=c_highl,2640**kwargs)26412642# ident of drawobject used for animations2643# must be defined AFTER init_common2644self._ident_drawobj_anim = 'anim_fancylines'26452646# if is_outline:2647# self.add_vbo(Vbo('outline',GL_LINES,2, noncyclic = 0))26482649if is_fill:2650self.add_vbo(Vbo('line_fill', GL_QUADS, 4, objtype='fill'))2651for style in LINEHEADS.keys():2652self.add_vbo(Vbo(('begin', 'fill', style), GL_TRIANGLES, 3, objtype='fill'))2653self.add_vbo(Vbo(('end', 'fill', style), GL_TRIANGLES, 3, objtype='fill'))26542655self.add(cm.AttrConf('arrowstretch', arrowstretch,2656groupnames=['options'],2657perm='wr',2658is_save=True,2659is_plugin=False,2660name='Arrow stretch',2661info='Arrow stretch factor.',2662))26632664# self.add(cm.AttrConf( 'arrowlength', arrowlength,2665# groupnames = ['options'],2666# perm='wr',2667# is_save = True,2668# is_plugin = False,2669# name = 'Arrow length',2670# info = 'Arrow length.',2671# ))26722673self.add(cm.AttrConf('is_lefthalf', is_lefthalf,2674groupnames=['options'],2675perm='wr',2676is_save=True,2677is_plugin=False,2678name='Show left',2679info='Show left half of line.',2680))26812682self.add(cm.AttrConf('is_righthalf', is_righthalf,2683groupnames=['options'],2684perm='wr',2685is_save=True,2686is_plugin=False,2687name='Show right',2688info='Show right half of line.',2689))26902691self.add_col(am.ArrayConf('beginstyles', 0,2692groupnames=['options'],2693perm='rw',2694choices=LINEHEADS,2695is_save=True,2696is_plugin=False,2697name='Begin style',2698info='Style of the line extremity at the beginning.',2699))27002701self.add_col(am.ArrayConf('endstyles', 0,2702groupnames=['options'],2703perm='rw',2704choices=LINEHEADS,2705is_save=True,2706is_plugin=False,2707name='End style',2708info='Style of the line extremity at the ending.',2709))27102711self.add_col(am.ArrayConf('vertices', np.zeros((2, 3), dtype=np.float32),2712dtype=np.float32,2713groupnames=['_private'],2714perm='rw',2715name='Vertex',2716unit='m',2717is_save=True,2718info='Vertex coordinate vectors of points. Example with 2 vertex: [[[x11,y11,z11],[x12,y12,z12]],[[x21,y21,z21],[x22,y22,z122]],...]',2719))27202721self.add_col(am.ArrayConf('widths', 0.5,2722dtype=np.float32,2723groupnames=['option'],2724perm='rw',2725name='Width',2726unit='m',2727is_save=True,2728info='Line width',2729))27302731def add_drawobj(self, vertices, width, color, color_highl=None,2732beginstyle=None,2733endstyle=None,2734is_update=True):2735# print 'Fancylines.add_drawobj'2736if color_highl is None:2737color_highl = self._get_colors_highl(np.array([color]))[0]27382739# print ' ids',self.get_ids()2740_id = self.add_row(vertices=vertices,2741widths=width,2742colors=color,2743colors_highl=color_highl,2744colors_fill=color,2745colors_fill_highl=color_highl,2746beginstyles=beginstyle,2747endstyles=endstyle,27482749)2750if is_update:2751self._update_vertexvbo()2752self._update_colorvbo()2753return _id27542755def add_drawobjs(self, vertices, widths, colors, colors_highl=None,2756beginstyles=None, endstyles=None,2757is_update=True):27582759if colors_highl is None:2760colors_highl = self._get_colors_highl(colors)27612762n = len(vertices)2763if beginstyles is None:2764beginstyles = np.zeros(n)2765if endstyles is None:2766endstyles = np.zeros(n)2767ids = self.add_rows(len(vertices),2768vertices=vertices,2769widths=widths,2770colors=colors,2771colors_highl=colors_highl,2772colors_fill=colors,2773colors_fill_highl=colors_highl,2774beginstyles=beginstyles,2775endstyles=endstyles,2776)2777if is_update:2778self._update_vertexvbo()2779self._update_colorvbo()2780return ids27812782def begin_animation(self, id_target):27832784self._id_target = id_target2785self._drawobj_anim = self.parent.get_drawobj_by_ident(self._ident_drawobj_anim)2786self.id_anim = self._drawobj_anim.add_drawobj(np.array(self.get_vertices(id_target)),27871.0*self.get_widths(id_target),2788self.color_anim.value,2789beginstyle=self.beginstyles[id_target],2790endstyle=self.endstyles[id_target],2791)2792# print 'begin_animation',self.ident,_id,self._drawobj_anim2793return True27942795def get_widths_array(self):2796return self.widths.value27972798def get_widths(self, ids):2799return self.widths[ids]28002801def set_widths(self, ids, values):2802self.widths[ids] = values28032804def _update_vertexvbo(self):2805# print '_update_vertexvbo',self.format_ident()28062807vertices = self.get_vertices_array()2808x1 = vertices[:, 0, 0]2809y1 = vertices[:, 0, 1]2810z1 = vertices[:, 0, 2]28112812x2 = vertices[:, 1, 0]2813y2 = vertices[:, 1, 1]2814z2 = vertices[:, 1, 2]2815dx = x2-x12816dy = y2-y12817alpha_xy = np.arctan2(dy, dx)2818length_xy = np.sqrt(dx*dx + dy*dy)2819halfwidth = 0.5*self.get_widths_array()2820x1_new = x1.copy()2821y1_new = y1.copy()2822x2_new = x2.copy()2823y2_new = y2.copy()2824# print ' origvert'2825# print ' x1_new=',x1_new,x1_new.dtype2826# print ' x2_new=',x2_new,x2_new.dtype2827if self._is_fill.value:2828for style, id_style in LINEHEADS.iteritems():28292830# begin2831inds_style = np.flatnonzero(self.beginstyles.value == id_style)28322833if len(inds_style) > 0:28342835# print ' style',style,len(inds_style)2836# print ' x1_new=',x1_new,x1_new.dtype2837# print ' x2_new=',x2_new,x2_new.dtype2838self._update_vertexvbo_begin_fill(style, inds_style, x1_new, y1_new,2839z1, x2, y2, z2, length_xy, alpha_xy, halfwidth)28402841# end2842inds_style = np.flatnonzero(self.endstyles.value == id_style)2843if len(inds_style) > 0:2844self._update_vertexvbo_end_fill(style, inds_style, x1, y1, z1, x2_new,2845y2_new, z2, length_xy, alpha_xy, halfwidth)28462847self._update_vertexvbo_line_fill(x1_new, y1_new, z1, x2_new, y2_new, z2,2848length_xy, alpha_xy, halfwidth, len(self))28492850def _update_vertexvbo_line_fill(self, x1, y1, z1, x2, y2, z2, length_xy, alpha_xy, halfwidth, n):2851# print '_update_vertexvbo_line_fill'2852# this allows different color indexing for polyline2853# TODO n2854# if inds_colors is None:2855#n = len(self)2856# else:2857# n = None28582859#n_vert = self.get_n_vert()2860#dphi = np.pi/(n_vert-1)28612862#beta = alpha_xy+np.pi/22863# print ' alpha_xy\n',alpha_xy/np.pi*1802864# print ' halfwidth\n',halfwidth2865# print ' x1\n',x12866# print ' length_xy=',length_xy2867# print ' length_xy-self.widths.value=',(length_xy-self.widths.value)28682869# self.is_righthalf.value2870xr1 = x1 + self.is_lefthalf.value * halfwidth * np.cos(alpha_xy+np.pi/2)2871yr1 = y1 + self.is_lefthalf.value * halfwidth * np.sin(alpha_xy+np.pi/2)28722873xr2 = x2 + self.is_lefthalf.value * halfwidth * np.cos(alpha_xy+np.pi/2)2874yr2 = y2 + self.is_lefthalf.value * halfwidth * np.sin(alpha_xy+np.pi/2)28752876xr3 = x2 + self.is_righthalf.value * halfwidth * np.cos(alpha_xy-np.pi/2)2877yr3 = y2 + self.is_righthalf.value * halfwidth * np.sin(alpha_xy-np.pi/2)28782879xr4 = x1 + self.is_righthalf.value * halfwidth * np.cos(alpha_xy-np.pi/2)2880yr4 = y1 + self.is_righthalf.value * halfwidth * np.sin(alpha_xy-np.pi/2)28812882# print '_update_vertexvbo ',n,n_vert,self._is_fill.value2883# print ' x\n',x2884# print ' y\n',y2885# print ' z\n',z2886n_vpe = 42887vertices = np.zeros((len(xr1), n_vpe * 3), dtype=np.float32)28882889vertices[:, 0] = xr12890vertices[:, 1] = yr12891vertices[:, 2] = z128922893vertices[:, 3] = xr22894vertices[:, 4] = yr22895vertices[:, 5] = z228962897vertices[:, 6] = xr32898vertices[:, 7] = yr32899vertices[:, 8] = z229002901vertices[:, 9] = xr42902vertices[:, 10] = yr42903vertices[:, 11] = z129042905# print ' vertices=\n',vertices2906self.get_vbo('line_fill').update_vertices(vertices, n)29072908#self._vertexvbo_fill = vbo.VBO(vertices.reshape((-1,3)))2909#self._indexvbo_fill = vbo.VBO(np.arange(self._n_vert*self._n_elem_fill, dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)29102911def _update_vertexvbo_begin_fill(self, style, inds_style, x1_new, y1_new, z1, x2, y2, z2, length_xy, alpha_xy, halfwidth):2912ident_vbo = ('begin', 'fill', style)2913headvbo = self.get_vbo(ident_vbo)2914# print '_update_vertexvbo_begin_fill'29152916n = len(inds_style)2917alphastretch = 1.02918n_vert = 62919if style == 'bevel':2920n_vert = 62921arrowstretch = 1.029222923if style == 'triangle':2924n_vert = 32925arrowstretch = self.arrowstretch.value29262927if style == 'arrow':2928n_vert = 32929alphastretch = 1.22930arrowstretch = self.arrowstretch.value2931radius = arrowstretch*halfwidth[inds_style]2932if style != 'bevel':2933x1_new[inds_style] = x2[inds_style] - (length_xy[inds_style]-radius)*np.cos(alpha_xy[inds_style])2934y1_new[inds_style] = y2[inds_style] - (length_xy[inds_style]-radius)*np.sin(alpha_xy[inds_style])29352936# print ' x1_new=',x1_new,x1_new.dtype,halfwidth[inds_style]2937# print ' y1_new=',y1_new,y1_new.dtype29382939if self.is_righthalf.value:2940alpha_end = np.pi/22941else:2942n_vert = int(0.5*n_vert+0.5)2943alpha_end = 0.029442945if self.is_lefthalf.value:2946alpha_start = -np.pi/22947else:2948n_vert = int(0.5*n_vert+0.5)2949alpha_start = 0.029502951dphi = (alpha_end-alpha_start)/(n_vert-1)2952alphas = alpha_xy[inds_style]+(alphastretch*np.arange(alpha_start, alpha_end+dphi, dphi)+np.pi).reshape(-1, 1)29532954# print ' alpha_xy\n',alpha_xy/np.pi*1802955# print ' alphas=alpha0+phi\n',alphas/np.pi*18029562957x = np.cos(alphas) * radius + x1_new[inds_style]2958y = np.sin(alphas) * radius + y1_new[inds_style]29592960z = np.ones((n_vert, 1)) * z1[inds_style]29612962# print '_update_vertexvbo ',n,n_vert,self._is_fill.value2963# print ' x\n',x2964# print ' y\n',y2965# print ' z\n',z29662967# print '_update_vertexvbo_fill',n,len(x),n_vert,self._n_vpe_fill2968xf = x.transpose().flatten() # +0.52969yf = y.transpose().flatten() # +0.52970zf = z.transpose().flatten()2971xcf = (np.ones((n_vert, 1)) * x1_new[inds_style]).transpose().flatten()2972ycf = (np.ones((n_vert, 1)) * y1_new[inds_style]).transpose().flatten()2973# print ' xcf\n',xcf2974# print ' ycf\n',ycf29752976# create and compose main vertices array2977n_elem_fill = (n_vert-1)*n29782979n_vpe = headvbo.get_vpe()2980# print ' n_elem_fill ',self._n_elem_fill2981# print ' n_vpe',n_vpe2982vertices = np.zeros((n_elem_fill, n_vpe * 3), dtype=np.float32)2983# print ' vertices.reshape((-1,3)).shape',vertices.reshape((-1,3)).shape2984#zf = z.transpose().flatten()29852986ind = np.arange(0, n*n_vert).reshape(n, n_vert)[:, :-1].flatten()29872988vertices[:, 0] = xf[ind]2989vertices[:, 1] = yf[ind]2990vertices[:, 2] = zf[ind]29912992vertices[:, 3] = xcf[ind]2993vertices[:, 4] = ycf[ind]2994vertices[:, 5] = zf[ind]29952996ind2 = np.arange(0, n*n_vert).reshape(n, n_vert)[:, 1:].flatten()2997vertices[:, 6] = xf[ind2]2998vertices[:, 7] = yf[ind2]2999vertices[:, 8] = zf[ind2]3000# print ' vertices=\n',vertices3001headvbo.update_vertices(vertices, inds=inds_style)30023003#self._vertexvbo_fill = vbo.VBO(vertices.reshape((-1,3)))3004#self._indexvbo_fill = vbo.VBO(np.arange(self._n_vert*self._n_elem_fill, dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)30053006def _update_vertexvbo_end_fill(self, style, inds_style, x1, y1, z1, x2_new, y2_new, z2, length_xy, alpha_xy, halfwidth):3007ident_vbo = ('end', 'fill', style)3008headvbo = self.get_vbo(ident_vbo)3009# print '_update_vertexvbo_end_fill',style30103011n = len(inds_style)3012alphastretch = 1.03013n_vert = 63014arrowstretch = 1.03015if style == 'bevel':3016n_vert = 630173018if style == 'triangle':3019n_vert = 33020arrowstretch = self.arrowstretch.value30213022if style == 'arrow':3023n_vert = 33024alphastretch = 1.23025arrowstretch = self.arrowstretch.value3026radius = arrowstretch*halfwidth[inds_style]30273028if style != 'bevel':3029x2_new[inds_style] = x1[inds_style] + (length_xy[inds_style]-radius)*np.cos(alpha_xy[inds_style])3030y2_new[inds_style] = y1[inds_style] + (length_xy[inds_style]-radius)*np.sin(alpha_xy[inds_style])30313032if self.is_lefthalf.value:3033alpha_end = np.pi/23034else:3035n_vert = int(0.5*n_vert+0.5)3036alpha_end = 0.030373038if self.is_righthalf.value:3039alpha_start = -np.pi/23040else:3041n_vert = int(0.5*n_vert+0.5)3042alpha_start = 0.030433044dphi = (alpha_end-alpha_start)/(n_vert-1)3045alphas = alpha_xy[inds_style]+alphastretch*np.arange(alpha_start, alpha_end+dphi, dphi).reshape(-1, 1)30463047dphi = np.pi/(n_vert-1)30483049# print ' alpha_xy\n',alpha_xy/np.pi*1803050# print ' alphas=alpha0+phi\n',alphas/np.pi*1803051# print ' n_vert',n_vert,dphi/np.pi*18030523053# print ' length_xy=',length_xy3054# print ' length_xy-self.widths.value=',(length_xy-self.widths.value)3055# print ' x2=',x2,x2.dtype30563057# print ' y2_new=',y2_new,y2_new.dtype3058x = np.cos(alphas) * radius + x2_new[inds_style]3059y = np.sin(alphas) * radius + y2_new[inds_style]30603061z = np.ones((n_vert, 1)) * z2[inds_style]30623063# print '_update_vertexvbo ',n,n_vert,self._is_fill.value3064# print ' x\n',x3065# print ' y\n',y3066# print ' z\n',z30673068# print '_update_vertexvbo_fill',n,len(x),n_vert,self._n_vpe_fill3069xf = x.transpose().flatten() # +0.53070yf = y.transpose().flatten() # +0.53071zf = z.transpose().flatten()3072xcf = (np.ones((n_vert, 1)) * x2_new[inds_style]).transpose().flatten()3073ycf = (np.ones((n_vert, 1)) * y2_new[inds_style]).transpose().flatten()3074# print ' xcf\n',xcf3075# print ' ycf\n',ycf30763077# create and compose main vertices array3078n_elem_fill = (n_vert-1)*n30793080n_vpe = headvbo.get_vpe()3081# print ' n_elem_fill ',self._n_elem_fill3082# print ' n_vpe',n_vpe3083vertices = np.zeros((n_elem_fill, n_vpe * 3), dtype=np.float32)3084# print ' vertices.reshape((-1,3)).shape',vertices.reshape((-1,3)).shape3085#zf = z.transpose().flatten()30863087ind = np.arange(0, n*n_vert).reshape(n, n_vert)[:, :-1].flatten()30883089vertices[:, 0] = xf[ind]3090vertices[:, 1] = yf[ind]3091vertices[:, 2] = zf[ind]30923093vertices[:, 3] = xcf[ind]3094vertices[:, 4] = ycf[ind]3095vertices[:, 5] = zf[ind]30963097ind2 = np.arange(0, n*n_vert).reshape(n, n_vert)[:, 1:].flatten()3098vertices[:, 6] = xf[ind2]3099vertices[:, 7] = yf[ind2]3100vertices[:, 8] = zf[ind2]3101# print ' vertices=\n',vertices3102headvbo.update_vertices(vertices, inds=inds_style)31033104#self._vertexvbo_fill = vbo.VBO(vertices.reshape((-1,3)))3105#self._indexvbo_fill = vbo.VBO(np.arange(self._n_vert*self._n_elem_fill, dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)31063107def pick(self, p, detectwidth=0.1):3108"""3109Returns a binary vector which is True values for lines that have been selected3110by point p.31113112"""3113# print 'pick'3114if len(self) == 0:3115return np.array([], np.int)31163117vertices = self.get_vertices_array()3118x1 = vertices[:, 0, 0]3119y1 = vertices[:, 0, 1]31203121x2 = vertices[:, 1, 0]3122y2 = vertices[:, 1, 1]31233124# print ' x1', x13125# print ' x2', x23126dw = 0.5*(self.get_widths_array()+detectwidth)3127return self._ids[get_dist_point_to_segs(p, x1, y1, x2, y2, is_ending=True) < dw*dw]312831293130class Polylines(Fancylines):3131def __init__(self, ident, parent, name='Polylines', joinstyle=FLATHEAD, **kwargs):3132Fancylines.__init__(self, ident, parent, name=name, **kwargs)31333134# ident of drawobject used for animations3135# must be defined AFTER init_common3136self._ident_drawobj_anim = 'anim_polylines'31373138# FLATHEAD = 03139# BEVELHEAD = 13140self.add(cm.AttrConf('joinstyle', joinstyle,3141groupnames=['options'],3142perm='rw',3143is_save=True,3144is_plugin=False,3145name='Joinstyle',3146info='Joinstyle of line segments.',3147))31483149self.delete('vertices')3150self.add_col(am.ListArrayConf('vertices',3151# None,3152# dtype=np.object,3153groupnames=['_private'],3154perm='rw',3155name='Vertex',3156unit='m',3157is_save=True,3158info='Vertex coordinate vectors of points. Example with 2 vertex: [[[x11,y11,z11],[x12,y12,z12]],[[x21,y21,z21],[x22,y22,z122]],...]',3159))31603161def begin_animation(self, id_target):31623163self._id_target = id_target3164self._drawobj_anim = self.parent.get_drawobj_by_ident(self._ident_drawobj_anim)31653166self.id_anim = self._drawobj_anim.add_drawobj( # make a copy as array, otherwise instance is copied3167np.array(self.get_vertices(id_target), np.float32).tolist(),3168np.array(self.get_widths(id_target), np.float32),3169self.color_anim.get_value(),3170beginstyle=self.beginstyles[id_target],3171endstyle=self.endstyles[id_target],3172)3173# print 'begin_animation',self.ident,id_target,self._drawobj_anim3174# print ' vert=',self.vertices[id_target]3175return True31763177def append_vert_to_animation(self, vert):3178# print 'append_vert_to_animation',vert, type(vert)3179# for _id in self.get_ids():3180# print ' main.vertices',_id,self.vertices[_id], type(self.vertices[_id])3181# for _id in self._drawobj_anim.get_ids():3182# print ' anim.vertices',_id,self._drawobj_anim.vertices[_id], type(self._drawobj_anim.vertices[_id])3183self._drawobj_anim.get_vertices(self.id_anim).append(vert)3184#vertex = self._drawobj_anim.get_vertices(self.id_anim).tolist()3185# self._drawobj_anim.set_vertices.append(vert.tolist())3186# print ' vertices',self._drawobj_anim.vertices[self.id_anim],type(self._drawobj_anim.vertices[self.id_anim])3187#vertices = self._drawobj_anim.vertices[self.id_anim]3188# vertices.append(vert)3189# self._drawobj_anim.vertices[self.id_anim]= vertices#list(np.array(vertices,np.float32))31903191# print ' vertices',vertices,type(vertices)3192# print ' self._drawobj_anim.vertices[self.id_anim]',self._drawobj_anim.vertices[self.id_anim],type(self._drawobj_anim.vertices[self.id_anim])3193self._drawobj_anim._update_vertexvbo()3194self._drawobj_anim._update_colorvbo()3195return len(self._drawobj_anim.get_vertices(self.id_anim))-1 # vertex ind of next31963197def end_animation(self, is_del_last_vert=False):3198# print 'end_animation',self.ident,self._id_target3199# print ' verices =',self._drawobj_anim.vertices[self.id_anim]3200if is_del_last_vert:3201# cut of last one because duplicated after adding3202self.set_vertices(self._id_target, self._drawobj_anim.get_vertices(self.id_anim)[:-1])3203else:3204self.set_vertices(self._id_target, self._drawobj_anim.get_vertices(self.id_anim))32053206self.del_animation()3207# self._drawobj_anim.del_drawobj(self.id_anim)3208self._update_vertexvbo()3209self._update_colorvbo()3210return True32113212def _make_lines(self):3213n_lines_tot = 03214for polyline in self.get_vertices_array():3215n_seg = len(polyline)3216# if n_seg>1:3217n_lines_tot += n_seg-132183219linevertices = np.zeros((n_lines_tot, 2, 3), np.float32)3220vertexinds = np.zeros((n_lines_tot, 2), np.int32)32213222polyinds = np.zeros(n_lines_tot, np.int32)3223linebeginstyles = np.zeros(n_lines_tot, np.int32)3224lineendstyles = np.zeros(n_lines_tot, np.int32)32253226beginstyles = self.beginstyles.value3227endstyles = self.endstyles.value3228joinstyle = self.joinstyle.value3229ind = 03230ind_line = 03231for polyline in self.get_vertices_array():3232# print ' =======',len(polyline)3233n_seg = len(polyline)3234# print ' polyline\n',polyline32353236if n_seg > 1:3237polyvinds = range(n_seg)3238# print ' polyvinds\n',polyvinds3239vi = np.zeros((2*n_seg-2), np.int32)3240vi[0] = polyvinds[0]3241vi[-1] = polyvinds[-1]32423243# Important type conversion!!3244v = np.zeros((2*n_seg-2, 3), np.float32)3245v[0] = polyline[0]3246v[-1] = polyline[-1]3247if len(v) > 2:3248v[1:-1] = np.repeat(polyline[1:-1], 2, 0)3249vi[1:-1] = np.repeat(polyvinds[1:-1], 2)32503251n_lines = len(v)/23252# print ' v\n',v3253inds_polyline = range(ind_line, ind_line+n_lines)32543255polyinds[inds_polyline] = ind32563257linebeginstyles[inds_polyline] = joinstyle3258linebeginstyles[inds_polyline[0]] = beginstyles[ind]32593260lineendstyles[inds_polyline] = joinstyle3261lineendstyles[inds_polyline[-1]] = endstyles[ind]32623263linevertices[inds_polyline] = v.reshape((-1, 2, 3))3264vertexinds[inds_polyline] = vi.reshape((-1, 2))32653266ind_line += n_lines3267ind += 13268else:3269# empty polygon treatment3270pass32713272# print ' linevertex\n',linevertices32733274self._linevertices = linevertices3275self._polyinds = polyinds3276self._vertexinds = vertexinds3277self._linebeginstyles = linebeginstyles3278self._lineendstyles = lineendstyles32793280def _update_vertexvbo(self):3281# print '_update_vertexvbo',self.ident3282self._make_lines()3283vertices = self._linevertices3284x1 = vertices[:, 0, 0]3285y1 = vertices[:, 0, 1]3286z1 = vertices[:, 0, 2]32873288x2 = vertices[:, 1, 0]3289y2 = vertices[:, 1, 1]3290z2 = vertices[:, 1, 2]3291dx = x2-x13292dy = y2-y13293alpha_xy = np.arctan2(dy, dx)3294length_xy = np.sqrt(dx*dx + dy*dy)3295halfwidth = 0.5*self.get_widths_array()[self._polyinds]3296# if self.ident =='lanedraws':3297# print '_update_vertexvbo',self.ident3298# print ' halfwidth',halfwidth3299# print ' x1',x13300# print ' y1',y133013302x1_new = x1.copy()3303y1_new = y1.copy()3304x2_new = x2.copy()3305y2_new = y2.copy()3306# print ' origvert'3307# print ' x1_new=',x1_new,x1_new.dtype3308# print ' x2_new=',x2_new,x2_new.dtype3309if self._is_fill.value:3310for style, id_style in LINEHEADS.iteritems():33113312# begin3313inds_style = np.flatnonzero(self._linebeginstyles == id_style)33143315if len(inds_style) > 0:33163317# print ' style',style,len(inds_style)3318# print ' x1_new=',x1_new,x1_new.dtype3319# print ' x2_new=',x2_new,x2_new.dtype3320self._update_vertexvbo_begin_fill(style, inds_style, x1_new, y1_new,3321z1, x2, y2, z2, length_xy, alpha_xy, halfwidth)33223323# end3324inds_style = np.flatnonzero(self._lineendstyles == id_style)3325if len(inds_style) > 0:3326self._update_vertexvbo_end_fill(style, inds_style, x1, y1, z1, x2_new,3327y2_new, z2, length_xy, alpha_xy, halfwidth)33283329self._update_vertexvbo_line_fill(x1_new, y1_new, z1, x2_new, y2_new, z2,3330length_xy, alpha_xy, halfwidth, len(vertices))33313332def _update_colorvbo(self):3333n = len(self._polyinds)3334#n_vert = self.get_n_vert()3335# print '_update_colorvbo fancyline'3336#self._linecolors = np.array(linecolors, np.float32)3337#self._linecolors_highl = np.array(linecolors_highl, np.float32)3338if self._is_outline.value:3339colors = self.colors.value[self._polyinds] + \3340self.are_highlighted.value[self._polyinds].reshape(n, 1)*self.colors_highl.value[self._polyinds]3341for _vbo in self.get_vbos():3342if not _vbo.is_fill():3343_vbo.update_colors(colors)33443345if self._is_fill.value:3346colors = self.colors_fill.value[self._polyinds] + self.are_highlighted.value[self._polyinds].reshape(3347n, 1)*self.colors_fill_highl.value[self._polyinds]3348for _vbo in self.get_vbos():3349if _vbo.is_fill():3350_vbo.update_colors(colors)33513352def pick(self, p, detectwidth=0.1):3353"""3354Returns a binary vector which is True values for lines that have been selected3355by point p.33563357In particular, an element of this vector is True if the minimum distance3358between the respective line to point p is less than detectwidth3359"""3360# print 'pick'3361if len(self) == 0:3362return np.array([], np.int)33633364vertices = self._linevertices3365x1 = vertices[:, 0, 0]3366y1 = vertices[:, 0, 1]33673368x2 = vertices[:, 1, 0]3369y2 = vertices[:, 1, 1]33703371# print ' x1', x13372# print ' x2', x23373halfwidths = 0.5*(self.get_widths_array()[self._polyinds]+detectwidth)3374return self._ids[self._polyinds[get_dist_point_to_segs(p, x1, y1, x2, y2, is_ending=True) < halfwidths*halfwidths]]33753376def pick_handle(self, coord, detectwidth=0.1):3377"""3378Retuns list [ id, ind_vert] when handle is near coord,3379otherwise []33803381"""3382# print 'pick_handle',self.get_ident(),len(self)3383dw = detectwidth**233843385if len(self) == 0:3386return np.zeros((0, 2), np.int)33873388# if self.ident not in [ 'lines','fancylines','polylines']:3389# return np.zeros((0,2),np.int)33903391vertices = self._linevertices # self.get_vertices_array()3392handles = []3393# print ' vertices',vertices3394# print ' vertices.shape',vertices.shape3395dx = vertices[:, 0, 0]-coord[0]3396dy = vertices[:, 0, 1]-coord[1]3397inds = np.flatnonzero(dx*dx+dy*dy < dw)33983399ids = self._ids[self._polyinds[inds]]3400handle1 = np.ones((len(ids), 2), np.int)3401handle1[:, 0] = ids3402handle1[:, 1] = self._vertexinds[inds, 0]3403# print ' ',d,handle134043405dx = vertices[:, 1, 0]-coord[0]3406dy = vertices[:, 1, 1]-coord[1]3407inds = np.flatnonzero(dx*dx+dy*dy < dw)3408ids = self._ids[self._polyinds[inds]]3409handle2 = np.ones((len(ids), 2), np.int)3410handle2[:, 0] = ids3411handle2[:, 1] = self._vertexinds[inds, 1]3412# print ' ',d,handle23413handles = np.concatenate((handle1, handle2), 0)34143415return handles34163417def get_boundingbox(self):3418if len(self) == 0:3419return None3420vv = self._linevertices3421# TODOD: can be done faster3422return np.array([[np.min(vv[:, :, 0]), np.min(vv[:, :, 1]), np.min(vv[:, :, 2])],3423[np.max(vv[:, :, 0]), np.max(vv[:, :, 1]), np.max(vv[:, :, 2])]3424], float)342534263427class Circles(DrawobjMixin):34283429def __init__(self, ident, parent, name='Circles',3430is_parentobj=False,3431is_fill=True, # Fill objects,3432is_outline=True, # show outlines3433c_highl=0.3,3434n_vert=7, # default number of vertex per circle3435linewidth=2,3436**kwargs):34373438self.init_common(ident, parent=parent, name=name,3439linewidth=linewidth,3440is_parentobj=is_parentobj,3441n_vert=n_vert,3442is_fill=is_fill,3443is_outline=is_outline,3444c_highl=c_highl,3445**kwargs)3446# ident of drawobject used for animations3447# must be defined AFTER init_common3448self._ident_drawobj_anim = 'anim_circles'34493450if is_outline:3451self.add_vbo(Vbo('outline', GL_LINES, 2, objtype='outline'))3452if is_fill:3453self.add_vbo(Vbo('fill', GL_TRIANGLES, 3, objtype='fill'))34543455self.add_col(am.ArrayConf('centers', np.zeros(3, dtype=np.float32),3456dtype=np.float32,3457groupnames=['_private'],3458perm='rw',3459name='Center',3460unit='m',3461is_save=True,3462info='Center coordinate. Example: [x,y,z]',3463))34643465self.add_col(am.ArrayConf('radii', 1.0,3466dtype=np.float32,3467groupnames=['_private'],3468perm='rw',3469name='Radius',3470is_save=True,3471info='Circle radius',3472))34733474def is_tool_allowed(self, tool, id_drawobj=-1):3475"""3476Returns True if this tool can be applied to this drawobj.3477Optionally a particular drawobj can be specified with id_drawobj.3478"""3479# basic tools:3480# return tool.ident not in ['configure','select_handles','delete','move','stretch']3481return True34823483def get_centers_array(self):3484return self.centers.value34853486def get_radii_array(self):3487return self.radii.value34883489def get_boundingbox(self):3490if len(self) == 0:3491return None3492vv = self.get_centers_array()3493rad = self.get_radii_array()3494# TODOD: can be done faster3495return np.array([[np.min(vv[:, 0]-rad), np.min(vv[:, 1]-rad), np.min(vv[:, 2])],3496[np.max(vv[:, 0]+rad), np.max(vv[:, 1]+rad), np.max(vv[:, 2])]3497], float)34983499def add_drawobj(self, center, radius,3500color, color_fill=None,3501color_highl=None, color_fill_highl=None,3502is_update=True):35033504if color_fill is None:3505color_fill = color35063507if color_highl is None:3508color_highl = self._get_colors_highl(np.array([color]))[0]35093510if color_fill_highl is None:3511color_fill_highl = self._get_colors_highl(np.array([color_fill]))[0]35123513_id = self.add_row(centers=center,3514radii=radius,3515colors=color,3516colors_highl=color_highl,3517colors_fill=color_fill,3518colors_fill_highl=color_fill_highl,3519)3520if is_update:3521self._update_vertexvbo()3522self._update_colorvbo()3523return _id35243525def add_drawobjs(self, centers, radii,3526colors, colors_fill=None,3527colors_highl=None, colors_fill_highl=None,3528is_update=True):3529# print 'Circles.add_drawobjs',self._is_fill.value,self._is_outline.value3530if colors_fill is None:3531colors_fill = colors35323533if colors_highl is None:3534colors_highl = self._get_colors_highl(colors)35353536if colors_fill_highl is None:3537colors_fill_highl = self._get_colors_highl(colors_fill)35383539# print ' colors',colors[:2]3540# print ' colors_highl',colors_highl[:2]35413542ids = self.add_rows(len(centers),3543centers=centers,3544radii=radii,3545colors=colors,3546colors_highl=colors_highl,3547colors_fill=colors_fill,3548colors_fill_highl=colors_fill_highl,3549)3550if is_update:3551self._update_vertexvbo()3552self._update_colorvbo()3553return ids35543555def begin_animation(self, id_target):35563557self._id_target = id_target3558self._drawobj_anim = self.parent.get_drawobj_by_ident(self._ident_drawobj_anim)3559self.id_anim = self._drawobj_anim.add_drawobj(np.array(self.centers[id_target]),35601.0*self.radii[id_target],3561self.color_anim.value,3562)3563# print 'begin_animation',self.ident,_id,self._drawobj_anim3564return True35653566def set_anim(self, _id, drawobjelem_anim):3567# print 'set_anim',self.ident,_id,drawobj_anim3568(drawobj_anim, id_anim) = drawobjelem_anim3569# print ' self.vertices[_id]=',self.vertices[_id]3570# print ' drawobjset_anim.vertices[id_anim]=',drawobjset_anim.vertices[id_anim]3571self.centers[_id] = np.array(drawobj_anim.centers[id_anim])3572self.radii[_id] = 1.0*drawobj_anim.radii[id_anim]3573drawobj_anim.del_drawobj(id_anim)3574self._update_vertexvbo()3575return True35763577def end_animation(self, is_del_last_vert=False):3578# print 'end_animation',self.ident,_id,self._drawobj_anim3579self.centers[self._id_target] = np.array(self._drawobj_anim.centers[self.id_anim])3580self.radii[self._id_target] = 1.0*self._drawobj_anim.radii[self.id_anim]35813582self._drawobj_anim.del_drawobj(self.id_anim)3583self._update_vertexvbo()3584return True35853586def move(self, _id, vertex, vertex_delta):3587# print 'move',self.ident,_id, vertex_delta3588self.centers[_id] += vertex_delta3589# print ' vertices[id_anim]=',self.vertices[_id]3590self._update_vertexvbo()3591return True35923593def stretch(self, _id, vertex, vertex_delta, ind_vertex):3594# print 'move',self.ident,_id, v3595#self.vertices[_id, ind_vertex] += vertex_delta35963597self.radii[_id] = np.sqrt(np.sum((vertex - self.centers[_id])**2))3598# print ' vertices[id_anim]=',self.vertices[_id]3599self._update_vertexvbo()3600return True36013602def _update_vertexvbo(self):36033604n = len(self)3605n_vert = self.get_n_vert()36063607# print '_update_vertexvbo ',n,n_vert,self._is_fill.value36083609# compute x,y,z of vertices of n objects3610dphi = 2*np.pi/(n_vert-1)3611phi = np.arange(0, 2*np.pi+dphi, dphi).reshape(-1, 1)36123613centers = self.get_centers_array()3614radii = self.get_radii_array()3615x = np.cos(phi)*radii+centers[:, 0]36163617y = np.sin(phi)*radii+centers[:, 1]36183619z = np.ones((n_vert, 1)) * centers[:, 2]3620# print ' x.shape=', x.shape3621if self._is_outline.value:3622self._update_vertexvbo_lines(x, y, z)36233624if self._is_fill.value:3625self._update_vertexvbo_fill(x, y, z)36263627def _update_vertexvbo_fill(self, x, y, z):3628n = len(self)3629n_vert = self.get_n_vert()3630# print '_update_vertexvbo_fill',n,len(x),n_vert#,self._n_vpe_fill3631xf = x.transpose().flatten() # +0.53632yf = y.transpose().flatten() # +0.53633zf = z.transpose().flatten()36343635centers = self.get_centers_array()3636#radii = self.get_radii_array()36373638xcf = (np.ones((n_vert, 1)) * centers[:, 0]).transpose().flatten()3639ycf = (np.ones((n_vert, 1)) * centers[:, 1]).transpose().flatten()36403641# create and compose main vertices array3642n_elem_fill = (n_vert-1)*n36433644#glDrawElements(GL_TRIANGLES, self._n_vert*self._n_elem_fill, GL_UNSIGNED_INT, None)3645# self._n_vert*self._n_elem_fill = n_vert * (n_vert-1)*n3646# repeat for each of the n objects: self._n_vpe_fill*(n_vert-1)3647# self._n_vpe * self._n_elem_fill = self._n_vpe * (n_vert-1)*n36483649n_vpe_fill = self.get_vbo('fill').get_vpe()3650# print ' n_elem_fill',n_elem_fill,n_vpe_fill3651vertices = np.zeros((n_elem_fill, n_vpe_fill * 3), dtype=np.float32)3652# print ' vertices.reshape((-1,3)).shape',vertices.reshape((-1,3)).shape3653zf = z.transpose().flatten()36543655ind = np.arange(0, n*n_vert).reshape(n, n_vert)[:, :-1].flatten()36563657vertices[:, 0] = xf[ind]3658vertices[:, 1] = yf[ind]3659vertices[:, 2] = zf[ind]36603661vertices[:, 3] = xcf[ind]3662vertices[:, 4] = ycf[ind]3663vertices[:, 5] = zf[ind]36643665ind2 = np.arange(0, n*n_vert).reshape(n, n_vert)[:, 1:].flatten()3666vertices[:, 6] = xf[ind2]3667vertices[:, 7] = yf[ind2]3668vertices[:, 8] = zf[ind2]36693670self.get_vbo('fill').update_vertices(vertices, n)3671#self._vertexvbo_fill = vbo.VBO(vertices.reshape((-1,3)))3672#self._indexvbo_fill = vbo.VBO(np.arange(self._n_vert*self._n_elem_fill, dtype=np.int32), target=GL_ELEMENT_ARRAY_BUFFER)36733674def _update_vertexvbo_lines(self, x, y, z):3675# print '_update_vertexvbo_lines',len(x)3676n = len(self)3677n_vert = self.get_n_vert()36783679# create and compose main vertices array3680n_elem = (n_vert-1)*n36813682n_vpe = 2 # vertices per OGL element36833684vertices = np.zeros((n_elem, n_vpe * 3), dtype=np.float32)36853686# print ' vertices.reshape((-1,3)).shape',vertices.reshape((-1,3)).shape36873688xf = x.transpose().flatten()3689yf = y.transpose().flatten()3690zf = z.transpose().flatten()36913692ind = np.arange(0, n*n_vert).reshape(n, n_vert)[:, :-1].flatten()36933694vertices[:, 0] = xf[ind]3695vertices[:, 1] = yf[ind]3696vertices[:, 2] = zf[ind]36973698ind2 = np.arange(0, n*n_vert).reshape(n, n_vert)[:, 1:].flatten()3699vertices[:, 3] = xf[ind2]3700vertices[:, 4] = yf[ind2]3701vertices[:, 5] = zf[ind2]37023703self.get_vbo('outline').update_vertices(vertices, n)37043705def pick(self, p, detectwidth=0.1):3706"""3707Returns a binary vector which is True values for circles that have been selected3708by point p.37093710In particular, an element is selected if point p is within the circle3711"""3712if len(self) == 0:3713return np.array([], np.int)37143715#centers = self.centers.value3716centers = self.get_centers_array()3717radii = self.get_radii_array()+0.5*detectwidth3718dx = centers[:, 0]-p[0]3719dy = centers[:, 1]-p[1]3720return self._ids[dx*dx+dy*dy < (radii*radii)]37213722def pick_handle(self, coord, detectwidth=0.1):3723"""3724Retuns list [ id, ind_vert] when handle is near coord,3725otherwise []37263727"""3728if len(self) == 0:3729return np.zeros((0, 2), np.int)3730# print 'pick_handle',self.get_ident(),len(self)3731dw = detectwidth**237323733centers = self.get_centers_array()3734radii = self.get_radii_array()3735dx = centers[:, 0]-coord[0]3736dy = centers[:, 1]-coord[1]3737r = dx*dx+dy*dy3738ids = self._ids[(r > radii*radii-dw) & (r < radii*radii+dw)]3739#handles = np.concatenate(( ids.reshape((len(ids),1)), np.zeros((len(ids),1),np.int)),1)37403741# print ' ids',ids3742# print ' handles',handles3743return np.concatenate((ids.reshape((len(ids), 1)), np.zeros((len(ids), 1), np.int)), 1)374437453746class Polygons(DrawobjMixin):3747def __init__(self, ident, parent, name='Polygons', **kwargs):3748self.init_common(ident, parent=parent, name=name,3749is_fill=False,3750is_outline=True,3751**kwargs)3752# ident of drawobject used for animations3753# must be defined AFTER init_common3754self._ident_drawobj_anim = 'anim_polygons'37553756if self._is_outline:3757self.add_vbo(Vbo('outline', GL_LINES, 2, objtype='outline'))3758if self._is_fill:3759self.add_vbo(Vbo('fill', GL_TRIANGLES, 3, objtype='fill'))37603761self.delete('vertices')3762self.add_col(am.ListArrayConf('vertices',3763# None,3764# dtype=np.object,3765groupnames=['_private'],3766perm='rw',3767name='Vertex',3768unit='m',3769is_save=True,3770info='3D coordinate list of Polygon Points.',3771))37723773def add_drawobj(self, vertex,3774color, color_fill=None,3775color_highl=None, color_fill_highl=None,3776is_update=True):37773778if color_fill is None:3779color_fill = color37803781if color_highl is None:3782color_highl = self._get_colors_highl(np.array([color]))[0]37833784if color_fill_highl is None:3785color_fill_highl = self._get_colors_highl(np.array([color_fill]))[0]37863787_id = self.add_row(vertices=vertex,3788colors=color,3789colors_highl=color_highl,3790colors_fill=color_fill,3791colors_fill_highl=color_fill_highl,3792)3793if is_update:3794self._update_vertexvbo()3795self._update_colorvbo()3796return _id37973798def add_drawobjs(self, vertices,3799colors, colors_fill=None,3800colors_highl=None, colors_fill_highl=None,3801is_update=True):38023803if colors_fill is None:3804colors_fill = colors38053806if colors_highl is None:3807colors_highl = self._get_colors_highl(colors)38083809if colors_fill_highl is None:3810colors_fill_highl = self._get_colors_highl(colors_fill)38113812ids = self.add_rows(len(vertices),3813vertices=vertices,3814colors=colors,3815colors_highl=colors_highl,3816colors_fill=colors_fill,3817colors_fill_highl=colors_fill_highl,3818)3819if is_update:3820self._update_vertexvbo()3821self._update_colorvbo()3822return ids38233824def begin_animation(self, id_target):38253826self._id_target = id_target3827self._drawobj_anim = self.parent.get_drawobj_by_ident(self._ident_drawobj_anim)3828self.id_anim = self._drawobj_anim.add_drawobj( # make a copy as array, otherwise instance is copied3829np.array(self.get_vertices(id_target), np.float32).tolist(),3830self.color_anim.get_value(),3831)3832# print 'begin_animation',self.ident,_id,self._drawobj_anim3833return True38343835def append_vert_to_animation(self, vert):3836# print 'append_vert_to_animation',vert, type(vert)3837# for _id in self.get_ids():3838# print ' main.vertices',_id,self.vertices[_id], type(self.vertices[_id])3839# for _id in self._drawobj_anim.get_ids():3840# print ' anim.vertices',_id,self._drawobj_anim.vertices[_id], type(self._drawobj_anim.vertices[_id])38413842self._drawobj_anim.get_vertices(self.id_anim).append(vert)3843# print ' vertices',self._drawobj_anim.vertices[self.id_anim],type(self._drawobj_anim.vertices[self.id_anim])3844#vertices = self._drawobj_anim.vertices[self.id_anim]3845# vertices.append(vert)3846# self._drawobj_anim.vertices[self.id_anim]= vertices#list(np.array(vertices,np.float32))38473848# print ' vertices',vertices,type(vertices)3849# print ' self._drawobj_anim.vertices[self.id_anim]',self._drawobj_anim.vertices[self.id_anim],type(self._drawobj_anim.vertices[self.id_anim])3850self._drawobj_anim._update_vertexvbo()3851self._drawobj_anim._update_colorvbo()3852return len(self._drawobj_anim.get_vertices(self.id_anim))-1 # vertex ind of next38533854# def get_vertices_array(self):3855# return self.vertices.value38563857def _make_lines(self):3858n_lines_tot = 03859for polyline in self.get_vertices_array():3860n_lines_tot += len(polyline)38613862linevertices = np.zeros((n_lines_tot, 2, 3), np.float32)3863vertexinds = np.zeros((n_lines_tot, 2), np.int32)38643865polyinds = np.zeros(n_lines_tot, np.int32)3866linebeginstyles = np.zeros(n_lines_tot, np.int32)3867lineendstyles = np.zeros(n_lines_tot, np.int32)38683869ind = 03870ind_line = 038713872for polyline in self.get_vertices_array(): # self.vertices.value:3873# print ' ======='38743875# print ' polyline\n',polyline3876polyvinds = range(len(polyline))3877# print ' polyvinds\n',polyvinds3878vi = np.zeros((2*len(polyline)), np.int32)3879vi[0] = polyvinds[0]3880vi[-2] = polyvinds[-2]3881vi[-1] = polyvinds[-1]3882# print ' vi\n',vi38833884# Important type conversion!!3885v = np.zeros((2*len(polyline), 3), np.float32)3886v[0] = polyline[0]3887v[-2] = polyline[-1]3888v[-1] = polyline[0]3889# print ' v\n',v3890if len(v) > 3:3891v[1:-1] = np.repeat(polyline[1:], 2, 0)3892vi[1:-1] = np.repeat(polyvinds[1:], 2)3893n_lines = len(v)/23894# print ' v\n',v3895inds_polyline = range(ind_line, ind_line+n_lines)38963897polyinds[inds_polyline] = ind3898linevertices[inds_polyline] = v.reshape((-1, 2, 3))3899vertexinds[inds_polyline] = vi.reshape((-1, 2))3900ind_line += n_lines3901ind += 139023903self._linevertices = linevertices3904self._vertexinds = vertexinds3905self._polyinds = polyinds39063907def _update_vertexvbo(self):3908# print '_update_vertexvbo',self.format_ident()3909self._make_lines()39103911if self._is_outline.value:3912# print ' linevertices.reshape((-1,6))',self._linevertices.reshape((-1,6)),len(self._linevertices)3913self.get_vbo('outline').update_vertices(self._linevertices.reshape((-1, 6)), len(self._linevertices))3914#self._update_vertexvbo_line_fill(x1_new,y1_new,z1,x2_new,y2_new,z2,length_xy, alpha_xy,halfwidth,len(vertices))39153916# if self._is_fill.value:3917# self._update_vertexvbo_line_fill(x1_new,y1_new,z1,x2_new,y2_new,z2,length_xy, alpha_xy,halfwidth,len(vertices))39183919def _update_colorvbo(self):3920n = len(self._polyinds)3921#n_vert = self.get_n_vert()3922# print 'Polygons._update_colorvbo',self.ident,n3923# print ' colors',self.colors.value3924# print ' are_highlighted',self.are_highlighted.value3925#self._linecolors = np.array(linecolors, np.float32)3926#self._linecolors_highl = np.array(linecolors_highl, np.float32)3927if (self._is_outline.value) & (n > 0):3928colors = self.colors.value[self._polyinds] + \3929self.are_highlighted.value[self._polyinds].reshape(n, 1)*self.colors_highl.value[self._polyinds]3930self.get_vbo('outline').update_colors(colors)39313932# if self._is_fill.value:3933# colors = self.colors_fill.value[self._polyinds] + self.are_highlighted.value[self._polyinds].reshape(n,1)*self.colors_fill_highl.value[self._polyinds]3934# self.get_vbo('fill').update_colors(colors)39353936def pick(self, p, detectwidth=0.1):3937"""3938Returns a binary vector which is True values for lines that have been selected3939by point p.39403941In particular, an element of this vector is True if the minimum distance3942between the respective line to point p is less than detectwidth3943"""3944if len(self) == 0:3945return np.array([], np.int)39463947vertices = self._linevertices3948x1 = vertices[:, 0, 0]3949y1 = vertices[:, 0, 1]39503951x2 = vertices[:, 1, 0]3952y2 = vertices[:, 1, 1]39533954return self._ids[self._polyinds[get_dist_point_to_segs(p, x1, y1, x2, y2, is_ending=True) < detectwidth*detectwidth]]39553956def pick_handle(self, coord, detectwidth=0.1):3957"""3958Retuns list [ id, ind_vert] when handle is near coord,3959otherwise []39603961"""3962# print 'pick_handle',self.get_ident(),len(self),detectwidth3963dw = detectwidth ** 2 # np.sqrt(detectwidth)39643965if len(self) == 0:3966return np.zeros((0, 2), np.int)39673968# if self.ident not in [ 'lines','fancylines','polylines']:3969# return np.zeros((0,2),np.int)39703971vertices = self._linevertices # self.get_vertices_array()3972handles = []3973# print ' vertices',vertices3974# print ' vertices.shape',vertices.shape3975dx = vertices[:, 0, 0]-coord[0]3976dy = vertices[:, 0, 1]-coord[1]3977inds = np.flatnonzero(dx*dx+dy*dy < dw)39783979ids = self._ids[self._polyinds[inds]]3980handle1 = np.ones((len(ids), 2), np.int)3981handle1[:, 0] = ids3982handle1[:, 1] = self._vertexinds[inds, 0]3983# print ' ',d,handle139843985dx = vertices[:, 1, 0]-coord[0]3986dy = vertices[:, 1, 1]-coord[1]3987inds = np.flatnonzero(dx*dx+dy*dy < dw)3988ids = self._ids[self._polyinds[inds]]3989handle2 = np.ones((len(ids), 2), np.int)3990handle2[:, 0] = ids3991handle2[:, 1] = self._vertexinds[inds, 1]3992# print ' ',d,handle23993handles = np.concatenate((handle1, handle2), 0)39943995# print ' found',len(np.flatnonzero(handles))3996return handles39973998def get_boundingbox(self):3999if len(self) == 0:4000return None4001vv = self._linevertices4002# TODOD: can be done faster4003return np.array([[np.min(vv[:, :, 0]), np.min(vv[:, :, 1]), np.min(vv[:, :, 2])],4004[np.max(vv[:, :, 0]), np.max(vv[:, :, 1]), np.max(vv[:, :, 2])]4005], float)400640074008class OGLdrawing(am.ArrayObjman):4009"""4010Class holding an ordered list of all OGL draw objects.4011This class manages also the order in which the draw objects are rendered.40124013The basic idea is that an instance of this class can be passed to4014different OGL rendering canvas.4015"""40164017def __init__(self, ident='drawing', parent=None, name='OGL drawing', info='List of OGL draw objects'):4018"""4019Holds all drawing objects and provides basic access.4020"""4021self._init_objman(ident, parent=parent, name=name, info=info)4022self.add_col(cm.ObjsConf('drawobjects',4023groupnames=['options'],4024name='Draw object',4025info='Object, containing data and rendering methods.',4026))40274028self.add_col(am.ArrayConf('idents', '',4029dtype='object',4030perm='r',4031is_index=True,4032name='ID',4033info='Ident string of draw object.',4034))40354036self.add_col(am.ArrayConf('layers', -1.0,4037groupnames=['options'],4038perm='rw',4039#is_index = True,4040name='Layer',4041info='Layer defines the order in which drawobjects are drawn.',4042))40434044def get_drawobjs(self, is_anim=False):4045# print 'get_drawobjs'4046ids = []4047# efficient only if there are few number of different layers4048# TODO: use the new sort function of indexed cols4049for layer in sorted(set(self.layers.value)):4050inds = np.flatnonzero(self.layers.value == layer)4051ids += list(self.get_ids(inds))40524053# print ' ', ids4054if not is_anim:4055ids_noanim = []4056for _id in ids:4057# print ' check',_id,self.drawobjects[_id].get_ident(),self.drawobjects[_id].get_name(),self.drawobjects[_id].get_ident().count('anim')4058if self.drawobjects[_id].get_ident().count('anim') == 0:4059ids_noanim.append(_id)4060# print ' ids_noanim',ids_noanim4061return self.drawobjects[ids_noanim]4062else:4063return self.drawobjects[ids] # .value.values()4064# return self.drawobjects.value.values()40654066def has_drawobj_with_ident(self, ident):4067return self.idents.has_index(ident)40684069def get_drawobj_by_ident(self, ident):4070if self.has_drawobj_with_ident(ident):4071_id = self.idents.get_id_from_index(ident)4072return self.drawobjects[_id]4073else:4074None40754076def add_drawobj(self, drawobj, layer=0):4077id_drawobj = self.add_row(drawobjects=drawobj,4078idents=drawobj.get_ident(),4079layers=layer,4080)4081return id_drawobj40824083def del_drawobj_by_ident(self, ident):4084if self.idents.has_index(ident):4085_id = self.idents.get_id_from_index(ident)4086self.del_row(_id)4087return True4088else:4089return False409040914092class OGLnavcanvas(wx.Panel):4093"""4094Canvas with some navigation tools.4095"""40964097def __init__(self, parent,4098mainframe=None,4099size=wx.DefaultSize,4100):41014102wx.Panel.__init__(self, parent, -1)4103box = wx.BoxSizer(wx.VERTICAL)4104#box.Add((20, 30))4105#keys = buttonDefs.keys()4106# keys.sort()4107# for k in keys:4108# text = buttonDefs[k][1]4109# btn = wx.Button(self, k, text)4110# box.Add(btn, 0, wx.ALIGN_CENTER|wx.ALL, 15)4111# self.Bind(wx.EVT_BUTTON, self.OnButton, btn)4112#btn = wx.Button(self, 1, "test")4113#box.Add(btn, 0, wx.ALIGN_CENTER|wx.ALL, 15)41144115# With this enabled, you see how you can put a GLCanvas on the wx.Panel4116# if 1:4117c = OGLcanvas(self, mainframe=mainframe)4118# important to give a value4119c.SetMinSize((200, 200))4120self._canvas = c41214122# navigation bar4123self._navbar = self.make_navbar()41244125# compose navcanvas window4126#box.Add(self._canvas,1,wx.GROW)#4127box.Add(self._canvas, 1, wx.EXPAND)4128box.Add(self._navbar, 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4) # from NaviPanelTest41294130#box.Add(c, 0, wx.ALIGN_CENTER|wx.ALL, 15)4131#box.Add(c, 0, wx.EXPAND)4132# sizer.Add(self._toolspanel,0,wx.EXPAND)41334134self.SetAutoLayout(True)4135self.SetSizer(box)4136#self.Bind(wx.EVT_SIZE, self.OnSize)41374138# def OnSize(self, event):4139# self.Show(show=True, recursive=True)41404141def get_canvas(self):4142return self._canvas41434144def make_navbar(self):4145"""4146Initialize toolbar which consist of navigation buttons4147"""4148bottonsize = (16, 16)4149bottonborder = 104150toolbarborder = 141514152# toolbar41534154##4155navbar = wx.BoxSizer(wx.HORIZONTAL)41564157bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'gtk_fit_zoom_24px.png'), wx.BITMAP_TYPE_PNG)4158b = wx.BitmapButton(self, -1, bitmap, bottonsize)4159b.SetToolTipString("Zoom to fit")4160self.Bind(wx.EVT_BUTTON, self.on_zoom_tofit, b)4161navbar.Add(b, flag=wx.ALL, border=toolbarborder) # ,border=toolbarborder ,flag=wx.ALL, # 0, wx.ALL, 541624163bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'gtk_in_zoom_24px.png'), wx.BITMAP_TYPE_PNG)4164b = wx.BitmapButton(self, -1, bitmap, bottonsize,4165(bitmap.GetWidth()+bottonborder, bitmap.GetHeight()+bottonborder))4166b.SetToolTipString("Zoom in")4167self.Bind(wx.EVT_BUTTON, self.on_zoom_in, b)4168navbar.Add(b, flag=wx.ALL, border=toolbarborder)41694170bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'gtk_out_zoom_24px.png'), wx.BITMAP_TYPE_PNG)4171b = wx.BitmapButton(self, -1, bitmap, bottonsize,4172(bitmap.GetWidth()+bottonborder, bitmap.GetHeight()+bottonborder))4173b.SetToolTipString("Zoom out")4174self.Bind(wx.EVT_BUTTON, self.on_zoom_out, b)4175navbar.Add(b, flag=wx.ALL, border=toolbarborder)41764177bitmap = wx.Bitmap(os.path.join(IMAGEDIR, 'icon_select_components.png'), wx.BITMAP_TYPE_PNG)4178b = wx.BitmapButton(self, -1, bitmap, bottonsize,4179(bitmap.GetWidth()+bottonborder, bitmap.GetHeight()+bottonborder))4180b.SetToolTipString("Select drawing components")4181#b = wx.Button(self, label="Show/Hide")4182self.Bind(wx.EVT_BUTTON, self.popup_showhide, b)4183navbar.Add(b)4184# navbar.AddStretchSpacer()4185# navbar.AddSpacer(3)41864187self.coordsdisplay = wx.StaticText(self, -1, 'x,y', style=wx.TE_RIGHT)4188navbar.Add(self.coordsdisplay, wx.ALL | wx.EXPAND, 5, border=toolbarborder) # ,flag=wx.RIGHT no effect??4189# self.path = wx.TextCtrl(self, -1,'Try me', style=wx.TE_RIGHT)#size=(-1, -1))#,size=(300, -1))4190#self.path.Bind(wx.EVT_CHAR, self.on_test)4191#navbar.Add(self.path,1, wx.EXPAND, border=toolbarborder)41924193#b.Bind(wx.EVT_BUTTON, self.popup_showhide)41944195#b=wx.Button(self, wx.wx.ID_ZOOM_IN)4196#b.SetToolTipString("Zoom in")4197#self.Bind(wx.EVT_BUTTON, self.on_test, b)4198#navbar.Add(b, flag=wx.ALL, border=toolbarborder)41994200#bitmap = wx.ArtProvider_GetBitmap(wx.ART_GO_FORWARD,wx.ART_TOOLBAR)4201# b = wx.BitmapButton(self, -1, bitmap, bottonsize,4202# (bitmap.GetWidth()+bottonborder, bitmap.GetHeight()+bottonborder))4203#b.SetToolTipString("Go forward in browser history.")4204#self.Bind(wx.EVT_BUTTON, self.on_test, b)4205#navbar.Add(b,0, wx.EXPAND, border=toolbarborder)4206# bottons.append(b)42074208# self.add_tool(4209# 'home',self.on_go_home,4210# wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_TOOLBAR, tsize),4211# 'show panel of root instance')42124213# self.toolbar.AddSeparator()42144215# panel.SetAutoLayout(True)4216# panel.SetSizer(buttons)42174218navbar.Fit(self)4219return navbar42204221def display_coords(self, coords):4222# self.coordsdisplay.SetLabel(str(coords[0])+','+str(coords[1]))4223self.coordsdisplay.SetLabel('%8.3f,%8.3f' % (coords[0], coords[1]))42244225def get_navbar(self):4226return self._navbar42274228def on_zoom_tofit(self, event=None):4229self._canvas.zoom_tofit()4230if event:4231event.Skip()42324233def on_zoom_out(self, event=None):4234self._canvas.zoom_out()4235if event:4236event.Skip()42374238def on_zoom_in(self, event=None):4239self._canvas.zoom_in()4240if event:4241event.Skip()42424243def popup_showhide(self, event):4244#btn = event.GetEventObject()4245drawing = self._canvas.get_drawing()42464247# Create the popup menu4248self._menu_showhide = AgilePopupMenu(self)4249if drawing:4250for drawobj in drawing.get_drawobjs():4251# print ' path=',drawobj.get_name(),drawobj.is_visible()4252self._menu_showhide.append_item(4253drawobj.get_name(),4254self.showhide_drawobjs,4255info='Show/hide '+drawobj.get_name(),4256check=drawobj.is_visible(),4257)42584259self.PopupMenu(self._menu_showhide)4260self._menu_showhide.Destroy()4261event.Skip()42624263def showhide_drawobjs(self, event):4264# print 'showhide_drawobjs'4265drawing = self._canvas.get_drawing()4266if drawing:4267for drawobj in drawing.get_drawobjs():4268menuitem = self._menu_showhide.get_menuitem(drawobj.get_name())4269# print ' set_visible=',drawobj.get_name(),menuitem.IsChecked()4270drawobj.set_visible(menuitem.IsChecked())42714272self._canvas.draw()4273event.Skip()42744275def on_test(self, event=None):4276print 'this is a test'427742784279class OGLcanvas(glcanvas.GLCanvas):4280def __init__(self, parent, mainframe=None):4281if mainframe is None:4282self._mainframe = parent4283else:4284self._mainframe = mainframe42854286attribList = (glcanvas.WX_GL_RGBA, # RGBA4287glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered4288glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit4289glcanvas.GLCanvas.__init__(self, parent, attribList=attribList)4290self.init = False42914292self.context = glcanvas.GLContext(self)42934294self.xRotate = 0.4295self.yRotate = 0.4296self.zRotate = 0.42974298self.xTrans = 0.4299self.yTrans = 0.43004301# initial mouse position4302self.lastx = self.x = 304303self.lasty = self.y = 304304self.size = None43054306# gui event binding4307self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)4308self.Bind(wx.EVT_SIZE, self.OnSize)4309self.Bind(wx.EVT_PAINT, self.OnPaint)43104311# mouse event binding4312self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)4313self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDclick)4314self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)4315self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)4316self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)4317self.Bind(wx.EVT_MOTION, self.OnMotion)4318self.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel)43194320#4321self.action = ""43224323# 2D geom specific4324self.eyex = 0.04325self.eyey = 0.04326self.eyez = -30000.0 # -9.043274328self.centerx = 0.04329self.centery = 0.04330self.centerz = 0.043314332self.upx = -1.04333self.upy = 0.04334self.upz = 0.043354336self.g_Width = 6004337self.g_Height = 60043384339self.g_nearPlane = 10.0 # 10.4340self.g_farPlane = 10.0**8 # 10.0**8 #10000.43414342self.pos_start = (0.0, 0.0)4343self.trans_start = (0.0, 0.0)43444345self.resetView(is_draw=False)43464347self._tool = None4348self._drawing = None4349# self.Parent.Fit()4350# wx.CallAfter(self.Parent.Fit)4351# wx.CallAfter(self.OnSize)4352# self.Show()4353# self.SetCurrent(self.context)# too e43544355def polarView(self):4356glTranslatef(self.trans[1], 0.0, 0.0)4357glTranslatef(0.0, -self.trans[0], 0.0)43584359glRotatef(-self.zRotate, 0.0, 0.0, 1.0)4360glRotatef(-self.xRotate, 1.0, 0.0, 0.0)4361glRotatef(-self.yRotate, 0.0, 1.0, 0.0)43624363def OnEraseBackground(self, event):4364pass # Do nothing, to avoid flashing on MSW.43654366def OnSize(self, event):4367wx.CallAfter(self.DoSetViewport)4368event.Skip()4369# self.DoSetViewport()43704371def DoSetViewport(self):4372# self.Show()4373size = self.size = self.GetClientSize()4374# print 'DoSetViewport',size.width, size.height,self.IsShown()4375# if self.IsShown():43764377# sufficient to call SetCurrent in OnPaint4378# try:4379# #if self.context is not None:4380# #self.SetCurrent(self.context)4381# pass4382# except:4383# print 'WARNING in DoSetViewport: caoon set context'4384#glViewport(0, 0, size.width, size.height)4385self.OnReshape(size.width, size.height)4386# self.OnPaint()43874388def set_color_background(self, color):4389glClearColor(color[0], color[1], color[2], color[3])4390self.draw()43914392def OnReshape(self, width, height):4393"""Reshape the OpenGL viewport based on the dimensions of the window."""4394#global g_Width, g_Height4395self.g_Width = width4396self.g_Height = height4397glViewport(0, 0, self.g_Width, self.g_Height)43984399def OnPaint(self, event=None):4400# print 'OnPaint',self.IsShown()4401dc = wx.PaintDC(self)4402self.SetCurrent(self.context)4403if not self.init:4404self.InitGL()4405self.init = True4406self.OnDraw()4407# err self.SendSizeEventToParent()4408#del dc44094410def InitGL(self):4411glClearColor(0, 0, 0, 1)44124413def get_intersection(self, v_near, v_far):4414# 1509184415# idea from http://www.bfilipek.com/2012/06/select-mouse-opengl.html4416# https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection4417d = -v_near + v_far44184419t = -v_near[2]/d[2]4420v_inter = v_near+t*d44214422return v_inter44234424def unproject_event(self, event):4425return self.unproject(event.GetPosition())[0:2]44264427def unproject(self, pos_display):4428"""Get the world coordinates for viewCoordinate for the event4429"""4430# print 'unproject',pos_display4431x = pos_display[0]4432y = self.g_Height-pos_display[1]44334434modelviewmatrix = glGetDoublev(GL_MODELVIEW_MATRIX)4435projectionmatrix = glGetDoublev(GL_PROJECTION_MATRIX)4436viewport = glGetInteger(GL_VIEWPORT)44374438z = 0.04439worldCoordinate_near = np.array(gluUnProject(4440x, y, z,4441modelviewmatrix,4442projectionmatrix,4443viewport,), dtype=np.float32)44444445z = 1.04446worldCoordinate_far = np.array(gluUnProject(4447x, y, z,4448modelviewmatrix,4449projectionmatrix,4450viewport,), dtype=np.float32)44514452v_inter = self.get_intersection(worldCoordinate_near, worldCoordinate_far)4453# print ' world coords v_inter',v_inter4454return v_inter44554456def project(self, vertex):4457"""4458http://stackoverflow.com/questions/3792481/how-to-get-screen-coordinates-from-a-3d-point-opengl4459"""4460modelviewmatrix = glGetDoublev(GL_MODELVIEW_MATRIX)4461projectionmatrix = glGetDoublev(GL_PROJECTION_MATRIX)4462viewport = glGetInteger(GL_VIEWPORT)44634464coords = np.array(gluProject(vertex[0], vertex[1], vertex[2],4465modelviewmatrix, projectionmatrix,4466viewport))44674468coords[1] = self.g_Height - coords[1]4469# print 'project',coords44704471return coords44724473def OnDraw(self, *args, **kwargs):4474"""Draw the window."""44754476# print 'OGLCanvas.draw id(self._drawing)',id(self._drawing)4477# Clear frame buffer and depth buffer4478glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)4479# Set up viewing transformation, looking down -Z axis4480if self._drawing is None:4481self.SwapBuffers()4482return44834484glLoadIdentity()4485gluLookAt(self.eyex, self.eyey, self.eyez, self.centerx, self.centery,4486self.centerz, self.upx, self.upy, self.upz) # -.1,0,044874488# Set perspective (also zoom)4489glMatrixMode(GL_PROJECTION)4490glLoadIdentity()4491# the window corner OpenGL coordinates are (-+1, -+1)4492glOrtho(-1, 1, 1, -1, -1, 1)44934494aspect = float(self.g_Width)/float(self.g_Height)44954496gluPerspective(self.zoom, aspect, self.g_nearPlane, self.g_farPlane)4497glMatrixMode(GL_MODELVIEW)4498self.polarView()44994500# resolution in GL unit per scren pixel4501#resolution = self.get_resolution()4502# print ' get_resolution',resolution45034504# draw actual scene4505# if self._drawing:4506# self._drawing.print_attrs()4507for drawobj in self._drawing.get_drawobjs(is_anim=True):4508#checkobj = self._drawing.get_drawobj_by_ident(drawobj.ident)4509# if checkobj is not None:4510# print '\n draw.drawobj',drawobj.ident, checkobj.ident4511# else:4512# print '\n draw.drawobj',drawobj.ident, checkobj,self._drawing.has_drawobj_with_ident(drawobj.ident)4513drawobj.draw() # resolution)45144515self.SwapBuffers()45164517def draw(self, *args, **kwargs):4518# print 'draw',self.IsShown()4519# self.Show() # does not prevent error in SetCurrent4520try:4521self.SetCurrent(self.context)4522self.OnDraw(*args, **kwargs)4523# print 'draw',self.lastx,self.lasty,self.x,self.y4524except:4525print 'WARNING in draw: unable to set context'45264527def set_drawing(self, drawing):4528if self._drawing != drawing:45294530# if self._tool is not None:4531# self._tool.force_deactivation()45324533del self._drawing4534self._drawing = drawing4535# self.draw()45364537def activate_tool(self, tool):4538# called from tool4539self._tool = tool45404541def deactivate_tool(self):4542# called from tool45434544# print 'deactivate_tool',self._tool.format_ident()4545# make sure cursor gets back to normal4546self.SetCursor(wx.NullCursor)45474548# self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))4549self._tool = None4550self.draw()45514552def get_tool(self):4553return self._tool45544555def get_drawing(self):4556return self._drawing45574558def resetView(self, is_draw=True):4559self.zoom = 65.45604561self.xRotate = 180.4562self.yRotate = 180.4563self.zRotate = -90.04564self.trans = (0.0, 0.0)45654566if is_draw:4567self.draw()45684569def on_key_down(self, event):4570is_draw = False4571# print 'on_key_down',event.KeyCode(),type(event.KeyCode())4572if event.KeyCode() == 'x':4573self.xRotate += 5.04574is_draw |= True45754576if is_draw:4577self.draw()4578event.Skip()45794580def get_resolution(self):4581"""4582Resolution in GL unit per scren pixel4583"""4584if (self.g_Width == 0) & (self.g_Height == 0):4585# there is no window space4586return 1.045874588v_top = self.unproject((0.5*self.g_Width, 0))4589v_bot = self.unproject((0.5*self.g_Width, self.g_Height))45904591v_left = self.unproject((0, 0.5 * self.g_Height))4592v_right = self.unproject((self.g_Width, 0.5*self.g_Height))45934594dy = np.abs(v_bot[1]-v_top[1])4595dx = np.abs(v_right[1]-v_left[1])45964597if dx > dy:4598return dx/self.g_Width4599else:4600return dy/self.g_Height46014602def zoom_tofit(self, event=None, is_draw=True):4603# print 'zoom_tofit',is_draw4604#p = self._canvas.unproject_event(event)4605#vetrex = np.array([p[0], p[1], 0.0, 1.0],float)4606#p_screen = self._canvas.project(vetrex)4607# print 'SelectTool.on_left_down (px,py)=',p4608# print ' (x,y)=',event.GetPosition(),p_screen4609self.resetView()46104611vv_min, vv_max = self.get_boundingbox()4612dv = vv_max - vv_min46134614# print 'vv_min',vv_min4615# print 'vv_max',vv_max46164617p_min = self.project(vv_min)4618p_max = self.project(vv_max)46194620# print 'p_min',p_min4621# print 'p_max',p_max46224623dp = np.abs(np.array(p_max-p_min, float))46244625# print ' dp',dp,dp==np.nan,np.nan4626if np.isnan(np.sum(dp)):4627return46284629window = np.array([self.g_Width, self.g_Height], float)4630zoomfactor = 0.8*np.min(window/dp[:2])46314632# print ' zoomfactor,zoom',zoomfactor,self.zoom46334634self.zoom /= zoomfactor4635# print ' zoomfactor',zoomfactor,self.zoom46364637self.draw()4638#vv_min, vv_max = self.get_boundingbox()46394640# lowerleft corner4641vv_target = self.unproject((0.0, self.g_Height))46424643# print ' vv_min',vv_min4644# print ' vv_target',vv_target4645# print ' trans',self.trans4646dv = 0.9*vv_target-vv_min46474648# print ' dv',dv4649newtrans = np.array(self.trans) + dv[:2]4650self.trans = tuple(newtrans)4651# print ' trans',self.trans4652self.draw()46534654def get_boundingbox(self):4655drawing = self.get_drawing()4656vv_min = np.inf * np.ones((1, 3), float)4657vv_max = -np.inf * np.ones((1, 3), float)4658if drawing:4659for drawobj in drawing.get_drawobjs():4660bb = drawobj.get_boundingbox()4661if bb is not None:4662v_min, v_max = bb4663# print ' v_min',v_min4664# print ' v_max',v_max4665vv_min = np.concatenate((vv_min, v_min.reshape(1, 3)), 0)4666vv_max = np.concatenate((vv_max, v_max.reshape(1, 3)), 0)4667# print ' vv_min',vv_min4668# print ' vv_max',vv_max4669vv_min = np.min(vv_min, 0)4670vv_max = np.max(vv_max, 0)4671return vv_min, vv_max46724673def zoom_in(self, event=None, is_draw=True):4674self.zoom *= 0.94675if is_draw:4676self.draw()46774678def zoom_out(self, event=None, is_draw=True):4679self.zoom *= 1.14680if is_draw:4681self.draw()46824683def OnLeftDown(self, event, is_draw=False):4684# print 'GLCanvas.OnLeftDown',self._tool4685is_control_down = event.ControlDown() # | event.RawControlDown() | event.MetaDown()4686if (is_control_down & event.ShiftDown()) & (self.action == ''):4687self.action = 'drag'4688self.BeginGrap(event)4689event.Skip()46904691elif self._tool is not None:4692is_draw = self._tool.on_left_down(event)46934694if is_draw:4695self.draw()4696event.Skip()46974698def OnLeftDclick(self, event, is_draw=False):4699if self._tool is not None:4700is_draw = self._tool.on_left_dclick(event)47014702if is_draw:4703self.draw()4704event.Skip()47054706def OnLeftUp(self, event, is_draw=False):47074708if self.action == 'drag':4709self.EndGrap(event)4710self.action == ''4711event.Skip()47124713elif self._tool is not None:4714is_draw = self._tool.on_left_up(event)47154716if is_draw:4717self.draw()4718event.Skip()47194720def OnRightDown(self, event, is_draw=False):4721if self._tool is not None:4722is_draw = self._tool.on_right_down(event)47234724if is_draw:4725self.draw()4726event.Skip()47274728def OnRightUp(self, event, is_draw=False):47294730if self._tool is not None:4731is_draw = self._tool.on_right_up(event)47324733if is_draw:4734self.draw()4735event.Skip()47364737def OnMotion(self, event, is_draw=False):4738# print 'OnMotion',event.GetPosition()4739self.GetParent().display_coords(self.unproject_event(event))47404741if (event.ControlDown() & event.ShiftDown() & (self.action == 'drag')):4742self.MoveGrap(event)4743is_draw |= True4744event.Skip()47454746elif (self.action == 'drag'):4747self.EndGrap(event)4748is_draw |= True4749self.action == ''4750event.Skip()47514752elif self._tool is not None:4753is_draw |= self._tool.on_motion(event)47544755if is_draw:4756self.draw()47574758def BeginGrap(self, event):4759# http://www.wxpython.org/docs/api/wx.Cursor-class.html4760self._cursor_last = self.GetCursor()4761self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))4762self.pos_start = event.GetPosition()4763self.trans_start = self.trans4764# print 'BeginGrap',self.trans47654766def MoveGrap(self, event):47674768x, y = self.unproject(event.GetPosition())[0:2]4769x0, y0 = self.unproject(self.pos_start)[0:2]47704771self.trans = (self.trans_start[0] + (x-x0), self.trans_start[1] + (y-y0))4772# print 'MoveGrap',self.trans, x,y47734774def EndGrap(self, event):4775# print 'EndGrap'4776self.SetCursor(self._cursor_last)4777self.action = ''47784779def OnWheel(self, event, is_draw=False):4780#EventType = FloatCanvas.EVT_FC_MOUSEWHEEL4781#4782Rot = event.GetWheelRotation()4783# print 'OnWheel!!',Rot,event.ControlDown(),event.ShiftDown()4784if (not event.ShiftDown()) & event.ControlDown(): # event.ControlDown(): # zoom4785if Rot < 0:4786self.zoom_in(is_draw=False)4787else:4788self.zoom_out(is_draw=False)4789is_draw |= True47904791if (event.ShiftDown()) & event.ControlDown(): # event.ControlDown(): # zoom4792if Rot < 0:4793self.xRotate -= 5.04794else:4795self.xRotate += 5.04796is_draw |= True47974798elif self._tool is not None:4799is_draw |= self._tool.on_wheel(event)4800self.draw()4801event.Skip()48024803if is_draw:4804self.draw()4805event.Skip()480648074808class OGLcanvasTools(ToolsPanel):4809"""4810Shows a toolpallet with different tools and an options panel.4811Here tools are added which4812"""48134814def __init__(self, parent):4815ToolsPanel.__init__(self, parent, n_buttoncolumns=3, size=wx.DefaultSize)48164817# add ainitial tool4818self.add_initial_tool(SelectTool(self))48194820# self.add_tool(HandleTool(self))4821self.add_tool(StretchTool(self))4822self.add_tool(MoveTool(self))48234824self.add_tool(AddLineTool(self))4825self.add_tool(AddCircleTool(self))4826self.add_tool(AddPolylineTool(self))4827self.add_tool(AddPolygonTool(self))48284829self.add_tool(DeleteTool(self))48304831self.add_tool(ConfigureTool(self))4832# more tools can be added later...483348344835class OGleditor(wx.Panel):48364837def __init__(self, parent,4838mainframe=None,4839size=wx.DefaultSize,4840is_menu=False, # create menu items4841Debug=0,4842):48434844self._drawing = None48454846# if drawing is not None:....4847self.prefix_anim = 'anim_'4848self.layer_anim = 1000.048494850wx.Panel.__init__(self, parent, wx.ID_ANY, size=size)4851sizer = wx.BoxSizer(wx.HORIZONTAL)48524853self._mainframe = mainframe48544855# initialize GL canvas4856navcanvas = OGLnavcanvas(self, mainframe)4857#self._canvas = OGLcanvas(self)4858self._canvas = navcanvas.get_canvas()48594860# compose tool pallet here4861self._toolspanel = OGLcanvasTools(self)48624863# compose editor window48644865# works but toolpanel changes size!!!4866# sizer.Add(self._toolspanel,0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4)# from NaviPanelTest4867# sizer.Add(navcanvas,1,wx.GROW)48684869# print 'OGleditor!!!!!!!!!!!!!!!!!!!'48704871# 2.8 OK for 3.0 also4872sizer.Add(self._toolspanel, 0, wx.EXPAND)4873sizer.Add(navcanvas, 1, wx.EXPAND)48744875self.SetAutoLayout(True)48764877# finish panel setup4878self.SetSizer(sizer)4879# sizer.Fit(self)4880# self.Layout()48814882# no use:4883#wx.EVT_SIZE(self, self.on_size)48844885def on_test(self, event=None, drawing=None):4886print '\non_test'48874888if drawing is None:4889drawing = OGLdrawing()4890vertices = np.array([4891[[0.0, 0.0, 0.0], [0.2, 0.0, 0.0]], # 0 green4892[[0.0, 0.0, 0.0], [0.0, 0.9, 0.0]], # 1 red4893])48944895colors = np.array([4896[0.0, 0.9, 0.0, 0.9], # 04897[0.9, 0.0, 0.0, 0.9], # 14898])48994900colors2 = np.array([4901[0.5, 0.9, 0.5, 0.5], # 04902[0.9, 0.5, 0.9, 0.5], # 14903])4904colors2o = np.array([4905[0.8, 0.9, 0.8, 0.9], # 04906[0.9, 0.8, 0.9, 0.9], # 14907])490849094910# -------------------------------------------------------------------------------49114912if 1:4913lines = Lines('lines', drawing)4914lines.add_drawobjs(vertices, colors)4915drawing.add_drawobj(lines)491649174918# -------------------------------------------------------------------------------49194920if 1:4921rectangles = Rectangles('rectangles', drawing,4922is_fill=True,4923is_outline=True)49244925colors = np.array([4926[0.2, 0.9, 0.0, 0.9], # 04927[0.9, 0.2, 0.0, 0.9], # 14928])49294930colors2 = np.array([4931[0.9, 0.9, 0.5, 0.3], # 04932[0.9, 0.9, 0.5, 0.3], # 14933])49344935rectangles.add_drawobjs([[3.0, 0.0, 0.0], [0.0, 3.0, 0.0]], # offsets4936widths=[1.0, 1.6],4937lengths=[2.0, 0.4],4938rotangles_xy=[0, 0.5],4939colors=colors,4940colors_fill=colors2)4941drawing.add_drawobj(rectangles)494249434944# -------------------------------------------------------------------------------4945if 1:4946fancylines = Fancylines('fancylines', drawing,4947arrowstretch=1.0,4948is_lefthalf=True,4949is_righthalf=True4950)49514952colors_fancy = np.array([4953[0.0, 0.9, 0.0, 0.9], # 04954# [0.9,0.0,0.0,0.9], # 14955])4956vertices_fancy = np.array([4957[[0.0, -1.0, 0.0], [2, -1.0, 0.0]], # 0 green4958# [[0.0,-1.0,0.0],[0.0,-5.0,0.0]],# 1 red4959])49604961widths = [0.5,4962# 0.3,4963]4964# print ' vertices_fancy\n',vertices_fancy4965# FLATHEAD = 04966#BEVELHEAD = 14967#TRIANGLEHEAD = 24968#ARROWHEAD = 34969fancylines.add_drawobjs(vertices_fancy,4970widths, # width4971colors_fancy,4972beginstyles=[TRIANGLEHEAD, ],4973endstyles=[TRIANGLEHEAD, ],4974)4975drawing.add_drawobj(fancylines, layer=10)4976# -------------------------------------------------------------------------------4977if 1:4978polylines = Polylines('polylines', drawing,4979joinstyle=FLATHEAD,4980arrowstretch=1.0,4981is_lefthalf=True,4982is_righthalf=True4983)4984colors_poly = np.array([4985[0.0, 0.8, 0.5, 0.9], # 04986[0.8, 0.0, 0.5, 0.9], # 14987])49884989vertices_poly = np.array([4990[[0.0, 2.0, 0.0], [5.0, 2.0, 0.0], [5.0, 7.0, 0.0], [10.0, 7.0, 0.0]], # 0 green4991[[0.0, -2.0, 0.0], [-2.0, -2.0, 0.0]], # 1 red4992], np.object)49934994widths = [0.5,49950.3,4996]4997# print ' vertices_poly\n',vertices_poly4998polylines.add_drawobjs(vertices_poly,4999widths, # width5000colors_poly,5001beginstyles=[TRIANGLEHEAD, TRIANGLEHEAD],5002endstyles=[TRIANGLEHEAD, TRIANGLEHEAD])5003drawing.add_drawobj(polylines, layer=-2)50045005# -------------------------------------------------------------------------------5006if 1:5007polygons = Polygons('polygons', drawing, linewidth=5)5008colors_poly = np.array([5009[0.0, 0.9, 0.9, 0.9], # 05010[0.8, 0.2, 0.2, 0.9], # 15011])50125013vertices_poly = [5014[[0.0, 2.0, 0.0], [5.0, 2.0, 0.0], [5.0, 7.0, 0.0], ], # 0 green5015[[0.0, -2.0, 0.0], [-2.0, -2.0, 0.0], [-2.0, 0.0, 0.0]], # 1 red5016]50175018print ' vertices_polygon\n', vertices_poly5019polygons.add_drawobjs(vertices_poly,5020colors_poly)5021polygons.add_drawobj([[5.0, -2.0, 0.0], [3.0, -2.0, 0.0], [3.0, 0.0, 0.0]],5022[0.8, 0.2, 0.8, 0.9])5023drawing.add_drawobj(polygons)502450255026# -------------------------------------------------------------------------------50275028if 1:5029circles = Circles('circles', drawing,5030is_fill=False, # Fill objects,5031is_outline=True, # show outlines5032)5033circles.add_drawobjs([[0.0, 0.0, 0.0], [1.0, 0.5, 0.0]], [0.5, 0.25], colors2o, colors2)5034drawing.add_drawobj(circles)50355036# canvas.zoom_tofit()5037# wx.CallAfter(canvas.zoom_tofit)5038self.add_drawobjs_anim(drawing)5039self.set_drawing(drawing)5040if event:5041event.Skip()50425043def get_canvas(self):5044# DEPRICATED: canvas should not be needed outside netwdit5045# this is used mainly by the tools to know on which canvas to operate on5046# if multiple canvas, use the one with focus5047return self._canvas50485049def draw(self):50505051self._canvas.draw()5052# in the future there can be the same drawing on multiple canvases50535054def get_toolbox(self):5055return self._toolspanel50565057def add_toolclass(self, Toolclass, **kwargs):5058"""5059Add a new Toolclas to the tool-panel on the right side of the editor5060"""5061self.get_toolbox().add_toolclass(Toolclass, **kwargs)50625063def set_drawing(self, drawing):5064# self._toolspanel.reset_initial_tool()5065# here ad some additional drawing objects for animation5066# self.add_drawobjs_anim(drawing)5067self._drawing = drawing5068self._canvas.set_drawing(drawing)5069self._toolspanel.reset_initial_tool()50705071# wx.CallAfter(self._canvas.zoom_tofit)50725073def get_drawing(self):5074return self._drawing # self._canvas.get_drawing()50755076def add_drawobjs_anim(self, drawing=None):50775078if drawing is None:5079drawing = self._drawing5080drawobjs_anim = [Lines(self.prefix_anim+'lines', drawing,5081linewidth=1),50825083Rectangles(self.prefix_anim+'rectangles', drawing,5084linewidth=1,5085),50865087Fancylines(self.prefix_anim+'fancylines', drawing,5088is_lefthalf=True,5089is_righthalf=True,5090linewidth=1,5091),50925093Lines(self.prefix_anim+'lines', drawing,5094linewidth=1),50955096Polylines(self.prefix_anim+'polylines', drawing,5097joinstyle=FLATHEAD,5098is_lefthalf=True,5099is_righthalf=True,5100linewidth=1,5101),51025103Polygons(self.prefix_anim+'polygons', drawing,5104linewidth=1),51055106Circles(self.prefix_anim+'circles', drawing,5107is_fill=False, # Fill objects,5108is_outline=True, # show outlines5109linewidth=1,5110),51115112Triangles(self.prefix_anim+'triangles', drawing,5113is_fill=False, # Fill objects,5114is_outline=True, # show outlines5115linewidth=1,5116),5117]51185119for drawobj in drawobjs_anim:5120drawing.add_drawobj(drawobj, layer=self.layer_anim)51215122def get_mainframe(self):5123# this is used mainly by the tools to know on which mainframe to operate on5124return self._mainframe51255126# def on_size(self,event=None):5127# #print 'on_size',self._toolspanel.GetSize()5128#5129# if event:5130# event.Skip()513151325133if __name__ == '__main__':5134###############################################################################5135# MAIN FRAME51365137from mainframe import AgileToolbarFrameMixin51385139class OGLeditorMainframe(AgileToolbarFrameMixin, wx.Frame):5140"""5141Simple wx frame with some special features.5142"""51435144def __init__(self, title, pos=wx.DefaultPosition,5145size=(1000, 500), style=wx.DEFAULT_FRAME_STYLE,5146name='frame'):51475148# Forcing a specific style on the window.5149# Should this include styles passed?5150style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE5151wx.Frame.__init__(self, None, wx.NewId(), title, pos, size=size, style=style, name=name)5152self.gleditor = OGleditor(self)51535154self.Show() # must be here , before putting stuff on canvas51555156#################################################################5157# create the menu bar51585159self.menubar = AgileMenubar(self)5160self.make_menu()5161# self.menubar.append_menu('tools')5162self.SetMenuBar(self.menubar)5163self.on_test()51645165def make_menu(self, event=None):5166self.menubar.append_menu('file')5167# self.menubar.append_item('file/test',self.on_test,\5168# shortkey='Ctrl+t',info='Draw test objects')51695170def on_test(self, event=None):5171print '\non_test'5172vertices = np.array([5173[[0.0, 0.0, 0.0], [0.2, 0.0, 0.0]], # 0 green5174[[0.0, 0.0, 0.0], [0.0, 0.9, 0.0]], # 1 red5175])51765177colors = np.array([5178[0.0, 0.9, 0.0, 0.9], # 05179[0.9, 0.0, 0.0, 0.9], # 15180])51815182colors2 = np.array([5183[0.5, 0.9, 0.5, 0.5], # 05184[0.9, 0.5, 0.9, 0.5], # 15185])5186colors2o = np.array([5187[0.8, 0.9, 0.8, 0.9], # 05188[0.9, 0.8, 0.9, 0.9], # 15189])51905191drawing = OGLdrawing()5192# -------------------------------------------------------------------------------51935194if 1:5195lines = Lines('lines', drawing)5196lines.add_drawobjs(vertices, colors)5197drawing.add_drawobj(lines)51985199# -------------------------------------------------------------------------------5200if 1:5201triangles = Triangles('triangles', drawing,5202is_fill=True,5203is_outline=True)5204triangles.add_drawobjs(np.array([5205[[0.0, 0.0, 0.0], [1.5, 0.0, 0.0], [1.5, 2.5, 0.0]], # 0 green5206[[0.0, 0.0, 0.0], [-1.5, -0.9, 0.0], [-1.0, -2.5, 0.0]], # 1 red5207]), colors2, colors2o)5208drawing.add_drawobj(triangles)520952105211# -------------------------------------------------------------------------------52125213if 1:5214rectangles = Rectangles('rectangles', drawing,5215is_fill=True,5216is_outline=True)52175218colors = np.array([5219[0.2, 0.9, 0.0, 0.9], # 05220[0.9, 0.2, 0.0, 0.9], # 15221])52225223colors2 = np.array([5224[0.9, 0.9, 0.5, 0.3], # 05225[0.9, 0.9, 0.5, 0.3], # 15226])52275228rectangles.add_drawobjs([[3.0, 0.0, 0.0], [0.0, 3.0, 0.0]], # offsets5229widths=[1.0, 1.6],5230lengths=[2.0, 0.4],5231rotangles_xy=[0, 0.5],5232colors=colors,5233colors_fill=colors2)5234drawing.add_drawobj(rectangles)523552365237# -------------------------------------------------------------------------------5238if 1:5239fancylines = Fancylines('fancylines', drawing,5240arrowstretch=1.0,5241is_lefthalf=True,5242is_righthalf=True5243)52445245colors_fancy = np.array([5246[0.0, 0.9, 0.0, 0.9], # 05247# [0.9,0.0,0.0,0.9], # 15248])5249vertices_fancy = np.array([5250[[0.0, -1.0, 0.0], [2, -1.0, 0.0]], # 0 green5251# [[0.0,-1.0,0.0],[0.0,-5.0,0.0]],# 1 red5252])52535254widths = [0.5,5255# 0.3,5256]5257# print ' vertices_fancy\n',vertices_fancy5258# FLATHEAD = 05259#BEVELHEAD = 15260#TRIANGLEHEAD = 25261#ARROWHEAD = 35262fancylines.add_drawobjs(vertices_fancy,5263widths, # width5264colors_fancy,5265beginstyles=[TRIANGLEHEAD, ],5266endstyles=[TRIANGLEHEAD, ],5267)5268drawing.add_drawobj(fancylines, layer=10)5269# -------------------------------------------------------------------------------5270if 1:5271polylines = Polylines('polylines', drawing,5272joinstyle=FLATHEAD,5273arrowstretch=1.0,5274is_lefthalf=True,5275is_righthalf=True5276)5277colors_poly = np.array([5278[0.0, 0.8, 0.5, 0.9], # 05279[0.8, 0.0, 0.5, 0.9], # 15280])52815282vertices_poly = np.array([5283[[0.0, 2.0, 0.0], [5.0, 2.0, 0.0], [5.0, 7.0, 0.0], [10.0, 7.0, 0.0]], # 0 green5284[[0.0, -2.0, 0.0], [-2.0, -2.0, 0.0]], # 1 red5285], np.object)52865287widths = [0.5,52880.3,5289]5290# print ' vertices_poly\n',vertices_poly5291polylines.add_drawobjs(vertices_poly,5292widths, # width5293colors_poly,5294beginstyles=[TRIANGLEHEAD, TRIANGLEHEAD],5295endstyles=[TRIANGLEHEAD, TRIANGLEHEAD])5296drawing.add_drawobj(polylines, layer=-2)52975298# -------------------------------------------------------------------------------5299if 1:5300polygons = Polygons('polygons', drawing, linewidth=5)5301colors_poly = np.array([5302[0.0, 0.9, 0.9, 0.9], # 05303[0.8, 0.2, 0.2, 0.9], # 15304])53055306vertices_poly = [5307[[0.0, 2.0, 0.0], [5.0, 2.0, 0.0], [5.0, 7.0, 0.0], ], # 0 green5308[[0.0, -2.0, 0.0], [-2.0, -2.0, 0.0], [-2.0, 0.0, 0.0]], # 1 red5309]53105311print ' vertices_polygon\n', vertices_poly5312polygons.add_drawobjs(vertices_poly,5313colors_poly)5314polygons.add_drawobj([[5.0, -2.0, 0.0], [3.0, -2.0, 0.0], [3.0, 0.0, 0.0]],5315[0.8, 0.2, 0.8, 0.9])5316drawing.add_drawobj(polygons)531753185319# -------------------------------------------------------------------------------53205321if 1:5322circles = Circles('circles', drawing,5323is_fill=False, # Fill objects,5324is_outline=True, # show outlines5325)5326circles.add_drawobjs([[0.0, 0.0, 0.0], [1.0, 0.5, 0.0]], [0.5, 0.25], colors2o, colors2)5327drawing.add_drawobj(circles)53285329# drawing.add_drawobj(testogl.triangles)5330# drawing.add_drawobj(testogl.rectangles)5331# -------------------------------------------------------------------------------53325333#canvas = self.gleditor.get_canvas()5334# canvas.set_drawing(drawing)53355336#lines.add_drawobj([[0.0,0.0,0.0],[-0.2,-0.8,0.0]], [0.0,0.9,0.9,0.9])5337#circles.add_drawobj([1.5,0.0,0.0],0.6,colors2o[0], colors2[0])53385339# canvas.zoom_tofit()5340# wx.CallAfter(canvas.zoom_tofit)5341self.gleditor.add_drawobjs_anim(drawing)5342self.gleditor.set_drawing(drawing)5343if event:5344event.Skip()53455346def get_objbrowser(self):5347return self._objbrowser53485349class OGLeditorApp(wx.App):5350def OnInit(self):5351# wx.InitAllImageHandlers()5352self.mainframe = OGLeditorMainframe("OGLeditor")5353#sumopyicon = wx.Icon(os.path.join(IMAGEDIR,'icon_sumopy.png'),wx.BITMAP_TYPE_PNG, 16,16)5354# wx.Frame.SetIcon(self.mainframe,sumopyicon)5355# self.mainframe.SetIcon(sumopyicon)53565357# if True: #len(sys.argv)>=2:5358# from lib.net import readNet5359# filepath = '/home/joerg/projects/sumopy/bologna/bologna4.net.xml'#sys.argv[1]5360# _net = readNet(filepath)5361# else:5362# _net = None53635364self.SetTopWindow(self.mainframe)5365return True53665367###########################################################################5368# MAINLOOP53695370if len(sys.argv) == 3:5371ident = sys.argv[1]5372dirpath = sys.argv[2]5373else:5374ident = None5375dirpath = None5376app = OGLeditorApp(0)53775378if 0: # len(noplugins)>0:5379_msg = """The following plugins could not be plugged in:\n\n """ + noplugins[:-2] +\5380"""\n\nIf you like to use these plugins, please check messages on console for Import errors and install the required packages.5381"""5382dlg = wx.MessageDialog(None, _msg, "Warning from Plugins", wx.OK | wx.ICON_WARNING)5383dlg.ShowModal()5384dlg.Destroy()53855386app.MainLoop()538753885389