Source code for sknano.core.geometric_regions.misc

# -*- coding: utf-8 -*-
"""
===============================================================================
Helper functions (:mod:`sknano.core.geometric_regions.misc`)
===============================================================================

.. currentmodule:: sknano.core.geometric_regions.misc

"""
from __future__ import absolute_import, division, print_function
from __future__ import unicode_literals

import numpy as np

__all__ = ['generate_bounding_box']

from ._3D_regions import Cuboid


[docs]def generate_bounding_box(from_region=None, from_lattice=None, from_array=None, verbose=False): """Return a :class:`~sknano.core.geometric_regions.Cuboid` \ representing an axis-aligned bounding box. Parameters ---------- from_region : :class:`~sknano.core.geometric_regions.Geometric3DRegion` from_lattice : :class:`~sknano.core.crystallography.Crystal3DLattice` from_array : :class:`~numpy:numpy.ndarray` verbose : :class:`~python:bool` Returns ------- bounding_box : :class:`~sknano.core.geometric_regions.Cuboid` """ if all([obj is None for obj in (from_region, from_lattice, from_array)]): return None bounding_box = Cuboid() if from_region is not None: region = from_region bounding_box.pmin = region.pmin bounding_box.pmax = region.pmax elif from_lattice is not None: lattice = from_lattice # if np.allclose(np.radians(lattice.angles), np.pi / 2 * np.ones(3)): # lattice_region = # bounding_box.pmin = lattice_region.pmin # bounding_box.pmax = lattice_region.pmax # else: a, b, c = lattice.lengths cos_alpha, cos_beta, cos_gamma = np.cos(np.radians(lattice.angles)) lx = a xy = b * cos_gamma xz = c * cos_beta ly = np.sqrt(b ** 2 - xy ** 2) yz = (b * c * cos_alpha - xy * xz) / ly lz = np.sqrt(c ** 2 - xz ** 2 - yz ** 2) lattice_region = lattice.region xlo, ylo, zlo = lattice_region.o if verbose: print('xy={}, xz={}, yz={}'.format(xy, xz, yz)) print('lx={}, ly={}, lz={}'.format(lx, ly, lz)) print('xlo={}, ylo={}, zlo={}'.format(xlo, ylo, zlo)) print('lattice.region.centroid: {}'.format( lattice_region.centroid)) xlo_bound = xlo + min(0.0, xy, xz, xy + xz) xhi_bound = xlo + lx + max(0.0, xy, xz, xy + xz) ylo_bound = ylo + min(0.0, yz) yhi_bound = ylo + ly + max(0.0, yz) zlo_bound = zlo zhi_bound = zlo + lz bounding_box.pmin = [xlo_bound, ylo_bound, zlo_bound] bounding_box.pmax = [xhi_bound, yhi_bound, zhi_bound] if verbose: print('bounding_box: {}'.format(bounding_box)) print('orientation_matrix: {}'.format(lattice.orientation_matrix)) assert bounding_box.pmin <= bounding_box.pmax else: array = np.asarray(from_array) for i, dim in enumerate(('x', 'y', 'z')): setattr(bounding_box, dim + 'min', array[:, i].min()) setattr(bounding_box, dim + 'max', array[:, i].max()) return bounding_box