# -*- coding: utf-8 -*-
from typing import List, Union
import axisvm.com.tlb as axtlb
from .core.wrap import AxisVMModelItem, AxisVMModelItems
from .axsurface import SurfaceMixin
__all__ = ["IAxisVMNode", "IAxisVMNodes"]
class IAxisVMNode(AxisVMModelItem, SurfaceMixin):
"""Wrapper for the `IAxisVMNode` COM interface."""
...
[docs]class IAxisVMNodes(AxisVMModelItems, SurfaceMixin):
"""Wrapper for the `IAxisVMNodes` COM interface."""
__itemcls__ = IAxisVMNode
[docs] def get_record(
self, *args, interactive: bool = False, **kwargs
) -> Union[axtlb.RNode, List[axtlb.RNode]]:
"""
Returns a list of node records or a single record, which can be specified
by keyword arguments. It can be used to turn an arbitrary specification
of nodes in an embedded situation into a list of node recirds.
For that reason it includes trivial keys. Individual elements
can be specified, but the result is always a list. If there are
no valid specifiers, then
(1) if argument 'all' is provided, all of the nodes of the
model are returned
(2) if interactive == True, function either gets the selected
nodes from AxisVM, or if there is none, a selection \
dialog shows up in AxisVM and the function is called again \
with valid specifiers emerging from any of these scenarios.
Parameters
----------
**kwargs : dict, Optional
Possible keyword arguments:
* node : a single node, returns a sigle record
* nodes : a list of nodes, returns a list of records
* ID : int, a single nodeID
* IDs : list of int, a sequence of nodeIDs
* UID : int, a single nodeUID
* UIDs : list of int, a sequence of nodeUIDs
Returns
-------
Union[axtlb.RNode, List[axtlb.RNode]]
A single record, or a list of records, depending on the input.
"""
Model = self.model
nodes = None
try:
if "node" in kwargs:
nodes = [kwargs.pop("node")]
elif "nodes" in kwargs:
nodes = kwargs.pop("nodes")
elif "ID" in kwargs:
nodes = [Model.Nodes.GetNode(kwargs.pop("ID"))[0]]
elif "IDs" in kwargs:
nodes = [Model.Nodes.GetNode(ID)[0] for ID in kwargs.pop("IDs")]
elif "UID" in kwargs:
ID = Model.Nodes.IndexOfUID(kwargs.pop("UID"))
nodes = [Model.Nodes.GetNode(ID)[0]]
elif "UIDs" in kwargs:
IDs = [Model.Nodes.IndexOfUID(UID) for UID in kwargs.pop("UIDs")]
nodes = [Model.Nodes.GetNode(ID)[0] for ID in IDs]
except Exception:
raise "Ivalid specification of nodes!"
finally:
if nodes is None:
nodes = self.get_selected(interactive=interactive)
if nodes is None and "all" in args:
nNode = Model.Nodes.Count
nodeIDs = [i for i in range(1, nNode + 1)]
nodes = self.get_record(IDs=nodeIDs, interactive=False)
return nodes
[docs] def select(self, clear: bool = True, msg: str = None) -> Union[list, None]:
"""
Shows up a selectiondialog for nodes in AxisVM and returns the selected
nodes if succesful or None is nothing is selected.
Parameters
----------
clear: boolean, Optional
Clears selection if True. Default is True.
msg: str, Optional
The message to show. If not provided, a default message is shown.
Default is True.
"""
msg = "Select one or more nodes!" if msg is None else msg
deletecurrent = 1 if clear else 0
self.model.app.BringToFront()
self.model.StartModalSelection(msg, deletecurrent, chr(axtlb.seltNode))
return self.get_selected(interactive=False)
[docs] def get_selected(
self, interactive: bool = False, msg: str = None
) -> Union[list, None]:
"""
Returns a dictionary of nodes mapping node indices to node records,
or None if the selection is invalid.
Parameters
----------
interactive: bool, Optional
If nothing is selected when calling this function and this parameter
is `True`, a selection box appears and nodes can be selected through
the graphical user interface. If `False`, the function only returns
a list of nodes if they are already selected when this function is called.
Default is False.
msg:str, Optional
The message to show, only if 'interactive' is `True`. Default is None,
in which case a default message is shown.
"""
Model = self.model._wrapped
try:
nIDs = Model.Nodes.GetSelectedItemIds()[0]
return [Model.Nodes.GetNode(nID)[0] for nID in nIDs]
except Exception:
if interactive:
return self.select(clear=True, msg=msg)
else:
return None
[docs] def get_indices(self, *args, interactive: bool = False, **kwargs) -> List[int]:
"""
Returns a list of integers, depending on the arguments.
It can be used to turn an arbitrary specification of nodes into a list
of indices. Individual items can be specified, but the result is always a list.
If there are no valid specifiers, the function either gets the selected nodes
from AxisVM, or if there is none, a selection dialog shows up in
AxisVM and the function is called again with valid specifiers
emerging from any of these scenarios.
Possible keys and values
* node : a single node record
* nodes : a list of node records
* ID : int, a single node index
* IDs : [int], a sequence of node indices
* UID : int, a single unique node index
* UIDs : [int], a sequence of unique node indices
Note
----
The call accepts the trivial keys 'ID' and 'IDs' to support automatization,
where demand for trivial inputs is possible.
Returns
-------
List[int]
Examples
--------
To get indices of nodes from a selection in AxisVM.
>>> axvm = start_AxisVM(visible=True, daemon=True)
>>> axvm.model = examples.download_bernoulli_grid()
>>> axvm.model.Nodes.get_indices()
"""
nodeIDs = None
Model = self.model
try:
if "node" in kwargs:
n = kwargs["node"]
nodeIDs = [Model.Nodes.IndexOf(n.x, n.y, n.z, 1e-8, 1)]
elif "nodes" in kwargs:
nodes = kwargs["nodes"]
nodeIDs = [Model.Nodes.IndexOf(n.x, n.y, n.z, 1e-8, 1) for n in nodes]
if "ID" in kwargs:
nodeIDs = [kwargs["ID"]]
elif "nodeIDs" in kwargs:
nodeIDs = kwargs["IDs"]
elif "UID" in kwargs:
nodeIDs = [Model.Nodes.IndexOfUID(kwargs["UID"])]
elif "UIDs" in kwargs:
nodeIDs = [Model.Nodes.IndexOfUID(UID) for UID in kwargs["UIDs"]]
except Exception:
raise "Ivalid specification of nodeIDs!"
finally:
if nodeIDs is None:
nodeIDs = self.get_selected_indices(interactive=interactive)
if nodeIDs is None and "all" in args:
nNode = Model.Nodes.Count
nodeIDs = [i for i in range(1, nNode + 1)]
return nodeIDs
[docs] def select_indices(self, clear=True, msg: str = None) -> Union[list, None]:
"""
Shows up a selectiondialog for nodes in AxisVM and returns the selected
nodeIDs if succesful.
Parameters
----------
clear: boolean, Optional
Clears selection state of all entities before the operation if `True`.
Default is `True`.
msg: str, Optional
The message to show. If not provided, a default message is shown.
Default is `True`.
"""
if msg is None:
msg = "Select one or more nodes!"
Model = self.model
deletecurrent = 1 if clear else 0
Model.app.BringToFront()
Model.StartModalSelection(msg, deletecurrent, chr(axtlb.seltNode))
return self.get_selected_indices(interactive=False)
[docs] def get_selected_indices(self, interactive: bool = False) -> Union[list, None]:
"""
Returns a list of nodeIDs. The result is always iterable,
even if it contains only one item.
"""
Model = self.model
try:
return Model.Nodes.GetSelectedItemIds()[0]
except Exception:
if interactive:
return self.select_indices(msg="Select one or more nodes!")
else:
return None
[docs] def connected_surfaces(
self, flatten: bool = False, as_dict: bool = False, **kwargs
) -> Union[dict, list]:
"""
Returns surfaces connected by the specified nodes. For the details of
specification of nodes see the documentation of :func:`get_indices`.
If ``as_dict == True``, the result is a dictionary that maps node indices
to lists of surfaces.
"""
Model = self.model
nodeIDs = self.get_indices(**kwargs)
assert nodeIDs is not None, "Invalid specification of nodes!"
if as_dict:
return dict(
{nID: Model.Nodes.GetConnectedSurfaces(nID)[0] for nID in nodeIDs}
)
if flatten:
surfaces = set()
for nID in nodeIDs:
surfaces.update(Model.Nodes.GetConnectedSurfaces(nID)[0])
return list(surfaces)
return [Model.Nodes.GetConnectedSurfaces(nID)[0] for nID in nodeIDs]