mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 14:40:26 -05:00
Improves geometry tools robustness and accuracy
* Replace asserts with alternatives * Refactors GeometryTools for improved robustness
This commit is contained in:
1 parent
fd5bdc96d2
commit
597cfd4d30
6 files changed
+402
-225
No files matched your search
@@ -1994,8 +1994,8 @@ void calculateConnectionGeometry( const RigCell& c1,
|
||||
c1.faceIndices( faceId, &face1 );
|
||||
c2.faceIndices( cvf::StructGridInterface::oppositeFace( faceId ), &face2 );
|
||||
|
||||
bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon,
|
||||
&intersections,
|
||||
bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( polygon,
|
||||
intersections,
|
||||
(cvf::EdgeIntersectStorage<size_t>*)nullptr,
|
||||
cvf::wrapArrayConst( &nodes ),
|
||||
face1.data(),
|
||||
|
||||
@@ -94,8 +94,8 @@ cvf::StructGridInterface::FaceType RigCellFaceGeometryTools::calculateCellFaceOv
|
||||
c1.faceIndices( ( cvf::StructGridInterface::FaceType )( fIdx ), &face1 );
|
||||
c2.faceIndices( cvf::StructGridInterface::oppositeFace( ( cvf::StructGridInterface::FaceType )( fIdx ) ), &face2 );
|
||||
|
||||
bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon,
|
||||
&intersections,
|
||||
bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( polygon,
|
||||
intersections,
|
||||
(cvf::EdgeIntersectStorage<size_t>*)nullptr,
|
||||
cvf::wrapArrayConst( &mainGrid.nodes() ),
|
||||
face1.data(),
|
||||
@@ -335,8 +335,8 @@ void RigCellFaceGeometryTools::extractConnectionsForFace( const RigFault::FaultF
|
||||
std::array<size_t, 4> candidateFaceIndices;
|
||||
mainGrid->cell( candidateCellIndex ).faceIndices( candidateFace, &candidateFaceIndices );
|
||||
|
||||
bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( &polygon,
|
||||
&intersections,
|
||||
bool foundOverlap = cvf::GeometryTools::calculateOverlapPolygonOfTwoQuads( polygon,
|
||||
intersections,
|
||||
(cvf::EdgeIntersectStorage<size_t>*)nullptr,
|
||||
cvf::wrapArrayConst( &mainGridNodes ),
|
||||
sourceFaceIndices.data(),
|
||||
|
||||
@@ -239,30 +239,20 @@ GeometryTools::IntersectionStatus inPlaneLineIntersect( double x1,
|
||||
double y4,
|
||||
double l1NormalizedTolerance,
|
||||
double l2NormalizedTolerance,
|
||||
double* x,
|
||||
double* y,
|
||||
double* fractionAlongLine1,
|
||||
double* fractionAlongLine2 )
|
||||
double& x,
|
||||
double& y,
|
||||
double& fractionAlongLine1,
|
||||
double& fractionAlongLine2 )
|
||||
{
|
||||
double mua, mub;
|
||||
double denom, numera, numerb;
|
||||
|
||||
denom = ( y4 - y3 ) * ( x2 - x1 ) - ( x4 - x3 ) * ( y2 - y1 );
|
||||
numera = ( x4 - x3 ) * ( y1 - y3 ) - ( y4 - y3 ) * ( x1 - x3 );
|
||||
numerb = ( x2 - x1 ) * ( y1 - y3 ) - ( y2 - y1 ) * ( x1 - x3 );
|
||||
auto denom = ( y4 - y3 ) * ( x2 - x1 ) - ( x4 - x3 ) * ( y2 - y1 );
|
||||
auto numera = ( x4 - x3 ) * ( y1 - y3 ) - ( y4 - y3 ) * ( x1 - x3 );
|
||||
auto numerb = ( x2 - x1 ) * ( y1 - y3 ) - ( y2 - y1 ) * ( x1 - x3 );
|
||||
|
||||
double EPS = 1e-40;
|
||||
|
||||
// Are the line coincident?
|
||||
if ( fabs( numera ) < EPS && fabs( numerb ) < EPS && fabs( denom ) < EPS )
|
||||
{
|
||||
#if 0
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
*fractionAlongLine1 = 0;
|
||||
*fractionAlongLine2 = 0;
|
||||
return GeometryTools::LINES_OVERLAP;
|
||||
#else
|
||||
cvf::Vec3d p12( x2 - x1, y2 - y1, 0 );
|
||||
cvf::Vec3d p13( x3 - x1, y3 - y1, 0 );
|
||||
cvf::Vec3d p34( x4 - x3, y4 - y3, 0 );
|
||||
@@ -274,10 +264,10 @@ GeometryTools::IntersectionStatus inPlaneLineIntersect( double x1,
|
||||
|
||||
if ( length12 < EPS )
|
||||
{
|
||||
*x = x1;
|
||||
*y = y1;
|
||||
*fractionAlongLine1 = 1;
|
||||
*fractionAlongLine2 = p13.length() / p34.length();
|
||||
x = x1;
|
||||
y = y1;
|
||||
fractionAlongLine1 = 1;
|
||||
fractionAlongLine2 = p13.length() / p34.length();
|
||||
return GeometryTools::LINES_OVERLAP;
|
||||
}
|
||||
|
||||
@@ -292,10 +282,10 @@ GeometryTools::IntersectionStatus inPlaneLineIntersect( double x1,
|
||||
if ( ( normDist13 < 0 - l1NormalizedTolerance && normDist14 < 0 - l1NormalizedTolerance ) ||
|
||||
( normDist13 > 1 + l1NormalizedTolerance && normDist14 > 1 + l1NormalizedTolerance ) )
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
*fractionAlongLine1 = 0;
|
||||
*fractionAlongLine2 = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
fractionAlongLine1 = 0;
|
||||
fractionAlongLine2 = 0;
|
||||
return GeometryTools::NO_INTERSECTION;
|
||||
}
|
||||
|
||||
@@ -311,68 +301,67 @@ GeometryTools::IntersectionStatus inPlaneLineIntersect( double x1,
|
||||
|
||||
if ( pt3IsInside && !pt4IsInside )
|
||||
{
|
||||
*fractionAlongLine1 = normDist13;
|
||||
*fractionAlongLine2 = 0.0;
|
||||
*x = x3;
|
||||
*y = y3;
|
||||
fractionAlongLine1 = normDist13;
|
||||
fractionAlongLine2 = 0.0;
|
||||
x = x3;
|
||||
y = y3;
|
||||
}
|
||||
else if ( pt4IsInside && !pt3IsInside )
|
||||
{
|
||||
*fractionAlongLine1 = normDist14;
|
||||
*fractionAlongLine2 = 1.0;
|
||||
*x = x4;
|
||||
*y = y4;
|
||||
fractionAlongLine1 = normDist14;
|
||||
fractionAlongLine2 = 1.0;
|
||||
x = x4;
|
||||
y = y4;
|
||||
}
|
||||
else if ( pt3IsInside && pt4IsInside )
|
||||
{
|
||||
// Return edge 2 vertex furthest along edge 1
|
||||
if ( normDist13 <= normDist14 )
|
||||
{
|
||||
*fractionAlongLine1 = normDist14;
|
||||
*fractionAlongLine2 = 1.0;
|
||||
*x = x4;
|
||||
*y = y4;
|
||||
fractionAlongLine1 = normDist14;
|
||||
fractionAlongLine2 = 1.0;
|
||||
x = x4;
|
||||
y = y4;
|
||||
}
|
||||
else
|
||||
{
|
||||
*fractionAlongLine1 = normDist13;
|
||||
*fractionAlongLine2 = 0.0;
|
||||
*x = x3;
|
||||
*y = y3;
|
||||
fractionAlongLine1 = normDist13;
|
||||
fractionAlongLine2 = 0.0;
|
||||
x = x3;
|
||||
y = y3;
|
||||
}
|
||||
}
|
||||
else // both outside on each side
|
||||
{
|
||||
// Return End of edge 1
|
||||
*fractionAlongLine1 = 1.0;
|
||||
*fractionAlongLine2 = normDist32;
|
||||
*x = x2;
|
||||
*y = y2;
|
||||
fractionAlongLine1 = 1.0;
|
||||
fractionAlongLine2 = normDist32;
|
||||
x = x2;
|
||||
y = y2;
|
||||
}
|
||||
|
||||
return GeometryTools::LINES_OVERLAP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Are the line parallel */
|
||||
if ( fabs( denom ) < EPS )
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
*fractionAlongLine1 = 0;
|
||||
*fractionAlongLine2 = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
fractionAlongLine1 = 0;
|
||||
fractionAlongLine2 = 0;
|
||||
|
||||
return GeometryTools::NO_INTERSECTION;
|
||||
}
|
||||
|
||||
/* Is the intersection along the the segments */
|
||||
mua = numera / denom;
|
||||
mub = numerb / denom;
|
||||
auto mua = numera / denom;
|
||||
auto mub = numerb / denom;
|
||||
|
||||
*x = x1 + mua * ( x2 - x1 );
|
||||
*y = y1 + mua * ( y2 - y1 );
|
||||
*fractionAlongLine1 = mua;
|
||||
*fractionAlongLine2 = mub;
|
||||
x = x1 + mua * ( x2 - x1 );
|
||||
y = y1 + mua * ( y2 - y1 );
|
||||
fractionAlongLine1 = mua;
|
||||
fractionAlongLine2 = mub;
|
||||
|
||||
if ( mua < 0 - l1NormalizedTolerance || 1 + l1NormalizedTolerance < mua || mub < 0 - l2NormalizedTolerance ||
|
||||
1 + l2NormalizedTolerance < mub )
|
||||
@@ -382,10 +371,10 @@ GeometryTools::IntersectionStatus inPlaneLineIntersect( double x1,
|
||||
else if ( fabs( mua ) < l1NormalizedTolerance || fabs( 1 - mua ) < l1NormalizedTolerance || fabs( mub ) < l2NormalizedTolerance ||
|
||||
fabs( 1 - mub ) < l2NormalizedTolerance )
|
||||
{
|
||||
if ( fabs( mua ) < l1NormalizedTolerance ) *fractionAlongLine1 = 0;
|
||||
if ( fabs( 1 - mua ) < l1NormalizedTolerance ) *fractionAlongLine1 = 1;
|
||||
if ( fabs( mub ) < l2NormalizedTolerance ) *fractionAlongLine2 = 0;
|
||||
if ( fabs( 1 - mub ) < l2NormalizedTolerance ) *fractionAlongLine2 = 1;
|
||||
if ( fabs( mua ) < l1NormalizedTolerance ) fractionAlongLine1 = 0;
|
||||
if ( fabs( 1 - mua ) < l1NormalizedTolerance ) fractionAlongLine1 = 1;
|
||||
if ( fabs( mub ) < l2NormalizedTolerance ) fractionAlongLine2 = 0;
|
||||
if ( fabs( 1 - mub ) < l2NormalizedTolerance ) fractionAlongLine2 = 1;
|
||||
return GeometryTools::LINES_TOUCH;
|
||||
}
|
||||
else
|
||||
@@ -403,13 +392,11 @@ GeometryTools::IntersectionStatus GeometryTools::inPlaneLineIntersect3D( const c
|
||||
const cvf::Vec3d& p2,
|
||||
const cvf::Vec3d& p3,
|
||||
const cvf::Vec3d& p4,
|
||||
cvf::Vec3d* intersectionPoint,
|
||||
double* fractionAlongLine1,
|
||||
double* fractionAlongLine2,
|
||||
cvf::Vec3d& intersectionPoint,
|
||||
double& fractionAlongLine1,
|
||||
double& fractionAlongLine2,
|
||||
double tolerance )
|
||||
{
|
||||
CVF_ASSERT( intersectionPoint != nullptr );
|
||||
|
||||
int Z = findClosestAxis( planeNormal );
|
||||
int X = ( Z + 1 ) % 3;
|
||||
int Y = ( Z + 2 ) % 3;
|
||||
@@ -420,16 +407,16 @@ GeometryTools::IntersectionStatus GeometryTools::inPlaneLineIntersect3D( const c
|
||||
double l2NormTol = tolerance / ( p4 - p3 ).length();
|
||||
|
||||
IntersectionStatus intersectionStatus =
|
||||
inPlaneLineIntersect( p1[X], p1[Y], p2[X], p2[Y], p3[X], p3[Y], p4[X], p4[Y], l1NormTol, l2NormTol, &x, &y, fractionAlongLine1, fractionAlongLine2 );
|
||||
inPlaneLineIntersect( p1[X], p1[Y], p2[X], p2[Y], p3[X], p3[Y], p4[X], p4[Y], l1NormTol, l2NormTol, x, y, fractionAlongLine1, fractionAlongLine2 );
|
||||
|
||||
// Check if we have a valid intersection point
|
||||
if ( intersectionStatus == NO_INTERSECTION || intersectionStatus == LINES_OVERLAP )
|
||||
{
|
||||
intersectionPoint->setZero();
|
||||
intersectionPoint.setZero();
|
||||
}
|
||||
else
|
||||
{
|
||||
*intersectionPoint = p1 + ( *fractionAlongLine1 ) * ( p2 - p1 );
|
||||
intersectionPoint = p1 + ( fractionAlongLine1 ) * ( p2 - p1 );
|
||||
}
|
||||
|
||||
return intersectionStatus;
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "cvfArrayWrapperConst.h"
|
||||
#include "cvfMatrix3.h"
|
||||
#include "cvfMatrix4.h"
|
||||
|
||||
#include "cafPdmLogging.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
@@ -93,7 +96,7 @@ public:
|
||||
std::vector<cvf::Vec3d>* createdVertexes );
|
||||
|
||||
template <typename VerticeArrayType, typename IndexType>
|
||||
static bool insertVertexInPolygon( std::vector<IndexType>* polygon,
|
||||
static bool insertVertexInPolygon( std::vector<IndexType>& polygon,
|
||||
ArrayWrapperConst<VerticeArrayType, cvf::Vec3d> nodeCoords,
|
||||
IndexType vertexIndex,
|
||||
double tolerance );
|
||||
@@ -103,9 +106,9 @@ public:
|
||||
const cvf::Vec3d& p2,
|
||||
const cvf::Vec3d& p3,
|
||||
const cvf::Vec3d& p4,
|
||||
cvf::Vec3d* intersectionPoint,
|
||||
double* fractionAlongLine1,
|
||||
double* fractionAlongLine2,
|
||||
cvf::Vec3d& intersectionPoint,
|
||||
double& fractionAlongLine1,
|
||||
double& fractionAlongLine2,
|
||||
double tolerance = 1e-6 );
|
||||
|
||||
template <typename VerticeArrayType, typename PolygonArrayType, typename IndexType>
|
||||
@@ -113,12 +116,12 @@ public:
|
||||
ArrayWrapperConst<VerticeArrayType, cvf::Vec3d> vertices,
|
||||
ArrayWrapperConst<PolygonArrayType, IndexType> indices,
|
||||
const cvf::Vec3d& point,
|
||||
int* touchedEdgeIndex,
|
||||
int& touchedEdgeIndex,
|
||||
double tolerance = 1e-6 );
|
||||
|
||||
template <typename VerticeArrayType, typename IndexType>
|
||||
static bool calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>* polygon,
|
||||
std::vector<cvf::Vec3d>* createdVertexes,
|
||||
static bool calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>& polygon,
|
||||
std::vector<cvf::Vec3d>& createdVertexes,
|
||||
EdgeIntersectStorage<IndexType>* edgeIntersectionStorage,
|
||||
ArrayWrapperConst<VerticeArrayType, cvf::Vec3d> nodes,
|
||||
const IndexType cv1CubeFaceIndices[4],
|
||||
@@ -148,8 +151,8 @@ public:
|
||||
IndexType e2P2,
|
||||
IndexType* vxIndexIntersectionPoint,
|
||||
GeometryTools::IntersectionStatus* intersectionStatus,
|
||||
double* fractionAlongEdge1,
|
||||
double* fractionAlongEdge2 );
|
||||
double& fractionAlongEdge1,
|
||||
double& fractionAlongEdge2 );
|
||||
void addIntersection( IndexType e1P1,
|
||||
IndexType e1P2,
|
||||
IndexType e2P1,
|
||||
|
||||
@@ -27,6 +27,11 @@ namespace cvf
|
||||
template <typename Vec3Type>
|
||||
Vec3Type GeometryTools::computePolygonCenter( const std::vector<Vec3Type>& polygon )
|
||||
{
|
||||
if ( polygon.empty() )
|
||||
{
|
||||
return Vec3Type::UNDEFINED;
|
||||
}
|
||||
|
||||
Vec3Type s;
|
||||
|
||||
for ( size_t i = 0; i < polygon.size(); i++ )
|
||||
@@ -65,25 +70,22 @@ DataType GeometryTools::interpolateQuad( const cvf::Vec3d& v1,
|
||||
/// Todo: If a vertex is replaced, the VxToCv map in TimeStepGeometry should be updated
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename VerticeArrayType, typename IndexType>
|
||||
bool GeometryTools::insertVertexInPolygon( std::vector<IndexType>* polygon,
|
||||
bool GeometryTools::insertVertexInPolygon( std::vector<IndexType>& polygon,
|
||||
ArrayWrapperConst<VerticeArrayType, cvf::Vec3d> nodeCoords,
|
||||
IndexType vertexIndex,
|
||||
double tolerance )
|
||||
{
|
||||
CVF_ASSERT( polygon );
|
||||
|
||||
// Check if vertex is directly included already
|
||||
|
||||
for ( typename std::vector<IndexType>::iterator it = polygon->begin(); it != polygon->end(); ++it )
|
||||
for ( typename std::vector<IndexType>::iterator it = polygon.begin(); it != polygon.end(); ++it )
|
||||
{
|
||||
if ( *it == vertexIndex ) return true;
|
||||
}
|
||||
|
||||
#if 1
|
||||
// Check if the new point is within tolerance of one of the polygon vertices
|
||||
|
||||
bool existsOrInserted = false;
|
||||
for ( typename std::vector<IndexType>::iterator it = polygon->begin(); it != polygon->end(); ++it )
|
||||
for ( typename std::vector<IndexType>::iterator it = polygon.begin(); it != polygon.end(); ++it )
|
||||
{
|
||||
if ( ( nodeCoords[*it] - nodeCoords[vertexIndex] ).length() < tolerance )
|
||||
{
|
||||
@@ -93,14 +95,13 @@ bool GeometryTools::insertVertexInPolygon( std::vector<IndexType>*
|
||||
}
|
||||
|
||||
if ( existsOrInserted ) return true;
|
||||
#endif
|
||||
|
||||
// Copy the start polygon to a list
|
||||
|
||||
std::list<IndexType> listPolygon;
|
||||
for ( size_t pcIdx = 0; pcIdx < polygon->size(); ++pcIdx )
|
||||
for ( size_t pcIdx = 0; pcIdx < polygon.size(); ++pcIdx )
|
||||
{
|
||||
listPolygon.push_back( ( *polygon )[pcIdx] );
|
||||
listPolygon.push_back( polygon[pcIdx] );
|
||||
}
|
||||
|
||||
// Insert vertex in polygon if the distance to one of the edges is small enough
|
||||
@@ -125,10 +126,10 @@ bool GeometryTools::insertVertexInPolygon( std::vector<IndexType>*
|
||||
|
||||
// Write polygon back into the vector
|
||||
|
||||
polygon->clear();
|
||||
polygon.clear();
|
||||
for ( typename std::list<IndexType>::iterator it = listPolygon.begin(); it != listPolygon.end(); ++it )
|
||||
{
|
||||
polygon->push_back( *it );
|
||||
polygon.push_back( *it );
|
||||
}
|
||||
|
||||
return existsOrInserted;
|
||||
@@ -157,7 +158,7 @@ bool GeometryTools::isPointTouchingIndexedPolygon( const cvf::Vec3d&
|
||||
cvf::ArrayWrapperConst<VerticeArrayType, cvf::Vec3d> vertices,
|
||||
cvf::ArrayWrapperConst<PolygonArrayType, IndexType> indices,
|
||||
const cvf::Vec3d& point,
|
||||
int* touchedEdgeIndex,
|
||||
int& touchedEdgeIndex,
|
||||
double tolerance )
|
||||
{
|
||||
size_t numIndices = indices.size();
|
||||
@@ -183,9 +184,7 @@ bool GeometryTools::isPointTouchingIndexedPolygon( const cvf::Vec3d&
|
||||
size_t firstIdx;
|
||||
size_t secondIdx;
|
||||
|
||||
CVF_TIGHT_ASSERT( touchedEdgeIndex );
|
||||
|
||||
*touchedEdgeIndex = -1;
|
||||
touchedEdgeIndex = -1;
|
||||
for ( firstIdx = 0, secondIdx = 1; firstIdx < numIndices; ++firstIdx, ++secondIdx )
|
||||
{
|
||||
if ( secondIdx >= numIndices ) secondIdx = 0;
|
||||
@@ -195,7 +194,7 @@ bool GeometryTools::isPointTouchingIndexedPolygon( const cvf::Vec3d&
|
||||
double sqDist = GeometryTools::linePointSquareDist( vx0, vx1, point );
|
||||
if ( sqDist < tolerance * tolerance )
|
||||
{
|
||||
*touchedEdgeIndex = static_cast<int>( firstIdx );
|
||||
touchedEdgeIndex = static_cast<int>( firstIdx );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -247,20 +246,17 @@ bool GeometryTools::isPointTouchingIndexedPolygon( const cvf::Vec3d&
|
||||
/// The second face must have opposite winding of the first
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename VerticeArrayType, typename IndexType>
|
||||
bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>* polygon,
|
||||
std::vector<cvf::Vec3d>* createdVertexes,
|
||||
bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>& polygon,
|
||||
std::vector<cvf::Vec3d>& createdVertexes,
|
||||
EdgeIntersectStorage<IndexType>* edgeIntersectionStorage,
|
||||
ArrayWrapperConst<VerticeArrayType, cvf::Vec3d> nodes,
|
||||
const IndexType cv1CubeFaceIndices[4],
|
||||
const IndexType cv2CubeFaceIndices[4],
|
||||
double tolerance )
|
||||
{
|
||||
CVF_ASSERT( polygon );
|
||||
CVF_ASSERT( createdVertexes );
|
||||
|
||||
// Topology analysis
|
||||
|
||||
IndexType newVertexIndex = static_cast<IndexType>( nodes.size() + createdVertexes->size() );
|
||||
IndexType newVertexIndex = static_cast<IndexType>( nodes.size() + createdVertexes.size() );
|
||||
|
||||
bool cv1VxTouchCv2[4] = { false, false, false, false };
|
||||
bool cv2VxTouchCv1[4] = { false, false, false, false };
|
||||
@@ -291,7 +287,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
int k;
|
||||
for ( k = 0; k < 4; ++k )
|
||||
{
|
||||
polygon->push_back( cv1CubeFaceIndices[k] );
|
||||
polygon.push_back( cv1CubeFaceIndices[k] );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -311,7 +307,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
nodes,
|
||||
wrapArrayConst( cv2CubeFaceIndices, 4 ),
|
||||
nodes[cv1CubeFaceIndices[cv1Idx]],
|
||||
&( cv1VxTouchCv2Edge[cv1Idx] ),
|
||||
cv1VxTouchCv2Edge[cv1Idx],
|
||||
tolerance );
|
||||
if ( cv1VxTouchCv2[cv1Idx] ) ++numCv1VxesOnCv2;
|
||||
}
|
||||
@@ -322,7 +318,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
nodes,
|
||||
wrapArrayConst( cv1CubeFaceIndices, 4 ),
|
||||
nodes[cv2CubeFaceIndices[cv1Idx]],
|
||||
&( cv2VxTouchCv1Edge[cv1Idx] ),
|
||||
cv2VxTouchCv1Edge[cv1Idx],
|
||||
tolerance );
|
||||
if ( cv2VxTouchCv1[cv1Idx] ) ++numCv2VxesOnCv1;
|
||||
}
|
||||
@@ -335,7 +331,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
int k;
|
||||
for ( k = 0; k < 4; ++k )
|
||||
{
|
||||
polygon->push_back( cv1CubeFaceIndices[k] );
|
||||
polygon.push_back( cv1CubeFaceIndices[k] );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -346,7 +342,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
int k;
|
||||
for ( k = 3; k >= 0; --k ) // Return opposite winding, to match winding of face 1
|
||||
{
|
||||
polygon->push_back( cv2CubeFaceIndices[k] );
|
||||
polygon.push_back( cv2CubeFaceIndices[k] );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -367,9 +363,9 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
if ( cv1VxTouchCv2[cv1Idx] && cv1VxTouchCv2Edge[cv1Idx] == -1 ) // Start of cv1 edge is touching inside the cv2
|
||||
// polygon (not on an cv2 edge)
|
||||
{
|
||||
if ( polygon->empty() || polygon->back() != cv1CubeFaceIndices[cv1Idx] )
|
||||
if ( polygon.empty() || polygon.back() != cv1CubeFaceIndices[cv1Idx] )
|
||||
{
|
||||
polygon->push_back( cv1CubeFaceIndices[cv1Idx] );
|
||||
polygon.push_back( cv1CubeFaceIndices[cv1Idx] );
|
||||
}
|
||||
|
||||
if ( cv1VxTouchCv2[nextCv1Idx] && cv1VxTouchCv2Edge[nextCv1Idx] == -1 )
|
||||
@@ -431,8 +427,8 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
cv2CubeFaceIndices[nextCv2Idx],
|
||||
&intersectionVxIndex,
|
||||
&intersectStatus,
|
||||
&fractionAlongEdge1,
|
||||
&fractionAlongEdge2 );
|
||||
fractionAlongEdge1,
|
||||
fractionAlongEdge2 );
|
||||
|
||||
if ( !found )
|
||||
{
|
||||
@@ -441,9 +437,9 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
nodes[cv1CubeFaceIndices[nextCv1Idx]],
|
||||
nodes[cv2CubeFaceIndices[cv2Idx]],
|
||||
nodes[cv2CubeFaceIndices[nextCv2Idx]],
|
||||
&intersection,
|
||||
&fractionAlongEdge1,
|
||||
&fractionAlongEdge2,
|
||||
intersection,
|
||||
fractionAlongEdge1,
|
||||
fractionAlongEdge2,
|
||||
tolerance );
|
||||
|
||||
switch ( intersectStatus )
|
||||
@@ -451,7 +447,7 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
case GeometryTools::LINES_CROSSES:
|
||||
{
|
||||
intersectionVxIndex = newVertexIndex;
|
||||
createdVertexes->push_back( intersection );
|
||||
createdVertexes.push_back( intersection );
|
||||
++newVertexIndex;
|
||||
}
|
||||
break;
|
||||
@@ -466,7 +462,13 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
else if ( fractionAlongEdge2 >= 1.0 )
|
||||
intersectionVxIndex = cv2CubeFaceIndices[nextCv2Idx];
|
||||
else
|
||||
CVF_ASSERT( false ); // Tolerance trouble
|
||||
{
|
||||
// Numerical precision issue at edge boundary
|
||||
// Create intersection vertex at the computed intersection point as fallback
|
||||
intersectionVxIndex = newVertexIndex;
|
||||
createdVertexes.push_back( intersection );
|
||||
++newVertexIndex;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GeometryTools::LINES_OVERLAP:
|
||||
@@ -480,7 +482,13 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
else if ( fractionAlongEdge2 >= 1.0 )
|
||||
intersectionVxIndex = cv2CubeFaceIndices[nextCv2Idx];
|
||||
else
|
||||
CVF_ASSERT( false ); // Tolerance trouble
|
||||
{
|
||||
// Numerical precision issue at edge boundary
|
||||
// Create intersection vertex at the computed intersection point as fallback
|
||||
intersectionVxIndex = newVertexIndex;
|
||||
createdVertexes.push_back( intersection );
|
||||
++newVertexIndex;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -504,7 +512,11 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
if ( ( intersectStatus == GeometryTools::LINES_CROSSES ) || ( intersectStatus == GeometryTools::LINES_TOUCH ) ||
|
||||
( intersectStatus == GeometryTools::LINES_OVERLAP ) )
|
||||
{
|
||||
CVF_ASSERT( intersectionVxIndex != cvf::UNDEFINED_UINT );
|
||||
if ( intersectionVxIndex == cvf::UNDEFINED_UINT )
|
||||
{
|
||||
// Invalid intersection - skip and continue processing
|
||||
continue;
|
||||
}
|
||||
|
||||
intersectionFractionsAlongEdge.push_back( fractionAlongEdge1 );
|
||||
intersectedCv2EdgeIdxs.push_back( cv2Idx );
|
||||
@@ -539,9 +551,9 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
typename std::map<double, IndexType>::iterator it;
|
||||
for ( it = sortingMap.begin(); it != sortingMap.end(); ++it )
|
||||
{
|
||||
if ( polygon->empty() || polygon->back() != it->second )
|
||||
if ( polygon.empty() || polygon.back() != it->second )
|
||||
{
|
||||
polygon->push_back( it->second );
|
||||
polygon.push_back( it->second );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,9 +582,9 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
// outside, so we
|
||||
// must stop
|
||||
{
|
||||
if ( polygon->empty() || polygon->back() != cv2CubeFaceIndices[cv2Idx] )
|
||||
if ( polygon.empty() || polygon.back() != cv2CubeFaceIndices[cv2Idx] )
|
||||
{
|
||||
polygon->push_back( cv2CubeFaceIndices[cv2Idx] );
|
||||
polygon.push_back( cv2CubeFaceIndices[cv2Idx] );
|
||||
}
|
||||
--cv2Idx;
|
||||
if ( cv2Idx < 0 ) cv2Idx = 3;
|
||||
@@ -581,22 +593,28 @@ bool GeometryTools::calculateOverlapPolygonOfTwoQuads( std::vector<IndexType>*
|
||||
}
|
||||
else
|
||||
{
|
||||
CVF_ASSERT( lastIntersection < intersectedCv2EdgeIdxs.size() );
|
||||
if ( lastIntersection >= intersectedCv2EdgeIdxs.size() )
|
||||
{
|
||||
// Array bounds exceeded - exit processing gracefully
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( polygon->size() > 2 )
|
||||
if ( polygon.size() > 2 )
|
||||
{
|
||||
if ( polygon->back() == polygon->front() ) polygon->pop_back();
|
||||
if ( polygon.back() == polygon.front() ) polygon.pop_back();
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
if ( polygon->size() < 3 )
|
||||
// Sanity checks with logging
|
||||
if ( polygon.size() < 3 )
|
||||
{
|
||||
// cvf::Trace::show(cvf::String("Degenerated connection polygon detected. (Less than 3 vertexes) Cv's probably
|
||||
// not in contact: %1 , %2").arg(m_ownerCvId).arg(m_neighborCvId));
|
||||
polygon->clear();
|
||||
caf::PdmLogging::warning( QString( "GeometryTools: Generated degenerate polygon with %1 vertices. "
|
||||
"Input faces may not overlap significantly. Tolerance=%2" )
|
||||
.arg( polygon.size() )
|
||||
.arg( tolerance ) );
|
||||
polygon.clear();
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -910,7 +928,7 @@ void EdgeIntersectStorage<IndexType>::canonizeAddress( IndexType& e1P1,
|
||||
|
||||
flipE1E2 = ( flipE1 ? e1P2 : e1P1 ) > ( flipE2 ? e2P2 : e2P1 );
|
||||
|
||||
static IndexType temp;
|
||||
IndexType temp;
|
||||
if ( flipE1 )
|
||||
{
|
||||
temp = e1P1;
|
||||
@@ -949,13 +967,13 @@ void EdgeIntersectStorage<IndexType>::addIntersection( IndexType
|
||||
double fractionAlongEdge1,
|
||||
double fractionAlongEdge2 )
|
||||
{
|
||||
static bool flipE1;
|
||||
static bool flipE2;
|
||||
static bool flipE1E2;
|
||||
bool flipE1;
|
||||
bool flipE2;
|
||||
bool flipE1E2;
|
||||
|
||||
canonizeAddress( e1P1, e1P2, e2P1, e2P2, flipE1, flipE2, flipE1E2 );
|
||||
|
||||
static IntersectData iData;
|
||||
IntersectData iData;
|
||||
|
||||
iData.fractionAlongEdge1 = flipE1 ? 1 - fractionAlongEdge1 : fractionAlongEdge1;
|
||||
iData.fractionAlongEdge2 = flipE2 ? 1 - fractionAlongEdge2 : fractionAlongEdge2;
|
||||
@@ -969,7 +987,9 @@ void EdgeIntersectStorage<IndexType>::addIntersection( IndexType
|
||||
}
|
||||
|
||||
iData.intersectionPointIndex = vxIndexIntersectionPoint;
|
||||
CVF_ASSERT( e1P1 < m_edgeIntsectMap.size() );
|
||||
if ( e1P1 >= m_edgeIntsectMap.size() || e1P2 >= m_edgeIntsectMap.size() || e2P1 >= m_edgeIntsectMap.size() ||
|
||||
e2P2 >= m_edgeIntsectMap.size() )
|
||||
return;
|
||||
m_edgeIntsectMap[e1P1][e1P2][e2P1][e2P2] = iData;
|
||||
}
|
||||
|
||||
@@ -983,27 +1003,26 @@ bool EdgeIntersectStorage<IndexType>::findIntersection( IndexType
|
||||
IndexType e2P2,
|
||||
IndexType* vxIndexIntersectionPoint,
|
||||
GeometryTools::IntersectionStatus* intersectionStatus,
|
||||
double* fractionAlongEdge1,
|
||||
double* fractionAlongEdge2 )
|
||||
double& fractionAlongEdge1,
|
||||
double& fractionAlongEdge2 )
|
||||
{
|
||||
static bool flipE1;
|
||||
static bool flipE2;
|
||||
static bool flipE1E2;
|
||||
bool flipE1;
|
||||
bool flipE2;
|
||||
bool flipE1E2;
|
||||
|
||||
canonizeAddress( e1P1, e1P2, e2P1, e2P2, flipE1, flipE2, flipE1E2 );
|
||||
|
||||
if ( !m_edgeIntsectMap[e1P1].size() ) return false;
|
||||
if ( e1P1 >= m_edgeIntsectMap.size() || e1P2 >= m_edgeIntsectMap.size() || e2P1 >= m_edgeIntsectMap.size() ||
|
||||
e2P2 >= m_edgeIntsectMap.size() || !m_edgeIntsectMap[e1P1].size() )
|
||||
return false;
|
||||
|
||||
typename std::map<IndexType, std::map<IndexType, std::map<IndexType, IntersectData>>>::iterator it;
|
||||
it = m_edgeIntsectMap[e1P1].find( e1P2 );
|
||||
auto it = m_edgeIntsectMap[e1P1].find( e1P2 );
|
||||
if ( it == m_edgeIntsectMap[e1P1].end() ) return false;
|
||||
|
||||
typename std::map<IndexType, std::map<IndexType, IntersectData>>::iterator it2;
|
||||
it2 = it->second.find( e2P1 );
|
||||
auto it2 = it->second.find( e2P1 );
|
||||
if ( it2 == it->second.end() ) return false;
|
||||
|
||||
typename std::map<IndexType, IntersectData>::iterator it3;
|
||||
it3 = it2->second.find( e2P2 );
|
||||
auto it3 = it2->second.find( e2P2 );
|
||||
if ( it3 == it2->second.end() ) return false;
|
||||
|
||||
*vxIndexIntersectionPoint = it3->second.intersectionPointIndex;
|
||||
@@ -1011,17 +1030,17 @@ bool EdgeIntersectStorage<IndexType>::findIntersection( IndexType
|
||||
|
||||
if ( flipE1E2 )
|
||||
{
|
||||
*fractionAlongEdge1 = it3->second.fractionAlongEdge2;
|
||||
*fractionAlongEdge2 = it3->second.fractionAlongEdge1;
|
||||
fractionAlongEdge1 = it3->second.fractionAlongEdge2;
|
||||
fractionAlongEdge2 = it3->second.fractionAlongEdge1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*fractionAlongEdge1 = it3->second.fractionAlongEdge1;
|
||||
*fractionAlongEdge2 = it3->second.fractionAlongEdge2;
|
||||
fractionAlongEdge1 = it3->second.fractionAlongEdge1;
|
||||
fractionAlongEdge2 = it3->second.fractionAlongEdge2;
|
||||
}
|
||||
|
||||
if ( flipE1 ) *fractionAlongEdge1 = 1 - *fractionAlongEdge1;
|
||||
if ( flipE2 ) *fractionAlongEdge2 = 1 - *fractionAlongEdge2;
|
||||
if ( flipE1 ) fractionAlongEdge1 = 1 - fractionAlongEdge1;
|
||||
if ( flipE2 ) fractionAlongEdge2 = 1 - fractionAlongEdge2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user