Skip to content

Commit

Permalink
adding spaceball mouse support; use the json preferences file
Browse files Browse the repository at this point in the history
  • Loading branch information
SteveDoyle2 committed Oct 8, 2024
1 parent fbedcd3 commit b7a7995
Show file tree
Hide file tree
Showing 16 changed files with 325 additions and 196 deletions.
43 changes: 41 additions & 2 deletions pyNastran/bdf/bdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@
from .bdf_interface.stats import get_bdf_stats

from .errors import (CrossReferenceError, DuplicateIDsError,
CardParseSyntaxError, UnsupportedCard, DisabledCardError,
SuperelementFlagError, ReplicationError)
CardParseSyntaxError, UnsupportedCard, DisabledCardError,
SuperelementFlagError, ReplicationError)
from .bdf_interface.pybdf import (
BDFInputPy, _clean_comment, _clean_comment_bulk, _check_for_spaces,
add_superelements_from_deck_lines,
Expand All @@ -206,6 +206,45 @@
if TYPE_CHECKING: # pragma: no cover
from cpylog import SimpleLogger

Element = (
CELAS1 | CELAS2 | CELAS3 | CELAS4 |
CDAMP1 | CDAMP2 | CDAMP3 | CDAMP4 | CDAMP5 |
CVISC | CBUSH | CBUSH1D | CBUSH2D | CFAST | #CWELD
CGAP | GENEL | CCONEAX |
CROD | CTUBE | CONROD |
CBAR | CBEAM | CBEAM3 | CBEND | CSHEAR |
CTRIA3 | CTRIA6 | CTRIAR |
CQUAD4 | CQUAD8 | CQUADR | CQUAD |
CTRIAX | CTRIAX6 |
CQUADX | CQUADX4 | CQUADX8 |
CRAC2D | CRAC3D |
CPLSTN3 | CPLSTN4 | CPLSTN6 | CPLSTN8 |
CPLSTS3 | #CPLSTS4 | CPLSTS6 | CPLSTS8 |
CTETRA4 | CTETRA10 | CPENTA6 | CPENTA15 |
CHEXA8 | CHEXA20 | CPYRAM5 | CPYRAM13 |
CTRAX3 | CTRAX6 |
# thermal
CHBDYE |CHBDYG | CHBDYP |
# Nastran 95
CIHEX1 | CIHEX2 |
CHEXA1 | CHEXA2)
Property = (
PELAS | PELAST | PDAMP | PDAMPT | PDAMP5 | PMASS |
PROD | PTUBE | PVISC |
PBUSH | PBUSH1D | PBUSH2D | PGAP |
PRAC2D | PRAC3D | PCONEAX |
PBAR | PBARL | PBEAM | PBRSECT |
PBEAML | PBCOMP | PBMSECT |
PBEND | PBEAM3 |
PSHEAR | PPLANE |
PSHELL | PCOMP | PCOMPG |
PSOLID | PLSOLID | PIHEX | PCOMPS | PCOMPLS |
PTRSHL #| PWELD
)
Material = (
MAT1 | MAT2 | MAT3 | MAT8 | MAT9 | MAT10 | MAT11 |
MAT3D | EQUIV | MATG)
ThermalMaterial = MAT4 | MAT5
CORD = CORD1R | CORD1C | CORD1S | CORD2R | CORD2C | CORD2S

REMOVED_CARDS = {
Expand Down
207 changes: 92 additions & 115 deletions pyNastran/bdf/bdf_interface/add_methods.py

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions pyNastran/bdf/bdf_interface/get_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pyNastran.bdf.bdf_interface.attributes import BDFAttributes
from pyNastran.utils.numpy_utils import integer_types
if TYPE_CHECKING: # pragma: no cover
from pyNastran.bdf.bdf import BDF
from pyNastran.bdf.bdf import BDF, Element, Property, Material, ThermalMaterial
from pyNastran.bdf.cards.coordinate_systems import Coord
from pyNastran.bdf.cards.nodes import POINT, GRID, SPOINT, EPOINT # , SPOINTs, EPOINTs, SEQGP, GRIDB
from pyNastran.bdf.cards.aero.aero import (
Expand Down Expand Up @@ -261,7 +261,7 @@ def RigidElement(self, eid: int, msg: str='') -> Union[RBAR, RBE1, RBE2, RBE3, R

#--------------------
# PROPERTY CARDS
def Property(self, pid: int, msg: str='') -> Any:
def Property(self, pid: int, msg: str='') -> Property:
"""
gets an elemental property (e.g. PSOLID, PLSOLID, PCOMP, PSHELL, PSHEAR);
not mass property (PMASS)
Expand Down Expand Up @@ -321,7 +321,7 @@ def get_thermal_material_ids(self) -> Iterable[int]:
"""gets the thermal material ids"""
return self.thermal_materials.keys()

def Material(self, mid: int, msg: str='') -> Union[MAT1, MAT2, MAT3, MAT4, MAT5, MAT8, MAT9, MAT10, MAT11, MAT3D, EQUIV, MATG]:
def Material(self, mid: int, msg: str='') -> Material | ThermalMaterial:
"""gets a structural or thermal material"""
if mid in self.materials:
return self.materials[mid]
Expand All @@ -336,7 +336,7 @@ def Material(self, mid: int, msg: str='') -> Union[MAT1, MAT2, MAT3, MAT4, MAT5,
)
raise KeyError(msg2)

def StructuralMaterial(self, mid, msg='') -> Union[MAT1, MAT2, MAT3, MAT8, MAT9, MAT10, MAT11, MAT3D, EQUIV, MATG]:
def StructuralMaterial(self, mid, msg='') -> Material:
"""gets a structural material"""
try:
mat = self.materials[mid]
Expand All @@ -363,7 +363,7 @@ def HyperelasticMaterial(self, mid: int, msg: str='') -> Union[MATHE, MATHP]:
raise KeyError('Invalid Hyperelastic Material ID: mid=%s%s' % (mid, msg))
return mat

def Materials(self, mids, msg='') -> list[Union[MAT1, MAT2, MAT3, MAT8, MAT9, MAT10, MAT11, MAT3D, EQUIV, MATG]]:
def Materials(self, mids, msg='') -> list[Material]:
"""gets one or more Materials"""
if isinstance(mids, integer_types):
mids = [mids]
Expand Down
54 changes: 29 additions & 25 deletions pyNastran/bdf/bdf_interface/safe_cross_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
Safe cross-referencing skips failed xref's
"""
from __future__ import annotations
from collections import defaultdict
from typing import Any
from typing import Any, TYPE_CHECKING

import numpy as np
from numpy import zeros, argsort, arange, array_equal
from pyNastran.bdf.bdf_interface.cross_reference import XrefMesh

if TYPE_CHECKING:
from pyNastran.bdf.bdf import Element, Property #, GRID
from pyNastran.bdf.cards.nodes import GRID

class SafeXrefMesh(XrefMesh):
"""
Expand All @@ -28,21 +31,21 @@ def __init__(self) -> None:
# for elem in model.elements:
# elem.check_unique_nodes()

def safe_cross_reference(self, xref=True,
xref_nodes=True,
xref_elements=True,
xref_nodes_with_elements=False,
xref_properties=True,
xref_masses=True,
xref_materials=True,
xref_loads=True,
xref_constraints=True,
xref_aero=True,
xref_sets=True,
xref_optimization=True,
create_superelement_geometry=False,
def safe_cross_reference(self, xref: bool=True,
xref_nodes: bool=True,
xref_elements: bool=True,
xref_nodes_with_elements: bool=False,
xref_properties: bool=True,
xref_masses: bool=True,
xref_materials: bool=True,
xref_loads: bool=True,
xref_constraints: bool=True,
xref_aero: bool=True,
xref_sets: bool=True,
xref_optimization: bool=True,
create_superelement_geometry: bool=False,
debug=True,
word=''):
word: str='') -> None:
"""
Performs cross referencing in a way that skips data gracefully.
Expand Down Expand Up @@ -85,7 +88,7 @@ def safe_cross_reference(self, xref=True,
self.pop_xref_errors()
for superelement_tuple, superelement in sorted(self.superelement_models.items()):
if isinstance(superelement_tuple, int):
word = f' (Superelement {super_tuple:d})'
word = f' (Superelement {superelement_tuple:d})'
else:
wordi, value, label = superelement_tuple
if label:
Expand Down Expand Up @@ -382,7 +385,7 @@ def _safe_cross_reference_optimization(self) -> None:
for unused_key, topvar in self.topvar.items():
topvar.safe_cross_reference(self)

def safe_empty_nodes(self, nids, msg=''):
def safe_empty_nodes(self, nids: list[int], msg: str='') -> tuple[list[GRID], list[int]]:
"""safe xref version of self.Nodes(nid, msg='')"""
nodes = []
missing_nodes = []
Expand All @@ -398,7 +401,7 @@ def safe_empty_nodes(self, nids, msg=''):
self.log.warning('Nodes %s are missing%s' % (str(missing_nodes), msg))
return nodes, missing_nodes

def safe_get_nodes(self, nids: list[int], msg: str='') -> tuple[list[Any], str]:
def safe_get_nodes(self, nids: list[int], msg: str='') -> tuple[list[GRID], str]:
"""safe xref version of self.Nodes(nid, msg='')"""
nodes = []
error_nodes = []
Expand All @@ -414,7 +417,7 @@ def safe_get_nodes(self, nids: list[int], msg: str='') -> tuple[list[Any], str]:
msgi += 'Could not find nodes %s%s\n' % (', '.join(error_nodes), msg)
return nodes, msgi

def safe_get_points(self, point_ids, msg=''):
def safe_get_points(self, point_ids: list[int], msg: str=''):
"""safe xref version of self.Points(point_ids, msg='')"""
points = []
error_points = []
Expand All @@ -430,7 +433,7 @@ def safe_get_points(self, point_ids, msg=''):
msgi += 'Could not find POINTs %s%s\n' % (', '.join(error_points), msg)
return points, msgi

def safe_get_elements(self, eids, msg=''):
def safe_get_elements(self, eids: list[int], msg: str=''):
"""safe xref version of self.Elements(eid, msg='')"""
elements = []
msgi = ''
Expand All @@ -443,7 +446,7 @@ def safe_get_elements(self, eids, msg=''):
elements.append(element)
return elements, msgi

def safe_element(self, eid, ref_id, xref_errors, msg=''):
def safe_element(self, eid: int, ref_id: int, xref_errors, msg: str='') -> ELement:
"""
Gets an element card
Expand All @@ -466,8 +469,9 @@ def safe_element(self, eid, ref_id, xref_errors, msg=''):
xref_errors['eid'].append((ref_id, eid))
return eid_ref

def safe_elements(self, eids, ref_id: int,
xref_errors: dict[str, tuple[int, int]], msg=''):
def safe_elements(self, eids: list[int], ref_id: int,
xref_errors: dict[str, tuple[int, int]],
msg: str='') -> list[Element]:
"""
Gets an series of elements
Expand Down Expand Up @@ -497,7 +501,7 @@ def safe_elements(self, eids, ref_id: int,
#raise KeyError(msg)
return elements

def safe_property(self, pid, ref_id, xref_errors, msg=''):
def safe_property(self, pid: int, ref_id: int, xref_errors, msg: str='') -> Property:
"""
Parameters
----------
Expand Down
4 changes: 2 additions & 2 deletions pyNastran/bdf/cards/elements/mass.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def safe_cross_reference(self, model: BDF, xref_errors):
self.nodes_ref, missing_nodes = model.safe_empty_nodes(self.node_ids, msg=msg)
self.pid_ref = model.safe_property_mass(self.pid, self.eid, xref_errors, msg=msg)
if missing_nodes:
model.log.warning(missing_nodes)
model.log.warning(str(missing_nodes))

def uncross_reference(self) -> None:
"""Removes cross-reference links"""
Expand Down Expand Up @@ -500,7 +500,7 @@ def safe_cross_reference(self, model: BDF, xref_errors):
msg = ', which is required by CMASS2 eid=%s' % self.eid
self.nodes_ref, missing_nodes = model.safe_empty_nodes(self.node_ids, msg=msg)
if missing_nodes:
model.log.warning(missing_nodes)
model.log.warning(str(missing_nodes))

def uncross_reference(self) -> None:
"""Removes cross-reference links"""
Expand Down
3 changes: 1 addition & 2 deletions pyNastran/bdf/mesh_utils/mass_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
CHECK_MASS = False # should additional checks be done

if TYPE_CHECKING: # pragma: no cover
from pyNastran.bdf.bdf import BDF, NSM1, CQUAD4, CBAR, CBEAM, CROD, CONROD, CTRIA3
Element = CQUAD4 | CBAR | CBEAM | CROD | CONROD | CTRIA3
from pyNastran.bdf.bdf import BDF, NSM1, CQUAD4, CBAR, CBEAM, CROD, CONROD, CTRIA3, Element

NO_MASS = {
# has mass
Expand Down
20 changes: 15 additions & 5 deletions pyNastran/gui/dev/gui2/vtk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
from vtkmodules.vtkRenderingCore import vtkRenderer
from pyNastran.gui.qt_files.colors import BLACK_FLOAT
from pyNastran.gui.qt_files.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from pyNastran.gui.styles.trackball_style_camera import TrackballStyleCamera
from pyNastran.gui.styles.trackball_style_camera import TrackballStyleCamera, JoystickStyleCamera

if TYPE_CHECKING: # pragma: no cover
import numpy as np
from cpylog import SimpleLogger
from pyNastran.gui.dev.gui2.gui2 import MainWindow2
from vtkmodules.vtkInteractionStyle import vtkInteractor


class ScalarBar:
Expand All @@ -30,6 +32,7 @@ def __init__(self, gui: MainWindow2, parent):

self.vtk_interactor = QVTKRenderWindowInteractor(parent=parent)
self.set_style_as_trackball()
#self.set_style_as_joystick()

self.rend = vtkRenderer()
#self.vtk_interactor.GetRenderWindow().AddRenderer(self.rend)
Expand All @@ -46,15 +49,23 @@ def settings(self) -> Settings:
return self.gui.settings

@property
def log(self):
def log(self) -> SimpleLogger:
return self.gui.log

def set_style_as_trackball(self):
def set_style(self):
#self.mouse_actions.set_style_as_trackball()
self.mouse_actions.set_style_as_joystick()

def set_style_as_trackball(self) -> None:
"""sets the default rotation style"""
#self._simulate_key_press('t') # change mouse style to trackball
self.style = TrackballStyleCamera(self.vtk_interactor, self)
self.vtk_interactor.SetInteractorStyle(self.style)

def set_style_as_joystick(self) -> None:
self.style = JoystickStyleCamera(self.vtk_interactor, self)
self.vtk_interactor.SetInteractorStyle(self.style)

def set_quad_grid(self, box_name: str,
nodes: np.ndarray, elements: np.ndarray,
color: Optional[list[float]]=None,
Expand All @@ -67,7 +78,7 @@ def create_global_axes(self, dim_max: float) -> None:
self.log.warning('create_global_axes')


def fill_render_window(vtk_interactor,
def fill_render_window(vtk_interactor: vtkInteractor,
rend: vtkRenderer,
nframes: int=1) -> list[vtkRenderer]:
assert nframes in [1, 2, 4], nframes
Expand Down Expand Up @@ -126,4 +137,3 @@ def fill_render_window(vtk_interactor,
render_window.AddRenderer(rend4)
return [rend, rend2, rend3, rend4]
raise ValueError(nframes)

2 changes: 1 addition & 1 deletion pyNastran/gui/gui_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ def build_vtk_frame(self):
#self.rend.SetBackground2(*self.background_color2)

rend.ResetCamera()
self.mouse_actions.set_style_as_trackball()
self.mouse_actions.set_style()
self._build_vtk_frame_post()

def on_reset_camera(self):
Expand Down
14 changes: 14 additions & 0 deletions pyNastran/gui/gui_objects/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
LINE_WIDTH_MIN = 0.1
LINE_WIDTH_MAX = 2000.

IS_TRACKBALL_CAMERA = True
USE_PARALLEL_PROJECTION = True
DEFAULT_COLORMAP = 'jet'
NFILES_TO_SAVE = 9
Expand Down Expand Up @@ -325,6 +326,7 @@ def reset_settings(self, resize: bool=True,
self.shear_moment_torque_point_size = SHEAR_MOMENT_TORQUE_POINT_SIZE # float
self.shear_moment_torque_line_width = SHEAR_MOMENT_TORQUE_LINE_WIDTH # float

self.is_trackball_camera = IS_TRACKBALL_CAMERA
self.use_parallel_projection = USE_PARALLEL_PROJECTION
self.displacement_model_scale = DISPLACEMENT_MODEL_SCALE
self.show_info = True
Expand Down Expand Up @@ -398,6 +400,9 @@ def load(self, settings: QSettings) -> bool:
self.font_size, min_value=FONT_SIZE_MIN, max_value=None)

# parallel/perspective
self._set_setting(settings, setting_keys, ['is_trackball_camera'],
default=self.is_trackball_camera,
save=True, auto_type=bool)
self._set_setting(settings, setting_keys, ['use_parallel_projection'],
default=self.use_parallel_projection,
save=True, auto_type=bool)
Expand Down Expand Up @@ -695,6 +700,7 @@ def save(self, settings, is_testing: bool=False) -> None:
settings.setValue('main_window_state', parent.saveState())

# booleans
settings.setValue('is_trackball_camera', self.is_trackball_camera)
settings.setValue('use_parallel_projection', self.use_parallel_projection)
settings.setValue('use_gradient_background', self.use_gradient_background)

Expand Down Expand Up @@ -1112,6 +1118,14 @@ def set_magnify(self, magnify: int=5) -> None:
"""sets the screenshot magnification factor"""
self.magnify = magnify

def set_trackball_camera(self, is_trackball_camera: bool,
render: bool=True) -> None:
"""sets the parallel_projection flag"""
self.is_trackball_camera = is_trackball_camera
self.parent.mouse_settings.set_style()
if render:
self.parent.vtk_interactor.Render()

def set_parallel_projection(self, parallel_projection: bool,
render: bool=True) -> None:
"""sets the parallel_projection flag"""
Expand Down
Loading

0 comments on commit b7a7995

Please sign in to comment.