///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2018- Equinor ASA // // ResInsight 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. // // ResInsight 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 at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiaCellDividingTools.h" #include "cvfAssert.h" #include #include //-------------------------------------------------------------------------------------------------- /// Internal functions //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- /// Splits a line in a number of equal parts //-------------------------------------------------------------------------------------------------- std::vector splitLine( cvf::Vec3d ptStart, cvf::Vec3d ptEnd, size_t partCount ); //-------------------------------------------------------------------------------------------------- /// Calculates all points on a face described by edge points from all four edges. /// The result is a grid of points including the given edge points /// /// edgeXPtsHigh /// |-------------| /// | | /// edgeYPtsLow | | edgeYPtsHigh /// | | /// |-------------| /// edgeXPtsLow /// //-------------------------------------------------------------------------------------------------- std::vector> calcFacePoints( const std::vector edgeXPtsLow, const std::vector edgeXPtsHigh, const std::vector edgeYPtsLow, const std::vector edgeYPtsHigh ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RiaCellDividingTools::createHexCornerCoords( std::array mainCellCorners, size_t nx, size_t ny, size_t nz ) { std::array, 12> edgeCorners = { std::make_pair( 0, 1 ), std::make_pair( 3, 2 ), std::make_pair( 4, 5 ), std::make_pair( 7, 6 ), // X std::make_pair( 0, 3 ), std::make_pair( 4, 7 ), std::make_pair( 1, 2 ), std::make_pair( 5, 6 ), // Y std::make_pair( 0, 4 ), std::make_pair( 1, 5 ), std::make_pair( 3, 7 ), std::make_pair( 2, 6 ), // Z }; std::array nxyz = { nx, ny, nz }; std::array, 12> edgePoints; for ( int i = 0; i < 12; i++ ) { int partCountsIndex = i / 4; edgePoints[i] = splitLine( mainCellCorners[edgeCorners[i].first], mainCellCorners[edgeCorners[i].second], nxyz[partCountsIndex] ); } // lowIJ, highIJ, lowJK, highKJ, std::vector>> nodes; nodes.reserve( ( nx + 1 ) * ( ny + 1 ) * ( nz + 1 ) ); auto xyFacePtsLow = calcFacePoints( edgePoints[0], edgePoints[1], edgePoints[4], edgePoints[6] ); auto xyFacePtsHigh = calcFacePoints( edgePoints[2], edgePoints[3], edgePoints[5], edgePoints[7] ); auto yzFacePtsLow = calcFacePoints( edgePoints[4], edgePoints[5], edgePoints[8], edgePoints[10] ); auto yzFacePtsHigh = calcFacePoints( edgePoints[6], edgePoints[7], edgePoints[9], edgePoints[11] ); auto xzFacePtsLow = calcFacePoints( edgePoints[0], edgePoints[2], edgePoints[8], edgePoints[9] ); auto xzFacePtsHigh = calcFacePoints( edgePoints[1], edgePoints[3], edgePoints[10], edgePoints[11] ); nodes.push_back( xyFacePtsLow ); for ( size_t z = 1; z < nz; z++ ) { auto xyFacePoints = calcFacePoints( xzFacePtsLow[z], xzFacePtsHigh[z], yzFacePtsLow[z], yzFacePtsHigh[z] ); nodes.push_back( xyFacePoints ); } nodes.push_back( xyFacePtsHigh ); std::vector coords; coords.reserve( nx * ny * nz * 8 ); for ( size_t z = 1; z < nz + 1; z++ ) { for ( size_t y = 1; y < ny + 1; y++ ) { for ( size_t x = 1; x < nx + 1; x++ ) { std::array cs; cs[0] = nodes[z - 1][y - 1][x - 1]; cs[1] = nodes[z - 1][y - 1][x]; cs[2] = nodes[z - 1][y][x]; cs[3] = nodes[z - 1][y][x - 1]; cs[4] = nodes[z][y - 1][x - 1]; cs[5] = nodes[z][y - 1][x]; cs[6] = nodes[z][y][x]; cs[7] = nodes[z][y][x - 1]; coords.insert( coords.end(), cs.begin(), cs.end() ); } } } return coords; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RiaCellDividingTools::computeFlowDistance( const std::array& cellVertices, const cvf::Vec3d& areaCenter ) { auto subCellCorners = createHexCornerCoords( cellVertices, 2, 2, 2 ); double weightedDistanceTotal = 0.0; double weightTotal = 0.0; for ( size_t c = 0; c < 8; c++ ) { double weight = 1.0; weightTotal += weight; cvf::Vec3d centerOfSubCell = cvf::Vec3d::ZERO; { cvf::Vec3d vertexSum = cvf::Vec3d::ZERO; for ( size_t v = 0; v < 8; v++ ) vertexSum += subCellCorners[c * 8 + v]; centerOfSubCell = vertexSum / 8; } auto dist = ( centerOfSubCell - areaCenter ).length(); weightedDistanceTotal += ( dist * weight ); } return weightedDistanceTotal / weightTotal; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector splitLine( cvf::Vec3d ptStart, cvf::Vec3d ptEnd, size_t partCount ) { std::vector pts = { ptStart }; for ( size_t i = 1; i < partCount; i++ ) { pts.push_back( cvf::Vec3d( ptStart.x() + ( ptEnd.x() - ptStart.x() ) * i / partCount, ptStart.y() + ( ptEnd.y() - ptStart.y() ) * i / partCount, ptStart.z() + ( ptEnd.z() - ptStart.z() ) * i / partCount ) ); } pts.push_back( ptEnd ); return pts; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector> calcFacePoints( const std::vector edgeXPtsLow, const std::vector edgeXPtsHigh, const std::vector edgeYPtsLow, const std::vector edgeYPtsHigh ) { CVF_ASSERT( edgeXPtsLow.size() == edgeXPtsHigh.size() && edgeYPtsLow.size() == edgeYPtsHigh.size() ); size_t xSize = edgeXPtsLow.size(); size_t ySize = edgeYPtsLow.size(); std::vector> pts; // Add low edge points pts.push_back( edgeXPtsLow ); // Interior points for ( size_t y = 1; y < ySize - 1; y++ ) { auto interiorPts = splitLine( edgeYPtsLow[y], edgeYPtsHigh[y], xSize - 1 ); pts.push_back( interiorPts ); } // Add low edge points pts.push_back( edgeXPtsHigh ); return pts; }