///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil 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 "RigHexIntersectionTools.h" #include "RigCellGeometryTools.h" #include "cvfBoundingBox.h" #include "cvfGeometryTools.h" #include "cvfRay.h" #include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RigHexIntersectionTools::lineHexCellIntersection( const cvf::Vec3d p1, const cvf::Vec3d p2, const cvf::Vec3d hexCorners[8], const size_t hexIndex, std::vector* intersections ) { CVF_ASSERT( intersections != nullptr ); std::set uniqueIntersections; for ( int face = 0; face < 6; ++face ) { cvf::ubyte faceVertexIndices[4]; cvf::StructGridInterface::cellFaceVertexIndices( static_cast( face ), faceVertexIndices ); cvf::Vec3d intersection; bool isEntering = false; cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter( hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]] ); for ( int i = 0; i < 4; ++i ) { int next = i < 3 ? i + 1 : 0; int intsStatus = cvf::GeometryTools::intersectLineSegmentTriangle( p1, p2, hexCorners[faceVertexIndices[i]], hexCorners[faceVertexIndices[next]], faceCenter, &intersection, &isEntering ); if ( intsStatus == 1 ) { uniqueIntersections.insert( HexIntersectionInfo( intersection, isEntering, static_cast( face ), hexIndex ) ); } } } int intersectionCount = 0; for ( const auto& intersection : uniqueIntersections ) { intersections->push_back( intersection ); ++intersectionCount; } return intersectionCount; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigHexIntersectionTools::lineIntersectsHexCell( const cvf::Vec3d p1, const cvf::Vec3d p2, const cvf::Vec3d hexCorners[8] ) { for ( int face = 0; face < 6; ++face ) { cvf::ubyte faceVertexIndices[4]; cvf::StructGridInterface::cellFaceVertexIndices( static_cast( face ), faceVertexIndices ); cvf::Vec3d intersection; bool isEntering = false; cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter( hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]] ); for ( int i = 0; i < 4; ++i ) { int next = i < 3 ? i + 1 : 0; int intsStatus = cvf::GeometryTools::intersectLineSegmentTriangle( p1, p2, hexCorners[faceVertexIndices[i]], hexCorners[faceVertexIndices[next]], faceCenter, &intersection, &isEntering ); if ( intsStatus == 1 ) { return true; } } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigHexIntersectionTools::isPointInCell( const cvf::Vec3d point, const cvf::Vec3d hexCorners[8] ) { cvf::Ray ray; ray.setOrigin( point ); size_t intersections = 0; for ( int face = 0; face < 6; ++face ) { cvf::ubyte faceVertexIndices[4]; cvf::StructGridInterface::cellFaceVertexIndices( static_cast( face ), faceVertexIndices ); cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter( hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]] ); for ( int i = 0; i < 4; ++i ) { int next = i < 3 ? i + 1 : 0; if ( ray.triangleIntersect( hexCorners[faceVertexIndices[i]], hexCorners[faceVertexIndices[next]], faceCenter ) ) { ++intersections; } } } return intersections % 2 == 1; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigHexIntersectionTools::planeHexCellIntersection( cvf::Vec3d* hexCorners, const cvf::Plane& fracturePlane, std::list>& intersectionLineSegments ) { bool isCellIntersected = false; cvf::ubyte faceVertexIndices[4]; caf::HexGridIntersectionTools::ClipVx triangleIntersectionPoint1; caf::HexGridIntersectionTools::ClipVx triangleIntersectionPoint2; bool isMostVxesOnPositiveSideOfP1 = false; for ( int face = 0; face < 6; ++face ) { cvf::StructGridInterface::cellFaceVertexIndices( static_cast( face ), faceVertexIndices ); cvf::Vec3d faceCenter = cvf::GeometryTools::computeFaceCenter( hexCorners[faceVertexIndices[0]], hexCorners[faceVertexIndices[1]], hexCorners[faceVertexIndices[2]], hexCorners[faceVertexIndices[3]] ); for ( int i = 0; i < 4; i++ ) { int next = i < 3 ? i + 1 : 0; bool isIntersectingPlane = caf::HexGridIntersectionTools::planeTriangleIntersection( fracturePlane, hexCorners[faceVertexIndices[i]], 0, hexCorners[faceVertexIndices[next]], 1, faceCenter, 2, &triangleIntersectionPoint1, &triangleIntersectionPoint2, &isMostVxesOnPositiveSideOfP1 ); if ( isIntersectingPlane ) { isCellIntersected = true; intersectionLineSegments.emplace_back( triangleIntersectionPoint1.vx, triangleIntersectionPoint2.vx ); } } } return isCellIntersected; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RigHexIntersectionTools::planeHexIntersectionPolygons( std::array hexCorners, cvf::Mat4d transformMatrixForPlane, std::vector>& polygons ) { bool isCellIntersected = false; cvf::Plane fracturePlane; fracturePlane.setFromPointAndNormal( transformMatrixForPlane.translation(), static_cast( transformMatrixForPlane.col( 2 ) ) ); // Find line-segments where cell and fracture plane intersects std::list> intersectionLineSegments; isCellIntersected = planeHexCellIntersection( hexCorners.data(), fracturePlane, intersectionLineSegments ); RigCellGeometryTools::createPolygonFromLineSegments( intersectionLineSegments, polygons ); return isCellIntersected; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool operator<( const HexIntersectionInfo& hi1, const HexIntersectionInfo& hi2 ) { const double tolerance = 1e-6; if ( hi1.m_hexIndex != hi2.m_hexIndex ) return hi1.m_hexIndex < hi2.m_hexIndex; if ( hi1.m_face != hi2.m_face ) return hi1.m_face < hi2.m_face; if ( hi1.m_isIntersectionEntering != hi2.m_isIntersectionEntering ) return hi1.m_isIntersectionEntering < hi2.m_isIntersectionEntering; if ( hi1.m_face != hi2.m_face ) return hi1.m_face < hi2.m_face; if ( cvf::Math::abs( hi2.m_intersectionPoint.x() - hi1.m_intersectionPoint.x() ) > tolerance ) return hi1.m_intersectionPoint.x() < hi2.m_intersectionPoint.x(); if ( cvf::Math::abs( hi2.m_intersectionPoint.y() - hi1.m_intersectionPoint.y() ) > tolerance ) return hi1.m_intersectionPoint.y() < hi2.m_intersectionPoint.y(); if ( cvf::Math::abs( hi2.m_intersectionPoint.z() - hi1.m_intersectionPoint.z() ) > tolerance ) return hi1.m_intersectionPoint.z() < hi2.m_intersectionPoint.z(); return false; }