#
##
##  This file is part of pyFormex 2.4  (Thu Feb 25 13:39:20 CET 2021)
##  pyFormex is a tool for generating, manipulating and transforming 3D
##  geometrical models by sequences of mathematical operations.
##  Home page: http://pyformex.org
##  Project page:  http://savannah.nongnu.org/projects/pyformex/
##  Copyright 2004-2020 (C) Benedict Verhegghe (benedict.verhegghe@ugent.be)
##  Distributed under the GNU General Public License version 3 or later.
##
##  This program is free software: you can redistribute it and/or modify
##  it under the terms of the GNU General Public License as published by
##  the Free Software Foundation, either version 3 of the License, or
##  (at your option) any later version.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##
##  You should have received a copy of the GNU General Public License
##  along with this program.  If not, see http://www.gnu.org/licenses/.
##
"""Predefined camera viewing directions
"""
import re
RE_view = re.compile("(-?[xyz])(-?[xyz])")
[docs]def iconName(viewname):
    """Get the icon name for an axis view"""
    m = RE_view.match(viewname)
    if m:
        x, y = m.group(1), m.group(2)
        iconname = 'view-' + \
            
x[-1] + ('l' if x[0]=='-' else 'r') + '-' + \
            
y[-1] + ('d' if y[0]=='-' else 'u')
    elif viewname.startswith('iso'):
        iconname = 'view-iso1'
    else:
        iconname = viewname
    return iconname 
[docs]class ViewAngles(dict):
    """A dict to keep named camera angle settings.
    This class keeps a dictionary of named angle settings. Each value is
    a tuple of (longitude, latitude, twist) camera angles.
    This is a static class which should not need to be instantiated.
    There are seven predefined values: six for looking along global
    coordinate axes, one isometric view.
    """
    built_in_abs_views = {
        'xy': (0.,   0., 0.),
        'x-y': (0., 180., 0.),
        'xz': (0., -90., 0.),
        'x-z': (0.,  90., 0.),
        '-xy': (180.,   0., 0.),
        '-x-y': (180., 180., 0.),
        '-xz': (180.,  90., 0.),
        '-x-z': (180., -90., 0.),
        'yx': (180.,   0., 90.),
        'y-x': (0.,   0., 90.),
        'yz': (90.,   0., 90.),
        'y-z': (-90.,   0., 90.),
        '-yx': (0.,   0., -90.),
        '-y-x': (180.,   0., -90.),
        '-yz': (-90.,   0., -90.),
        '-y-z': (90.,   0., -90.),
        'zx': (-90.,  90., 0.),
        'z-x': (-90., -90., 0.),
        'zy': (-90.,   0., 0.),
        'z-y': (-90., 180., 0.),
        '-zx': (90., -90., 0.),
        '-z-x': (90.,  90., 0.),
        '-zy': (90.,   0., 0.),
        '-z-y': (90., 180., 0.),
        }
    built_in_rel_views = {
        'iso': (45., 35.2644, 0.),
        'iso0': (45., 35.2644, 0.),
        'iso1': (135., 35.2644, 0.),
        'iso2': (225., 35.2644, 0.),
        'iso3': (315., 35.2644, 0.),
        'iso4': (45., -35.2644, 0.),
        'iso5': (135., -35.2644, 0.),
        'iso6': (225., -35.2644, 0.),
        'iso7': (315., -35.2644, 0.),
        }
    aliases = ['front', 'back', 'right', 'left', 'top', 'bottom']
    buttons = aliases + ['iso0', 'iso3']
    defviews = {
        'xy': ['xy', '-xy', '-zy', 'zy', 'x-z', 'xz', 'iso0'],
        'xz': ['xz', '-xz', 'yz', '-yz', 'xy', 'x-y', 'iso0'],
    }
    defaxes = {
        'xy': ((0., -1., 0.), (1., 0., 0.), (0., 0., -1.)),
        'xz': ((0., 0., -1.), (1., 0., 0.), (0., 1., 0.)),
        }
    def __init__(self, data = built_in_rel_views):
       dict.__init__(self, data)
       for a, n in zip(ViewAngles.aliases, ViewAngles.defviews['xy']):
           self[a] = ViewAngles.built_in_abs_views[n]
       self.setOrientation('xz')
[docs]    def setOrientation(self, orient):
        """Set standard orientation.
        Parameters
        ----------
        orient: str
            The front orientation. Should be one of 'xy' or 'xz'.
            The other relative orientations are derived from it.
        Returns
        -------
        aliases: list
            List of standard relative orientations
        realnames:
            List of the real orientation anmes corresponding with aliases
        icons:
            List of icon names corresponding with the realnames
        """
        if orient in ViewAngles.defviews:
            self.orient = orient
            self.angle_axes = ViewAngles.defaxes[orient]
            aliases = ViewAngles.buttons
            realnames = ViewAngles.defviews[orient]
            icons = [iconName(n) for n in realnames]
            return aliases, realnames, icons
        else:
            raise ValueError("Invalid front orientation: %s" % orient) 
[docs]    def get(self, name):
        """Get the angles for a named view.
        Returns a tuple of angles (longitude, latitude, twist) if the
        named view was defined, or None otherwise
        """
        angles = ViewAngles.built_in_abs_views.get(name, None)
        if angles is not None:
            orient = 'xy'
        else:
            angles = dict.get(self, name, None)
            orient = self.orient
        return angles, orient  
# The global storage of named views
view_angles = ViewAngles()
[docs]def getAngles(name):
    """Get angles (and orient) of a named view."""
    return view_angles.get(name) 
def getAngleAxes(orient):
    return view_angles.angle_axes
def getOrientation():
    return view_angles.orient
[docs]def setAngles(name, angles):
    """Define new or redefine old view"""
    view_angles[name] = angles 
[docs]def viewNames():
    """Return a list of all view names"""
    return sorted(list(view_angles.built_in_abs_views.keys()) + list(view_angles.keys())) 
def setOrientation(orient):
    return view_angles.setOrientation(orient)
# End