1674 {
1675 TRACE();
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688 const MInt edgeEndPos[4] = {1, 3, 0, 2};
1689
1690
1691
1692 MFloat normals[2 * nDim][nDim];
1693 for(
MInt d1 = 0; d1 < 2 * nDim; d1++) {
1694 for(
MInt d2 = 0; d2 < nDim; d2++) {
1695 if(d1 >= (2 * d2) && d1 < (2 * (d2 + 1))) {
1697 normals[d1][d2] = pow(-F1, expo);
1698 } else {
1699 normals[d1][d2] = F0;
1700 }
1701 }
1702 }
1703
1704 const MInt noStlElementEdges = (nDim == 3) ? 3 : 1;
1705 const MInt noElementEdges = (nDim == 3) ? 12 : 4;
1707
1708 struct stlElement {
1709 MFloat points[nDim][nDim];
1710 MFloat edges[noStlElementEdges][2 * nDim];
1711 std::array<MFloat, nDim> normal;
1712 std::array<MBool, nDim> pointInsideCell;
1713 MInt noInsidePoints;
1714 std::array<MInt, noStlElementEdges> noCutsPerEdge;
1715 MBool cutSurfPerEdge[noStlElementEdges][2 * nDim];
1716 MInt noCuttedSurfaces;
1717 std::array<MBool, noStlElementEdges> edgeNotCutted;
1718 std::array<MBool, noStlElementEdges> edgeOnSurface;
1719 };
1720
1722 MFloat edges[noElementEdges][2 * nDim];
1723 std::array<MBool, noElementEdges> edgeIsCut;
1725 std::array<MBool, noElementEdges> edgeOnSurface;
1726 };
1727
1728
1731
1735 const MFloat halfLength = cellLength * 0.5;
1736
1737
1738
1740 for(
MInt e = 0; e < noElementEdges; e++) {
1741 if(nDim == 2) {
1742 for(
MInt d = 0; d < nDim; d++) {
1746 }
1747 } else {
1748 if(e < 4) {
1749 for(
MInt d = 0; d < nDim; d++) {
1753 }
1754 } else if(e < 8) {
1755 for(
MInt d = 0; d < nDim; d++) {
1759 }
1760 } else {
1761 for(
MInt d = 0; d < nDim; d++) {
1764 MInt h = edgeEndPos[e - 8] + 4;
1766 }
1767 }
1768 }
1769 }
1770
1771
1773 for(
MInt j = 0; j < nDim; j++) {
1776 }
1777 std::vector<MInt> nodeList;
1779 for(
MInt n = 0; n < (
MInt)nodeList.size(); n++) {
1780 std::vector<std::vector<MFloat>> cutPointList;
1781
1782
1784 continue;
1785 }
1786
1787
1788
1789 stlElement stl;
1790 for(
MInt e = 0; e < noStlElementEdges; e++) {
1791 for(
MInt d = 0; d < nDim; d++) {
1793 if(e + 1 < nDim) {
1794 stl.edges[e][d + nDim] =
m_solver->
m_geometry->elements[nodeList[n]].m_vertices[e + 1][d];
1795 } else {
1796 stl.edges[e][d + nDim] =
m_solver->
m_geometry->elements[nodeList[n]].m_vertices[0][d];
1797 }
1798 }
1799 }
1800 if(nDim == 3) {
1801 for(
MInt d = 0; d < nDim; d++) {
1803 }
1804 } else {
1805 stl.normal[0] = stl.edges[0][1 + nDim] - stl.edges[0][1];
1806 stl.normal[1] = stl.edges[0][0 + nDim] - stl.edges[0][0];
1807 }
1808
1809
1810 stl.noInsidePoints = 0;
1811 for(
MInt point = 0; point < nDim; point++) {
1812 stl.pointInsideCell[point] = false;
1813 MBool isInside =
true;
1814 for(
MInt d = 0; d < nDim; d++) {
1815 stl.points[point][d] =
m_solver->
m_geometry->elements[nodeList[n]].m_vertices[point][d];
1816 if(stl.points[point][d] < (target[d]) || stl.points[point][d] > (target[d + nDim])) {
1817 isInside = false;
1818 }
1819 }
1820 stl.pointInsideCell[point] = isInside;
1821
1822 if(stl.pointInsideCell[point]) {
1823 stl.noInsidePoints++;
1824 std::vector<MFloat> cutPoint;
1825 for(
MInt d = 0; d < nDim; d++) {
1826 cutPoint.push_back(stl.points[point][d]);
1827 }
1828 cutPointList.push_back(cutPoint);
1829 }
1830 }
1831
1832
1833
1834
1835 for(
MInt e = 0; e < noStlElementEdges; e++) {
1837 MInt point2 = (e + 1 < nDim) ? (e + 1) : 0;
1838 stl.edgeNotCutted[e] = (stl.pointInsideCell[point1] && stl.pointInsideCell[point2]);
1839 stl.noCutsPerEdge[e] = 0;
1840 stl.noCuttedSurfaces = 0;
1841 stl.edgeOnSurface[e] = false;
1842 for(
MInt surface = 0; surface < 2 * nDim; surface++) {
1843 stl.cutSurfPerEdge[e][surface] = false;
1844 }
1845 }
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855 if(stl.noInsidePoints < nDim) {
1856 switch(nDim) {
1857 case 2: {
1858 for(
MInt e = 0; e < noStlElementEdges; e++) {
1859
1860 if(stl.edgeNotCutted[e]) continue;
1861
1862
1863
1864
1865 for(
MInt surface = 0; surface < 2 * nDim; surface++) {
1866 const MFloat numer = stl.edges[e][1 + nDim] - stl.edges[e][1];
1867 const MFloat denom = stl.edges[e][0 + nDim] - stl.edges[e][0];
1870 const MFloat minStlEdgeX =
mMin(stl.edges[e][0], stl.edges[e][0 + nDim]);
1871 const MFloat minStlEdgeY =
mMin(stl.edges[e][1], stl.edges[e][1 + nDim]);
1872 const MFloat maxStlEdgeX =
mMax(stl.edges[e][0], stl.edges[e][0 + nDim]);
1873 const MFloat maxStlEdgeY =
mMax(stl.edges[e][1], stl.edges[e][1 + nDim]);
1874
1875
1876 if(
approx(normals[surface][0], F0, eps)) {
1877 const MFloat y = coordY + normals[surface][1] * halfLength;
1878 const MFloat x1 = coordX - halfLength;
1879 const MFloat x2 = coordX + halfLength;
1880
1881
1882
1883
1884 if(
approx(numer, F0, eps)) {
1885 continue;
1886 }
1887
1888
1889 else if(
approx(denom, F0, eps)) {
1890
1891
1892 if(x1 <= stl.edges[e][0 + nDim] && x2 >= stl.edges[e][0 + nDim]) {
1893
1894
1895 if(minStlEdgeY <= y && maxStlEdgeY >=
y) {
1896 std::vector<MFloat> cutPoint;
1897 cutPoint.push_back(stl.edges[e][0 + nDim]);
1898 cutPoint.push_back(
y);
1899 cutPointList.push_back(cutPoint);
1900 }
1901 }
1902 }
1903
1904
1905
1906
1907 else {
1908 const MFloat cutPointX = (denom / numer) * (
y - stl.edges[e][1]) + stl.edges[e][0];
1910 if(cutPointX >= x1 && cutPointX <= x2 && cutPointX >= minStlEdgeX && cutPointX <= maxStlEdgeX) {
1911 std::vector<MFloat> cutPoint;
1912 cutPoint.push_back(cutPointX);
1913 cutPoint.push_back(cutPointY);
1914 cutPointList.push_back(cutPoint);
1915 }
1916 }
1917 }
1918
1919 if(
approx(normals[surface][1], F0, eps)) {
1920 const MFloat x = coordX + normals[surface][0] * halfLength;
1921 const MFloat y1 = coordY - halfLength;
1922 const MFloat y2 = coordY + halfLength;
1923
1924
1925
1926
1927 if(
approx(denom, F0, eps)) {
1928 continue;
1929 }
1930
1931
1932 else if(
approx(numer, F0, eps)) {
1933
1934
1935 if(y1 <= stl.edges[e][1 + nDim] && y2 >= stl.edges[e][1 + nDim]) {
1936
1937
1938 if(minStlEdgeX <= x && maxStlEdgeX >= x) {
1939 std::vector<MFloat> cutPoint;
1940 cutPoint.push_back(x);
1941 cutPoint.push_back(stl.edges[e][1 + nDim]);
1942 cutPointList.push_back(cutPoint);
1943 }
1944 }
1945 }
1946
1947
1948
1949
1950 else {
1951 const MFloat cutPointX = x;
1952 const MFloat cutPointY = (numer / denom) * (x - stl.edges[e][0]) + stl.edges[e][1];
1953
1954 if(cutPointY >= y1 && cutPointY <= y2 && cutPointY >= minStlEdgeY && cutPointY <= maxStlEdgeY) {
1955 std::vector<MFloat> cutPoint;
1956 cutPoint.push_back(cutPointX);
1957 cutPoint.push_back(cutPointY);
1958 cutPointList.push_back(cutPoint);
1959 }
1960 }
1961 }
1962 }
1963 }
1964 break;
1965 }
1966 case 3: {
1967 for(
MInt e = 0; e < noStlElementEdges; e++) {
1968
1969 if(stl.edgeNotCutted[e]) continue;
1970
1971
1972
1973 for(
MInt surface = 0; surface < 2 * nDim; surface++) {
1976 for(
MInt d = 0; d < nDim; d++) {
1978 denom += (normals[surface][d] * (stl.edges[e][d + nDim] - stl.edges[e][d]));
1979 numer += (normals[surface][d] * locationVec);
1980 }
1981 for(
MInt d = 0; d < nDim; d++) {
1982 numer -= (normals[surface][d] * stl.edges[e][d]);
1983 }
1984 if(!
approx(denom, F0, eps)) {
1985
1986 MFloat lambda = numer / denom;
1987 if((lambda >= F0) && (lambda <= F1)) {
1988 MBool validIntersection =
true;
1989 std::vector<MFloat> cutPoint;
1990 for(
MInt d = 0; d < nDim; d++) {
1991 MFloat point = stl.edges[e][d] + lambda * (stl.edges[e][d + nDim] - stl.edges[e][d]);
1993 point = target[d];
1994 }
else if(fabs(point - target[d + nDim]) <
m_solver->
m_eps) {
1995 point = target[d + nDim];
1996 }
1997 cutPoint.push_back(point);
1998 if(point < (target[d]) || point > (target[d + nDim])) {
1999 validIntersection = false;
2000 }
2001 }
2002 if(validIntersection) {
2003 stl.cutSurfPerEdge[e][surface] = true;
2004 cutPointList.push_back(cutPoint);
2005 MBool surfCutBefore =
false;
2006 for(
MInt prevE = 0; prevE < e - 1; prevE++) {
2007 if(stl.cutSurfPerEdge[prevE][surface]) {
2008 surfCutBefore = true;
2009 break;
2010 }
2011 }
2012 if(!surfCutBefore) stl.noCuttedSurfaces++;
2013 stl.noCutsPerEdge[e]++;
2014 }
2015 }
2016 }
2017 }
2018 }
2019 break;
2020 }
2021 default: {
2022 mTerm(1, AT_,
"ERROR: Wrong number of dimensions! Aborting.");
2023 break;
2024 }
2025 }
2026
2027 if(nDim == 3) {
2028
2029 for(
MInt e = 0; e < noElementEdges; e++) {
2030 ele.edgeOnSurface[e] = false;
2033 for(
MInt d = 0; d < nDim; d++) {
2034 denom += (stl.normal[d] * (ele.edges[e][d + nDim] - ele.edges[e][d]));
2035 numer += (stl.normal[d] * stl.points[0][d]);
2036 }
2037 for(
MInt d = 0; d < nDim; d++) {
2038 numer -= (stl.normal[d] * ele.edges[e][d]);
2039 }
2040 if(
approx(denom, F0, eps)) {
2041 if(
approx(numer, F0, eps)) {
2042
2043
2044 ele.edgeOnSurface[e] = true;
2045 std::vector<MFloat> cutPoint1;
2046 std::vector<MFloat> cutPoint2;
2047 for(
MInt d = 0; d < nDim; d++) {
2048 cutPoint1.push_back(ele.edges[e][d]);
2049 cutPoint2.push_back(ele.edges[e][d + nDim]);
2050 }
2052 if(inside) {
2053 cutPointList.push_back(cutPoint1);
2054 }
2055
2056 inside =
pointInTriangle(stl.points[0], stl.points[1], stl.points[2], cutPoint2);
2057 if(inside) {
2058 cutPointList.push_back(cutPoint2);
2059 }
2060 break;
2061 } else {
2062
2063 continue;
2064 }
2065 } else {
2066 MFloat lambda = numer / denom;
2067 MBool inside =
false;
2068 std::vector<MFloat> cutPoint;
2069 if((lambda >= F0) && (lambda <= F1)) {
2070 for(
MInt d = 0; d < nDim; d++) {
2071 MFloat point = ele.edges[e][d] + lambda * (ele.edges[e][d + nDim] - ele.edges[e][d]);
2072 cutPoint.push_back(point);
2073 }
2074 inside =
pointInTriangle(stl.points[0], stl.points[1], stl.points[2], cutPoint);
2075 if(inside) {
2076 cutPointList.push_back(cutPoint);
2077 }
2078 }
2079 }
2080 }
2081 }
2082 }
2083
2084 for(
MInt c1 = 0; c1 < (
MInt)cutPointList.size(); c1++) {
2086 while(c2 < (
MInt)cutPointList.size()) {
2087 MBool dublicated =
true;
2088 for(
MInt d = 0; d < nDim; d++) {
2089 if(!
approx(cutPointList[c1][d], cutPointList[c2][d], eps)) {
2090 dublicated = false;
2091 break;
2092 }
2093 }
2094 if(dublicated) {
2095 cutPointList.erase(cutPointList.begin() + c2);
2096 } else {
2097 c2++;
2098 }
2099 }
2100 }
2101
2102 if((
MInt)cutPointList.size() < nDim)
continue;
2104 }
2105 }
2106 }
2107}
void setBoundaryStlElements(std::vector< std::vector< MFloat > > cutPointList, MFloat *normal, MInt segId, MInt i)
Add cut faces to the collector of the boundary cell.
MBool pointInTriangle(MFloat *A, MFloat *B, MFloat *C, std::vector< MFloat > P)
Checks if a point is inside a triangle.
const MFloat & c_coordinate(const MInt gCellId, const MInt dim) const
Returns the coordinate of the cell cellId for direction dim.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
static constexpr MFloat vertexPosition(MInt i, MInt j)