#
##
## This file is part of pyFormex 2.0 (Mon Sep 14 12:29:05 CEST 2020)
## 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/.
##
"""tools.py
Graphic Tools for pyFormex.
"""
import pyformex as pf
from pyformex.lazy import *
from pyformex.collection import Collection
from pyformex.mesh import Mesh
from pyformex.formex import Formex
from pyformex.trisurface import TriSurface
from pyformex.plugins.nurbs import NurbsCurve, NurbsSurface
class Plane(object):
def __init__(self, points, normal=None, size=(1.0, 1.0)):
pts = Coords(points)
if pts.shape == (3,) and normal is not None:
P = pts
n = Coords(normal)
if n.shape != (3,):
raise ValueError("normal does not have correct shape")
elif pts.shape == (3, 3,):
P = pts.centroid()
n = cross(pts[1]-pts[0], pts[2]-pts[0])
else:
raise ValueError("points has incorrect shape (%s)" % str(pts.shape))
s = Coords(size)
self.P = P
self.n = n
self.s = s
def point(self):
return self.P
def normal(self):
return self.n
def size(self):
return self.s
def bbox(self):
return self.P.bbox()
def __str__(self):
return 'P:%s n:%s s:%s' % (list(self.P), list(self.n), (list(self.s[0]), list(self.s[1])))
def actor(self, **kargs):
from pyformex.opengl import actors
actor = actors.PlaneActor(n=self.n, P=self.P, **kargs)
return actor
################# Report information about picked objects ################
def report(K):
if K is not None and hasattr(K, 'obj_type'):
if K.obj_type == 'actor':
return reportActors(K)
elif K.obj_type == 'element':
return reportElements(K)
elif K.obj_type == 'point':
return reportPoints(K)
elif K.obj_type == 'edge':
return reportEdges(K)
elif K.obj_type == 'prop':
return reportProps(K)
elif K.obj_type == 'partition':
return reportPartitions(K)
return ''
def reportActors(K):
s = "Actor report\n"
v = K.get(-1, [])
s += "Actors %s\n" % v
for k in v:
A = pf.canvas.actors[k]
t = A.getType()
s += " Actor %s (type %s)\n" % (k, t)
return s
def reportElements(K):
s = "Element report\n"
for k in K.keys():
v = K[k]
A = pf.canvas.actors[k]
t = A.getType()
s += "Actor %s (type %s); Elements %s\n" % (k, t, v)
if t == Formex:
e = A.coords
elif t == TriSurface or t == Mesh:
e = A.elems
for p in v:
s += " Element %s: %s\n" % (p, e[p])
return s
def reportProps(K):
s = "Property report\n"
for k in K.keys():
v = K[k]
A = pf.canvas.actors[k]
t = A.getType()
s += "Actor %s (type %s); Props %s\n" % (k, t, v)
for p in v:
w = where(A.object.prop == p)[0]
s += " Elements with prop %s: %s\n" % (p, w)
return s
def reportPoints(K):
s = "Point report\n"
for k in K.keys():
v = K[k]
A = pf.canvas.actors[k]
s += "Actor %s (type %s); Points %s\n" % (k, A.getType(), v)
x = A.object.points()
for p in v:
s += " Point %s: %s\n" % (p, x[p])
return s
def reportEdges(K):
s = "Edge report\n"
for k in K.keys():
v = K[k]
A = pf.canvas.actors[k]
s += "Actor %s (type %s); Edges %s\n" % (k, A.getType(), v)
e = A.edges()
for p in v:
s += " Edge %s: %s\n" % (p, e[p])
def reportPartitions(K):
s = "Partition report\n"
for k in K.keys():
P = K[k][0]
A = pf.canvas.actors[k]
t = A.getType()
for l in P.keys():
v = P[l]
s += "Actor %s (type %s); Partition %s; Elements %s\n" % (k, t, l, v)
if t == 'Formex':
e = A
elif t == 'TriSurface':
e = A.getElems()
for p in v:
s += " Element %s: %s\n" % (p, e[p])
return s
[docs]def getObjectItems(obj, items, mode):
"""Get the specified items from object."""
if mode == 'actor':
return [obj[i].object for i in items if hasattr(obj[i], 'object')]
elif mode in ['element', 'partition']:
if hasattr(obj, 'object') and hasattr(obj.object, 'select'):
return obj.object.select(items)
elif mode == 'point':
if hasattr(obj, 'points'):
return obj.object.points()[items]
return None
[docs]def getCollection(K):
"""Returns a collection."""
if K.obj_type == 'actor':
return [pf.canvas.actors[int(i)].object for i in K.get(-1, []) if hasattr(pf.canvas.actors[int(i)], 'object')]
elif K.obj_type in ['element', 'point']:
return [getObjectItems(pf.canvas.actors[k], K[k], K.obj_type) for k in K.keys()]
elif K.obj_type == 'partition':
return [getObjectItems(pf.canvas.actors[k], K[k][0][prop], K.obj_type) for k in K.keys() for prop in K[k][0].keys()]
else:
return None
[docs]def growCollection(K, **kargs):
"""Grow the collection with n frontal rings.
K should be a collection of elements.
This should work on any objects that have a growSelection method.
"""
if K.obj_type == 'element':
for k in K.keys():
o = pf.canvas.actors[k]
if hasattr(o, 'growSelection'):
K[k] = o.growSelection(K[k], **kargs)
[docs]def partitionCollection(K):
"""Partition the collection according to node adjacency.
The actor numbers will be connected to a collection of property numbers,
e.g. 0 [1 [4,12] 2 [6,20]], where 0 is the actor number, 1 and 2 are the
property numbers and 4, 12, 6 and 20 are the element numbers.
"""
sel = getCollection(K)
if len(sel) == 0:
print("Nothing to partition!")
return
if K.obj_type == 'actor':
actor_numbers = K.get(-1, [])
K.clear()
for i in actor_numbers:
K.add(arange(sel[int(i)].nelems()), i)
prop = 1
j = 0
for i in K.keys():
p = sel[j].partitionByConnection() + prop
print("Actor %s partitioned in %s parts" % (i, p.max()-p.min()+1))
C = Collection()
C.set(transpose(asarray([p, K[i]])))
K[i] = C
prop += p.max()-p.min()+1
j += 1
K.setType('partition')
[docs]def getPartition(K, prop):
""" Remove all partitions with property not in prop."""
for k in K.keys():
for p in K[k][0].keys():
if not p in prop:
K[k][0].remove(K[k][0][p], p)
[docs]def exportObjects(obj, name, single=False):
"""Export a list of objects under the given name.
If obj is a list, and single=True, each element of the list is exported
as a single item. The items will be given the names name-0, name-1, etc.
Else, the obj is exported as is under the name.
"""
if single and isinstance(obj, list):
export(dict([("name-%s"%i, v) for i, v in enumerate(obj)]))
else:
export({name: obj})
[docs]def actorDialog(actorids):
"""Create an actor dialog for the specified actors (by index)
"""
from pyformex.gui.draw import _T, _G, _I, askItems
print("actorDialog %s" % actorids)
actors = [pf.canvas.actors[i] for i in actorids]
items = [_T("actor_%s" % i, [
_I('name', str(a.name)),
_I('type', str(a.getType()), readonly=True),
_I('visible', bool(a.visible)),
_I('alpha', float(a.alpha)),
_I('objcolor', str(a.objcolor), itemtype='color'),
]) for i, a in zip(actorids, actors)]
res = askItems(items)
print(res)
# End