Commit ce425b9d authored by Daniel Böckenhoff (Laptop)'s avatar Daniel Böckenhoff (Laptop)
Browse files

mesh3D some start

parent ac8c8113
......@@ -376,6 +376,14 @@ class Tensors(AbstractNdarray):
dim = kwargs.pop('dim', None)
''' demand iterable structure '''
try:
len(tensors)
except TypeError as err:
raise TypeError("Iterable structure necessary."
" Got {tensors}"
.format(**locals()))
''' process empty inputs '''
if len(tensors) == 0:
if dim is not None:
......@@ -1025,6 +1033,12 @@ class TensorFields(Tensors):
# (over)write fields
obj.fields = [Tensors(field) for field in fields]
if not all([len(f) == len(obj) for f in obj.fields]):
olen = len(obj)
field_lengths = [len(f) for f in obj.fields]
raise ValueError("Length of base ({olen}) should be the same as"
" the length of all fields ({field_lengths})."
.format(**locals()))
return obj
def __getitem__(self, index):
......
......@@ -26,27 +26,42 @@ import cuttingTree
logger = loggingTools.Logger(__name__)
def scalars_to_fields(scalars):
scalars = np.array(scalars)
if len(scalars.shape) == 1:
return [tfields.Tensors(scalars)]
return [tfields.Tensors(fs) for fs in scalars]
def fields_to_scalars(fields):
return np.array(fields)
def faces_to_maps(faces, *fields):
return [tfields.TensorFields(faces, *fields, dtype=int)]
def maps_to_faces(maps):
return maps[0]
class Mesh3D(tfields.TensorMaps):
# pylint: disable=R0904
"""
Points3D child used as vertices combined with faces to build a geometrical mesh of triangles
Examples:
>>> m = tfields.Mesh3D([[1,2,3], [3,3,3], [0,0,0], [5,6,7]], faces=[[0, 1, 2], [1, 2, 3]])
>>> m
Mesh3D([[ 1., 2., 3.],
[ 3., 3., 3.],
[ 0., 0., 0.],
[ 5., 6., 7.]])
>>> m.faces
array([[0, 1, 2],
[1, 2, 3]])
>>> m.equal([[1, 2, 3],
... [3, 3, 3],
... [0, 0, 0],
... [5, 6, 7]])
True
>>> m.faces.equal([[0, 1, 2], [1, 2, 3]])
True
conversion to points only
>>> tfields.Points3D(m)
Points3D([[ 1., 2., 3.],
[ 3., 3., 3.],
[ 0., 0., 0.],
[ 5., 6., 7.]])
>>> tfields.Points3D(m).equal([[1, 2, 3],
... [3, 3, 3],
... [0, 0, 0],
... [5, 6, 7]])
True
Empty instances
>>> m = tfields.Mesh3D([]);
......@@ -59,14 +74,12 @@ class Mesh3D(tfields.TensorMaps):
[ 0., 0., 0.]])
a list of scalars is assigned to each face
>>> m.faceScalars
array([], shape=(1, 0), dtype=float64)
>>> mScalar = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], [[0, 1, 2]], faceScalars=[.5]);
>>> mScalar.faceScalars
array([[ 0.5]])
>>> mScalar = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], faces=[[0, 1, 2]], faceScalars=[.5]);
>>> np.array_equal(mScalar.faceScalars, [[ 0.5]])
True
adding together two meshes:
>>> m2 = tfields.Mesh3D([[1,0,0],[2,0,0],[0,3,0]], [[0,1,2]], faceScalars=[.7])
>>> m2 = tfields.Mesh3D([[1,0,0],[2,0,0],[0,3,0]], faces=[[0,1,2]], faceScalars=[.7])
>>> msum = tfields.Mesh3D([mScalar, m2])
>>> msum
Mesh3D([[ 1., 0., 0.],
......@@ -91,13 +104,46 @@ class Mesh3D(tfields.TensorMaps):
array([[0, 1, 2]])
"""
__slots__ = ['faces', 'faceScalars', 'coordSys', '_cache']
def __new__(cls, tensors, **kwargs):
fields = kwargs.pop('fields', [])
if not issubclass(type(tensors), Mesh3D):
kwargs['dim'] = 3
return super(Mesh3D, cls).__new__(cls, tensors, **kwargs)
faces = kwargs.pop('faces', None)
faceScalars = kwargs.pop('faceScalars', [])
maps = kwargs.pop('maps', None)
if maps and faces:
raise ValueError("Conflicting options maps and faces")
if maps is not None:
kwargs['maps'] = maps
if faceScalars:
map_fields = scalars_to_fields(faceScalars)
else:
map_fields = []
if faces is not None:
kwargs['maps'] = faces_to_maps(faces,
*map_fields)
obj = super(Mesh3D, cls).__new__(cls, tensors, *fields, **kwargs)
if len(obj.maps) > 1:
raise ValueError("Mesh3D only allows one map")
if obj.maps and obj.maps[0].dim != 3:
raise ValueError("Face dimension should be 3")
return obj
@property
def faces(self):
return maps_to_faces(self.maps)
@faces.setter
def faces(self, faces):
self.maps = faces_to_maps(faces)
@property
def faceScalars(self):
return fields_to_scalars(self.maps[0].fields)
@faceScalars.setter
def faceScalars(self, faceScalars):
self.maps[0].faces = scalars_to_fields(faceScalars)
@classmethod
def _updateSlotKwargs(cls, kwargs, skipCache=True):
......@@ -303,8 +349,11 @@ class Mesh3D(tfields.TensorMaps):
def setScalarArray(self, scalarIndex, scalarArray):
"""
>>> m = tfields.Mesh3D([[1,2,3], [3,3,3], [0,0,0], [5,6,7]], [[0, 1, 2], [1, 2, 3]],
... faceScalars=[[1,2,3,4,5], [6,7,8,9,0]])
>>> m = tfields.Mesh3D([[1,2,3], [3,3,3],
... [0,0,0], [5,6,7]],
... [[0, 1, 2], [1, 2, 3]],
... faceScalars=[[1,2,3,4,5],
... [6,7,8,9,0]])
>>> m.setScalarArray(1, [42, 84])
>>> m.faceScalars
array([[ 1., 42., 3., 4., 5.],
......@@ -1704,5 +1753,6 @@ class Mesh3D(tfields.TensorMaps):
if __name__ == '__main__':
import doctest
# doctest.run_docstring_examples(Mesh3D.clean, globals())
doctest.run_docstring_examples(Mesh3D, globals())
quit()
doctest.testmod()
......@@ -4,11 +4,11 @@
Author: Daniel Boeckenhoff
Mail: daniel.boeckenhoff@ipp.mpg.de
part of npTools library
part of tfields library
"""
import numpy as np
import warnings
import npTools
import tfields
import ioTools
import decoTools
import pyTools
......@@ -17,12 +17,12 @@ import loggingTools
logger = loggingTools.Logger(__name__)
class Triangles3D(npTools.Points3D):
class Triangles3D(tfields.TensorFields):
# pylint: disable=R0904
"""
Points3D child restricted to n * 3 Points. 3 Points always group together to one triangle.
Examples:
>>> t = npTools.Triangles3D([[1,2,3], [3,3,3], [0,0,0]]); t
>>> t = tfields.Triangles3D([[1,2,3], [3,3,3], [0,0,0]]); t
Triangles3D([[ 1., 2., 3.],
[ 3., 3., 3.],
[ 0., 0., 0.]])
......@@ -30,9 +30,9 @@ class Triangles3D(npTools.Points3D):
array([], shape=(1, 0), dtype=float64)
>>> _ = t.coordinateTransform(t.CYLINDER)
>>> a = [npTools.Points3D([[1],[2],[3]], coordSys=npTools.Points3D.CYLINDER),
... npTools.Points3D([[3],[3],[3]]), npTools.Points3D([[5],[1],[3]])]
>>> npTools.Triangles3D(a, coordSys=npTools.Points3D.CARTESIAN)
>>> a = [tfields.Points3D([[1],[2],[3]], coordSys=tfields.Points3D.CYLINDER),
... tfields.Points3D([[3],[3],[3]]), tfields.Points3D([[5],[1],[3]])]
>>> tfields.Triangles3D(a, coordSys=tfields.Points3D.CARTESIAN)
Triangles3D([[-0.41614684, 0.90929743, 3. ],
[ 3. , 3. , 3. ],
[ 5. , 1. , 3. ]])
......@@ -55,7 +55,7 @@ class Triangles3D(npTools.Points3D):
"should be concatenated must be the same.")
triangleScalars = np.concatenate([o.triangleScalars for o in inputArray], axis=0)
obj = npTools.Points3D.__new__(cls, inputArray, **kwargs)
obj = tfields.Points3D.__new__(cls, inputArray, **kwargs)
if not obj.getNPoints() % 3 == 0:
raise TypeError("Points 3D does not describe triangles. "
"Size of obj is {0}, has no divider 3".format(len(obj)))
......@@ -112,7 +112,7 @@ class Triangles3D(npTools.Points3D):
def appendScalars(self, scalars):
"""
Examples:
>>> t = npTools.Triangles3D([[1,2,3], [3,3,3], [0,0,0]], [[1001]])
>>> t = tfields.Triangles3D([[1,2,3], [3,3,3], [0,0,0]], [[1001]])
>>> t.appendScalars([42])
>>> t.triangleScalars
array([[1001, 42]])
......@@ -149,7 +149,7 @@ class Triangles3D(npTools.Points3D):
Default cut method for Triangles3D
Examples:
>>> x, y, z = sympy.symbols('x y z')
>>> t = npTools.Triangles3D([[1., 2., 3.], [-4., 5., 6.], [1, 2, -6],
>>> t = tfields.Triangles3D([[1., 2., 3.], [-4., 5., 6.], [1, 2, -6],
... [5, -5, -5], [1,0,-1], [0,1,-1], [-5, -5, -5],
... [1,0,-1], [0,1,-1]])
>>> tc = t.cut(x >= 0)
......@@ -197,15 +197,15 @@ class Triangles3D(npTools.Points3D):
"""
Calculate area with "heron's formula"
Examples:
>>> m = npTools.Mesh3D([[1,0,0], [0,0,1], [0,0,0]], [[0, 1, 2]]);
>>> m = tfields.Mesh3D([[1,0,0], [0,0,1], [0,0,0]], [[0, 1, 2]]);
>>> m.triangles.getAreas()
array([ 0.5])
>>> m = npTools.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [0,0,1]], [[0, 1, 2], [1, 2, 3]]);
>>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [0,0,1]], [[0, 1, 2], [1, 2, 3]]);
>>> m.triangles.getAreas()
array([ 0.5, 0.5])
>>> m = npTools.Mesh3D([[1,0,0], [0,1,0], [1,1,0], [0,0,1], [1,0,1]],
>>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [1,1,0], [0,0,1], [1,0,1]],
... [[0, 1, 2], [0, 3, 4]]);
>>> m.triangles.getAreas()
array([ 0.5, 0.5])
......@@ -256,7 +256,7 @@ class Triangles3D(npTools.Points3D):
Semi baricentric method to calculate circumcenter points of the triangles
Examples:
>>> m = npTools.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
... [[0, 1, 3],[0, 2, 3],[1,2,4], [1, 3, 4]]);
>>> m.triangles.getCircumcenters()
Points3D([[ 5.00000000e-01, 5.00000000e-01, 0.00000000e+00],
......@@ -279,7 +279,7 @@ class Triangles3D(npTools.Points3D):
# matrix vector product for matrices and vectors
P = np.einsum('...ji,...i', matrices, vectors)
P /= vectors.sum(axis=1).reshape((len(vectors), 1))
return npTools.Points3D(P)
return tfields.Points3D(P)
@decoTools.cached_property()
def centroids(self):
......@@ -290,7 +290,7 @@ class Triangles3D(npTools.Points3D):
nT = self.getNTriangles()
mat = np.ones((1, 3)) / 3.0
# matrix product calculatesq center of all triangles
return npTools.Points3D(np.dot(mat, self.reshape(nT, 3, 3))[0], coordSys=self.coordSys)
return tfields.Points3D(np.dot(mat, self.reshape(nT, 3, 3))[0], coordSys=self.coordSys)
"""
Old version:
......@@ -304,7 +304,7 @@ class Triangles3D(npTools.Points3D):
def getCentroids(self):
"""
Examples:
>>> m = npTools.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
... [[0, 1, 3],[0, 2, 3],[1,2,4], [1, 3, 4]]);
>>> m.triangles.getCentroids()
Points3D([[ 0.33333333, 0.33333333, 0. ],
......@@ -336,7 +336,7 @@ class Triangles3D(npTools.Points3D):
def getNormVectors(self):
"""
Examples:
>>> m = npTools.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
... [[0, 1, 3],[0, 2, 3],[1,2,4], [1, 3, 4]]);
>>> m.triangles.getNormVectors()
array([[ 0. , 0. , 1. ],
......@@ -363,11 +363,11 @@ class Triangles3D(npTools.Points3D):
last coordinate is prism
Examples:
empty Meshes return right formatted array
>>> m = npTools.Mesh3D([], faces=[])
>>> m = tfields.Mesh3D([], faces=[])
>>> m.triangles.getBaricentricCoordinates(np.array([0.2, 0.2, 0]))
array([], dtype=float64)
>>> m2 = npTools.Mesh3D([[0,0,0], [2,0,0], [0,2,0], [0,0,2]], [[0, 1, 2], [0, 2, 3]]);
>>> m2 = tfields.Mesh3D([[0,0,0], [2,0,0], [0,2,0], [0,0,2]], [[0, 1, 2], [0, 2, 3]]);
>>> m2.triangles.getBaricentricCoordinates(np.array([0.2, 0.2, 0]), delta=2.)
array([[ 0.1, 0.1, 0. ],
[ 0.1, 0. , 0.1]])
......@@ -379,7 +379,7 @@ class Triangles3D(npTools.Points3D):
If you define triangles that have colinear side vectors or in general lead to
not invertable matrices [ab, ac, ab x ac] a warning wil be thrown but no error
>>> m3 = npTools.Mesh3D([[0,0,0], [2,0,0], [4,0,0], [0,1,0]], [[0, 1, 2], [0, 1, 3]]);
>>> m3 = tfields.Mesh3D([[0,0,0], [2,0,0], [4,0,0], [0,1,0]], [[0, 1, 2], [0, 1, 3]]);
>>> import pytest
>>> with pytest.warns(UserWarning) as record:
... bc = m3.triangles.getBaricentricCoordinates(np.array([0.2, 0.2, 0]), delta=0.3)
......@@ -550,18 +550,18 @@ class Triangles3D(npTools.Points3D):
def pointInTrianglesBaryc(self, point, delta=0.):
"""
Examples:
>>> m = npTools.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], [[0, 1, 2]]);
>>> m.triangles.pointInTrianglesBaryc(npTools.Points3D([[0.2, 0.2, 0]]))
>>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], [[0, 1, 2]]);
>>> m.triangles.pointInTrianglesBaryc(tfields.Points3D([[0.2, 0.2, 0]]))
array([ True], dtype=bool)
wrong format of point will raise a ValueError
>>> m.triangles.pointInTrianglesBaryc(npTools.Points3D([[0.2, 0.2, 0], [0.2, 0.2, 0]]))
>>> m.triangles.pointInTrianglesBaryc(tfields.Points3D([[0.2, 0.2, 0], [0.2, 0.2, 0]]))
Traceback (most recent call last):
...
ValueError: point must be castable to shape 3 but is of shape (2, 3)
All Triangles are tested
>>> m2 = npTools.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [4,0,0], [4, 4, 0], [8, 0, 0]],
>>> m2 = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [4,0,0], [4, 4, 0], [8, 0, 0]],
... [[0, 1, 2], [3, 4, 5]]);
>>> m2.triangles.pointInTrianglesBaryc(np.array([0.2, 0.2, 0]))
......@@ -577,7 +577,7 @@ class Triangles3D(npTools.Points3D):
If you define triangles that have colinear side vectors or in general lead to
not invertable matrices the you will always get False
>>> m3 = npTools.Mesh3D([[0,0,0], [2,0,0], [4,0,0], [0,1,0]], [[0, 1, 2], [0, 1, 3]]);
>>> m3 = tfields.Mesh3D([[0,0,0], [2,0,0], [4,0,0], [0,1,0]], [[0, 1, 2], [0, 1, 3]]);
>>> import pytest
>>> with pytest.warns(UserWarning) as record:
... mask = m3.triangles.pointInTrianglesBaryc(np.array([0.2, 0.2, 0]), delta=0.3)
......@@ -604,19 +604,19 @@ class Triangles3D(npTools.Points3D):
Check whether point lies within triangles with Barycentric Technique
It could lie within multiple triangles!
Examples:
>>> m = npTools.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], [[0, 1, 2]]);
>>> m.triangles.pointInTrianglesBarycentric2(npTools.Points3D([[0.2, 0.2, 0]]))
>>> m = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0]], [[0, 1, 2]]);
>>> m.triangles.pointInTrianglesBarycentric2(tfields.Points3D([[0.2, 0.2, 0]]))
array([ True], dtype=bool)
wrong format of point will raise a ValueError
>>> m.triangles.pointInTrianglesBarycentric2(npTools.Points3D([[0.2, 0.2, 0],
>>> m.triangles.pointInTrianglesBarycentric2(tfields.Points3D([[0.2, 0.2, 0],
... [0.2, 0.2, 0]]))
Traceback (most recent call last):
...
ValueError: point must be castable to shape 3 but is of shape (2, 3)
All Triangles are tested
>>> m2 = npTools.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [4,0,0],
>>> m2 = tfields.Mesh3D([[1,0,0], [0,1,0], [0,0,0], [4,0,0],
... [4, 4, 0], [8, 0, 0]],
... [[0, 1, 2], [3, 4, 5]]);
>>> m2.triangles.pointInTrianglesBarycentric2(np.array([0.2, 0.2, 0]))
......@@ -671,15 +671,15 @@ class Triangles3D(npTools.Points3D):
np.array: boolean mask which is true, if point is on one side ray
of a triangle
Examples:
>>> m = npTools.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
>>> m = tfields.Mesh3D([[0,0,0], [1,0,0], [-1,0,0], [0,1,0], [0,0,1]],
... [[0, 1, 3],[0, 2, 3],[1,2,4]]);
Corner points are found
>>> m.triangles.pointOnTriangleSide(npTools.Points3D([[0,1,0]]))
>>> m.triangles.pointOnTriangleSide(tfields.Points3D([[0,1,0]]))
array([ True, True, False], dtype=bool)
Side points are found, too
>>> m.triangles.pointOnTriangleSide(npTools.Points3D([[0.5,0,0.5]]))
>>> m.triangles.pointOnTriangleSide(tfields.Points3D([[0.5,0,0.5]]))
array([False, False, True], dtype=bool)
"""
......@@ -812,7 +812,7 @@ class Triangles3D(npTools.Points3D):
"""
Forward to an alternative representation of the triangeles as mesh
"""
return npTools.Mesh3D(self,
return tfields.Mesh3D(self,
[[3 * i, 3 * i + 1, 3 * i + 2]
for i in range(self.getNTriangles())],
faceScalars=self.triangleScalars)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment