1 |
|
# -*- coding: utf-8 -*- |
2 |
|
|
3 |
######################################################## |
######################################################## |
4 |
# |
# |
498 |
""" |
""" |
499 |
return [ self.getStartPoint(), self.getEndPoint()] |
return [ self.getStartPoint(), self.getEndPoint()] |
500 |
|
|
501 |
|
|
502 |
def setElementDistribution(self,n,progression=1,createBump=False): |
def setElementDistribution(self,n,progression=1,createBump=False): |
503 |
""" |
""" |
504 |
Defines the number of elements on the line. If set it overwrites the local length setting which would be applied. |
Defines the number of elements on the line. If set it overwrites the local length setting which would be applied. |
1007 |
if not isinstance(curves[i],Manifold1D): |
if not isinstance(curves[i],Manifold1D): |
1008 |
raise TypeError("%s-th argument is not a Manifold1D object."%i) |
raise TypeError("%s-th argument is not a Manifold1D object."%i) |
1009 |
# for the curves a loop: |
# for the curves a loop: |
1010 |
used=[ False for i in curves] |
#used=[ False for i in curves] |
1011 |
self.__curves=list(curves) |
self.__curves=[] |
1012 |
|
for c in curves: |
1013 |
|
if not c in self.__curves: self.__curves.append(c) |
1014 |
Primitive.__init__(self) |
Primitive.__init__(self) |
1015 |
PrimitiveBase.__init__(self) |
PrimitiveBase.__init__(self) |
1016 |
|
|
1017 |
|
|
1018 |
def getCurves(self): |
def getCurves(self): |
1019 |
""" |
""" |
1071 |
return True |
return True |
1072 |
return False |
return False |
1073 |
|
|
1074 |
|
|
1075 |
|
|
1076 |
|
|
1077 |
class ReverseCurveLoop(ReversePrimitive, PrimitiveBase): |
class ReverseCurveLoop(ReversePrimitive, PrimitiveBase): |
1078 |
""" |
""" |
1079 |
An oriented loop of one-dimensional manifolds (= curves and arcs). |
An oriented loop of one-dimensional manifolds (= curves and arcs). |
1099 |
|
|
1100 |
def __len__(self): |
def __len__(self): |
1101 |
return len(self.getUnderlyingPrimitive()) |
return len(self.getUnderlyingPrimitive()) |
|
|
|
1102 |
#= |
#= |
1103 |
class Manifold2D(PrimitiveBase): |
class Manifold2D(PrimitiveBase): |
1104 |
""" |
""" |
1132 |
""" |
""" |
1133 |
raise NotImplementedError() |
raise NotImplementedError() |
1134 |
|
|
1135 |
|
def setElementDistribution(self,n,progression=1,createBump=False): |
1136 |
|
""" |
1137 |
|
Defines the number of elements on the lines |
1138 |
|
|
1139 |
|
:param n: number of elements on the line |
1140 |
|
:type n: ``int`` |
1141 |
|
:param progression: a positive progression factor |
1142 |
|
:type progression: positive ``float`` |
1143 |
|
:param createBump: of elements on the line |
1144 |
|
:type createBump: ``bool`` |
1145 |
|
""" |
1146 |
|
for i in self.getBoundary(): i.setElementDistribution(n,progression,createBump) |
1147 |
|
|
1148 |
def getPoints(self): |
def getPoints(self): |
1149 |
""" |
""" |
1150 |
returns a list of points used to define the boundary |
returns a list of points used to define the boundary |
1194 |
""" |
""" |
1195 |
applies 2D transfinite meshing to the surface. |
applies 2D transfinite meshing to the surface. |
1196 |
|
|
1197 |
:param orientation: sets the orientation of the triangles. It is only used if recombination is not used. |
:param orientation: sets the orientation of the triangles. It is only relevant if recombination is not used. |
1198 |
:type orientation: `Manifold2D.LEFT`, `Manifold2D.RIGHT`, `Manifold2D.ALTERNATE` |
:type orientation: `Manifold2D.LEFT`, `Manifold2D.RIGHT`, `Manifold2D.ALTERNATE` |
1199 |
:note: Transfinite meshing can not be applied if holes are present. |
:note: Transfinite meshing can not be applied if holes are present. |
1200 |
""" |
""" |
1226 |
if opposite == None: # three sides only |
if opposite == None: # three sides only |
1227 |
if not top.getElementDistribution()[0] == bottom.getElementDistribution()[0]: start, top, bottom= bottom, start, top |
if not top.getElementDistribution()[0] == bottom.getElementDistribution()[0]: start, top, bottom= bottom, start, top |
1228 |
if not top.getElementDistribution() == bottom.getElementDistribution(): |
if not top.getElementDistribution() == bottom.getElementDistribution(): |
1229 |
raise ValueError,"transfinite meshing requires oposite faces to be have the same element distribution." |
raise ValueError,"transfinite meshing requires opposite faces to be have the same element distribution." |
1230 |
if not opposite == None: |
if not opposite == None: |
1231 |
if not start.getElementDistribution()[0] == opposite.getElementDistribution()[0]: |
if not start.getElementDistribution()[0] == opposite.getElementDistribution()[0]: |
1232 |
raise ValueError,"transfinite meshing requires oposite faces to be have the same element distribution." |
raise ValueError,"transfinite meshing requires oposite faces to be have the same element distribution." |
1264 |
return (self.__points, self.__orientation) |
return (self.__points, self.__orientation) |
1265 |
else: |
else: |
1266 |
return None |
return None |
1267 |
|
def getPolygon(self): |
1268 |
|
""" |
1269 |
|
Returns a list of start/end points of the 1D mainfold form the loop. If not closed and exception is thrown. |
1270 |
|
""" |
1271 |
|
curves=self.getBoundary() |
1272 |
|
s=[curves[0].getStartPoint(), curves[0].getEndPoint()] |
1273 |
|
found= [ curves[0] ] |
1274 |
|
restart=True |
1275 |
|
while restart: |
1276 |
|
restart=False |
1277 |
|
for k in curves: |
1278 |
|
if not k in found: |
1279 |
|
if k.getStartPoint() == s[-1]: |
1280 |
|
found.append(k) |
1281 |
|
if k.getEndPoint() == s[0]: |
1282 |
|
if len(found) == len(curves): |
1283 |
|
return s |
1284 |
|
else: |
1285 |
|
raise ValueError,"loop %s is not closed."%self.getID() |
1286 |
|
s.append(k.getEndPoint()) |
1287 |
|
restart=True |
1288 |
|
break |
1289 |
|
if not restart: |
1290 |
|
raise ValueError,"loop %s is not closed."%self.getID() |
1291 |
class RuledSurface(Primitive, Manifold2D): |
class RuledSurface(Primitive, Manifold2D): |
1292 |
""" |
""" |
1293 |
A ruled surface, i.e. a surface that can be interpolated using transfinite |
A ruled surface, i.e. a surface that can be interpolated using transfinite |
1655 |
Creates a three-dimensional manifold. |
Creates a three-dimensional manifold. |
1656 |
""" |
""" |
1657 |
PrimitiveBase.__init__(self) |
PrimitiveBase.__init__(self) |
1658 |
|
self.__transfinitemeshing=False |
1659 |
|
|
1660 |
def getBoundary(self): |
def getBoundary(self): |
1661 |
""" |
""" |
1662 |
Returns a list of the one-dimensional manifolds forming the boundary |
Returns a list of the 2-dimensional manifolds forming the boundary |
1663 |
of the volume (including holes). |
of the volume (including holes). |
1664 |
""" |
""" |
1665 |
raise NotImplementedError() |
raise NotImplementedError() |
1666 |
|
|
1667 |
|
def setElementDistribution(self,n,progression=1,createBump=False): |
1668 |
|
""" |
1669 |
|
Defines the number of elements on the lines and surfaces |
1670 |
|
|
1671 |
|
:param n: number of elements on the line |
1672 |
|
:type n: ``int`` |
1673 |
|
:param progression: a positive progression factor |
1674 |
|
:type progression: positive ``float`` |
1675 |
|
:param createBump: of elements on the line |
1676 |
|
:type createBump: ``bool`` |
1677 |
|
""" |
1678 |
|
for i in self.getBoundary(): i.setElementDistribution(n,progression,createBump) |
1679 |
|
|
1680 |
|
def setRecombination(self, max_deviation=45*DEG): |
1681 |
|
""" |
1682 |
|
Recombines triangular meshes on all surface into mixed triangular/quadrangular meshes. These meshes |
1683 |
|
are then used to generate the volume mesh if possible. Recombination requires 3D transfinite meshing. |
1684 |
|
|
1685 |
|
``max_deviation`` specifies the maximum derivation of the largest angle in the quadrangle |
1686 |
|
from the right angle. Use ``max_deviation``==``None`` to switch off recombination. |
1687 |
|
|
1688 |
|
:param max_deviation: maximum derivation of the largest angle in the quadrangle from the right angle. |
1689 |
|
:type max_deviation: ``float`` or ``None``. |
1690 |
|
""" |
1691 |
|
if not max_deviation==None: |
1692 |
|
if max_deviation<=0: |
1693 |
|
raise ValueError, "max_deviation must be positive." |
1694 |
|
if max_deviation/DEG>=90: |
1695 |
|
raise ValueError, "max_deviation must be smaller than 90 DEG" |
1696 |
|
for i in self.getBoundary(): i.setRecombination(max_deviation) |
1697 |
|
self.setTransfiniteMeshing() |
1698 |
|
|
1699 |
|
def setTransfiniteMeshing(self,orientation="Left"): |
1700 |
|
""" |
1701 |
|
applies 3D transfinite meshing to the volume and all surface. It requires transfinite meshing on all faces which will be enforced (except |
1702 |
|
if ``orientation`` is equal to ``None``. |
1703 |
|
|
1704 |
|
:param orientation: sets the orientation of the triangles on the surfaces. It is only relevant if recombination is not used. |
1705 |
|
If orientation is equal to ``None``, the transinite meshing is not applied to the surfaces but must be set by the user. |
1706 |
|
:type orientation: `Manifold2D.LEFT`, `Manifold2D.RIGHT`, `Manifold2D.ALTERNATE` |
1707 |
|
:note: Transfinite meshing can not be applied if holes are present. |
1708 |
|
:note: only five or six surfaces may be used. |
1709 |
|
""" |
1710 |
|
if isinstance(self, ReversePrimitive): |
1711 |
|
return self.getUnderlyingPrimitive().setTransfiniteMeshing(orientation) |
1712 |
|
else: |
1713 |
|
if not orientation == None: |
1714 |
|
if not orientation in [ Manifold2D.LEFT, Manifold2D.RIGHT, Manifold2D.ALTERNATE]: |
1715 |
|
raise ValueError,"invalid orientation %s."%orientation |
1716 |
|
|
1717 |
|
if self.hasHole(): |
1718 |
|
raise ValueError,"transfinite meshing cannot be appled to surfaces with a hole." |
1719 |
|
b=self.getBoundary() |
1720 |
|
# find a face with 3/4 Points: |
1721 |
|
if len(b) == 6 : |
1722 |
|
des_len=4 |
1723 |
|
elif len(b) == 5: |
1724 |
|
des_len=3 |
1725 |
|
else: |
1726 |
|
raise ValueError,"transfinite meshing permits 5 or 6 surface only." |
1727 |
|
# start_b=None |
1728 |
|
# for l in b: |
1729 |
|
# if len(l.getPolygon()) == des_len: |
1730 |
|
# start_b = l |
1731 |
|
# break |
1732 |
|
# if start_b == None: |
1733 |
|
# raise ValueError,"Expect face with %s points."%des_len |
1734 |
|
# start_poly=start_b.getPolygon() |
1735 |
|
# now we need to find the opposite face: |
1736 |
|
# opposite = None |
1737 |
|
# for l in b: |
1738 |
|
# if all( [ not k in start_poly for k in l.getPolygon() ]): |
1739 |
|
# opposite = l |
1740 |
|
# break |
1741 |
|
# if opposite == None: |
1742 |
|
# raise ValueError,"Unable to find face for transfinite interpolation." |
1743 |
|
# opposite_poly=opposite.getPolygon() |
1744 |
|
# if not len(opposite_poly) == des_len: |
1745 |
|
# raise ValueError,"Unable to find face for transfinite interpolation." |
1746 |
|
# this needs more work to find the points!!!! |
1747 |
|
points = [] |
1748 |
|
self.__points=points |
1749 |
|
if not orientation == None: |
1750 |
|
for i in b: i.setTransfiniteMeshing(orientation) |
1751 |
|
self.__transfinitemeshing=True |
1752 |
|
|
1753 |
|
def resetTransfiniteMeshing(self): |
1754 |
|
""" |
1755 |
|
removes the transfinite meshing from the volume but not from the surfaces |
1756 |
|
""" |
1757 |
|
if isinstance(self, ReversePrimitive): |
1758 |
|
self.getUnderlyingPrimitive().resetTransfiniteMeshing() |
1759 |
|
else: |
1760 |
|
self.__transfinitemeshing=False |
1761 |
|
|
1762 |
|
def getTransfiniteMeshing(self): |
1763 |
|
""" |
1764 |
|
returns the transfinite meshing setings. If transfinite meshing is not set, ``None`` is returned. |
1765 |
|
|
1766 |
|
:return: a tuple of the tuple of points used to define the transfinite meshing and the orientation. If no points are set the points tuple is returned as ``None``. If no transfinite meshing is not set, ``None`` is returned. |
1767 |
|
:rtype: ``tuple`` of a ``tuple`` of `Point` s (or ``None``) and the orientation which is one of the values `Manifold2D.LEFT` , `Manifold2D.RIGHT` , `Manifold2D.ALTERNATE` |
1768 |
|
""" |
1769 |
|
if isinstance(self, ReversePrimitive): |
1770 |
|
return self.getUnderlyingPrimitive().getTransfiniteMeshing() |
1771 |
|
else: |
1772 |
|
if self.__transfinitemeshing: |
1773 |
|
return self.__points |
1774 |
|
else: |
1775 |
|
return None |
1776 |
|
|
1777 |
class Volume(Manifold3D, Primitive): |
class Volume(Manifold3D, Primitive): |
1778 |
""" |
""" |
1779 |
A volume with holes. |
A volume with holes. |
1799 |
Manifold3D.__init__(self) |
Manifold3D.__init__(self) |
1800 |
self.__loop=loop |
self.__loop=loop |
1801 |
self.__holes=holes |
self.__holes=holes |
1802 |
|
self.__transfinitemeshing=False |
1803 |
|
|
1804 |
def getHoles(self): |
def getHoles(self): |
1805 |
""" |
""" |
1852 |
|
|
1853 |
def getBoundary(self): |
def getBoundary(self): |
1854 |
""" |
""" |
1855 |
Returns a list of the one-dimensional manifolds forming the boundary |
Returns a list of the 2-dimensional manifolds forming the surface of the Volume (including holes). |
|
of the Surface (including holes). |
|
1856 |
""" |
""" |
1857 |
out = []+ self.getSurfaceLoop().getSurfaces() |
out = []+ self.getSurfaceLoop().getSurfaces() |
1858 |
for h in self.getHoles(): out+=h.getSurfaces() |
for h in self.getHoles(): out+=h.getSurfaces() |
1859 |
return out |
return out |
1860 |
|
|
1861 |
|
def hasHole(self): |
1862 |
|
""" |
1863 |
|
Returns True if a hole is present. |
1864 |
|
""" |
1865 |
|
return len(self.getHoles())>0 |
1866 |
class PropertySet(Primitive, PrimitiveBase): |
class PropertySet(Primitive, PrimitiveBase): |
1867 |
""" |
""" |
1868 |
Defines a group of `Primitive` s which can be accessed through a name. |
Defines a group of `Primitive` s which can be accessed through a name. |