#3695 Well path creation : Crash when creating a vertical well

Caused by two identical reference points next to each other
This commit is contained in:
Magne Sjaastad
2018-11-16 08:43:19 +01:00
parent e2cc7fb423
commit 9cd695278e
3 changed files with 137 additions and 74 deletions

View File

@@ -17,16 +17,15 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
#include "RiaPolyArcLineSampler.h" #include "RiaPolyArcLineSampler.h"
#include "cvfGeometryTools.h"
#include "cvfMatrix4.h"
#include "RiaArcCurveCalculator.h" #include "RiaArcCurveCalculator.h"
#include "cvfGeometryTools.h"
#include "cvfMatrix4.h"
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RiaPolyArcLineSampler::RiaPolyArcLineSampler(const cvf::Vec3d& startTangent, RiaPolyArcLineSampler::RiaPolyArcLineSampler(const cvf::Vec3d& startTangent, const std::vector<cvf::Vec3d>& lineArcEndPoints)
const std::vector<cvf::Vec3d>& lineArcEndPoints)
: m_startTangent(startTangent) : m_startTangent(startTangent)
, m_lineArcEndPoints(lineArcEndPoints) , m_lineArcEndPoints(lineArcEndPoints)
, m_samplingsInterval(0.15) , m_samplingsInterval(0.15)
@@ -35,17 +34,16 @@ RiaPolyArcLineSampler::RiaPolyArcLineSampler(const cvf::Vec3d& startTangent,
, m_points(nullptr) , m_points(nullptr)
, m_meshDs(nullptr) , m_meshDs(nullptr)
{ {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RiaPolyArcLineSampler::sampledPointsAndMDs(double sampleInterval, void RiaPolyArcLineSampler::sampledPointsAndMDs(double sampleInterval,
bool isResamplingLines, bool isResamplingLines,
std::vector<cvf::Vec3d>* points, std::vector<cvf::Vec3d>* points,
std::vector<double>* mds) std::vector<double>* mds)
{ {
CVF_ASSERT(sampleInterval > 0.0); CVF_ASSERT(sampleInterval > 0.0);
@@ -56,26 +54,28 @@ void RiaPolyArcLineSampler::sampledPointsAndMDs(double sampleInterval,
points->clear(); points->clear();
mds->clear(); mds->clear();
if (m_lineArcEndPoints.size() < 2) return ; std::vector<cvf::Vec3d> pointsNoDuplicates = RiaPolyArcLineSampler::pointsWithoutDuplicates(m_lineArcEndPoints);
m_points = points; if (pointsNoDuplicates.size() < 2) return;
m_meshDs = mds;
m_points = points;
m_meshDs = mds;
m_totalMD = startMD; m_totalMD = startMD;
cvf::Vec3d p1 = m_lineArcEndPoints[0]; cvf::Vec3d p1 = pointsNoDuplicates[0];
cvf::Vec3d p2 = m_lineArcEndPoints[1]; cvf::Vec3d p2 = pointsNoDuplicates[1];
m_points->push_back(p1); m_points->push_back(p1);
m_meshDs->push_back(m_totalMD); m_meshDs->push_back(m_totalMD);
cvf::Vec3d t2 = m_startTangent; cvf::Vec3d t2 = m_startTangent;
for (size_t pIdx = 0; pIdx < m_lineArcEndPoints.size() - 1 ; ++pIdx) for (size_t pIdx = 0; pIdx < pointsNoDuplicates.size() - 1; ++pIdx)
{ {
sampleSegment(t2, m_lineArcEndPoints[pIdx], m_lineArcEndPoints[pIdx + 1] , &t2); sampleSegment(t2, pointsNoDuplicates[pIdx], pointsNoDuplicates[pIdx + 1], &t2);
} }
return ; return;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -85,7 +85,7 @@ void RiaPolyArcLineSampler::sampleSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec
{ {
cvf::Vec3d p1p2 = p2 - p1; cvf::Vec3d p1p2 = p2 - p1;
CVF_ASSERT (p1p2.lengthSquared() > 1e-20); CVF_ASSERT(p1p2.lengthSquared() > 1e-20);
if (cvf::GeometryTools::getAngle(t1, p1p2) < 1e-5) if (cvf::GeometryTools::getAngle(t1, p1p2) < 1e-5)
{ {
@@ -100,16 +100,37 @@ void RiaPolyArcLineSampler::sampleSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RiaPolyArcLineSampler::sampleLine(cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent ) std::vector<cvf::Vec3d> RiaPolyArcLineSampler::pointsWithoutDuplicates(const std::vector<cvf::Vec3d>& points)
{
std::vector<cvf::Vec3d> outputPoints;
cvf::Vec3d previousPoint = cvf::Vec3d::UNDEFINED;
const double threshold = 1e-6;
for (const auto& p : points)
{
if (previousPoint.isUndefined() || ((previousPoint - p).lengthSquared()) > threshold)
{
outputPoints.push_back(p);
previousPoint = p;
}
}
return outputPoints;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaPolyArcLineSampler::sampleLine(cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent)
{ {
cvf::Vec3d p1p2 = p2 - p1; cvf::Vec3d p1p2 = p2 - p1;
double p1p2Length = p1p2.length(); double p1p2Length = p1p2.length();
if ( p1p2Length > m_samplingsInterval && m_isResamplingLines ) if (p1p2Length > m_samplingsInterval && m_isResamplingLines)
{ {
cvf::Vec3d tp1p2 = p1p2 / p1p2Length; cvf::Vec3d tp1p2 = p1p2 / p1p2Length;
double mdInc = m_samplingsInterval; double mdInc = m_samplingsInterval;
while ( mdInc < p1p2Length ) while (mdInc < p1p2Length)
{ {
cvf::Vec3d ps = p1 + mdInc * tp1p2; cvf::Vec3d ps = p1 + mdInc * tp1p2;
m_points->push_back(ps); m_points->push_back(ps);
@@ -132,10 +153,10 @@ void RiaPolyArcLineSampler::sampleArc(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p
// Find arc CS // Find arc CS
RiaArcCurveCalculator CS_rad(p1, t1, p2); RiaArcCurveCalculator CS_rad(p1, t1, p2);
double radius = CS_rad.radius(); double radius = CS_rad.radius();
cvf::Mat4d arcCS = CS_rad.arcCS(); cvf::Mat4d arcCS = CS_rad.arcCS();
double angleInc = m_samplingsInterval/ radius; double angleInc = m_samplingsInterval / radius;
cvf::Vec3d C = CS_rad.center(); cvf::Vec3d C = CS_rad.center();
cvf::Vec3d N = CS_rad.normal(); cvf::Vec3d N = CS_rad.normal();
@@ -144,12 +165,12 @@ void RiaPolyArcLineSampler::sampleArc(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p
// Rotate vector an increment, and transform to arc CS // Rotate vector an increment, and transform to arc CS
double arcAngle = cvf::GeometryTools::getAngle(N, p1 - C, p2 - C); double arcAngle = cvf::GeometryTools::getAngle(N, p1 - C, p2 - C);
if (arcAngle/angleInc > 5000) if (arcAngle / angleInc > 5000)
{ {
angleInc = arcAngle/5000; angleInc = arcAngle / 5000;
} }
for ( double angle = angleInc; angle < arcAngle; angle += angleInc ) for (double angle = angleInc; angle < arcAngle; angle += angleInc)
{ {
cvf::Vec3d C_to_incP = cvf::Vec3d::X_AXIS; cvf::Vec3d C_to_incP = cvf::Vec3d::X_AXIS;
C_to_incP *= radius; C_to_incP *= radius;
@@ -159,9 +180,8 @@ void RiaPolyArcLineSampler::sampleArc(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p
m_points->push_back(C_to_incP); m_points->push_back(C_to_incP);
m_meshDs->push_back(m_totalMD + angle * radius); m_meshDs->push_back(m_totalMD + angle * radius);
} }
m_totalMD += arcAngle*radius; m_totalMD += arcAngle * radius;
m_points->push_back(p2); m_points->push_back(p2);
m_meshDs->push_back(m_totalMD); m_meshDs->push_back(m_totalMD);

View File

@@ -25,14 +25,14 @@
class RiaPolyArcLineSampler class RiaPolyArcLineSampler
{ {
public: public:
RiaPolyArcLineSampler(const cvf::Vec3d& startTangent, RiaPolyArcLineSampler(const cvf::Vec3d& startTangent, const std::vector<cvf::Vec3d>& lineArcEndPoints);
const std::vector<cvf::Vec3d>& lineArcEndPoints);
void sampledPointsAndMDs(double sampleInterval,
bool isResamplingLines,
std::vector<cvf::Vec3d>* points,
std::vector<double>* mds);
void sampledPointsAndMDs(double sampleInterval, static std::vector<cvf::Vec3d> pointsWithoutDuplicates(const std::vector<cvf::Vec3d>& points);
bool isResamplingLines,
std::vector<cvf::Vec3d>* points,
std::vector<double>* mds);
private: private:
void sampleLine(cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent); void sampleLine(cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent);
@@ -42,11 +42,10 @@ private:
std::vector<cvf::Vec3d>* m_points; // Internal temporary pointers to collections beeing filled. std::vector<cvf::Vec3d>* m_points; // Internal temporary pointers to collections beeing filled.
std::vector<double>* m_meshDs; std::vector<double>* m_meshDs;
double m_samplingsInterval; double m_samplingsInterval;
bool m_isResamplingLines; bool m_isResamplingLines;
double m_totalMD; double m_totalMD;
cvf::Vec3d m_startTangent; cvf::Vec3d m_startTangent;
std::vector<cvf::Vec3d> m_lineArcEndPoints; std::vector<cvf::Vec3d> m_lineArcEndPoints;
}; };

View File

@@ -6,28 +6,72 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
TEST(RiaPolyArcLineSampler, Basic) TEST(RiaPolyArcLineSampler, Basic)
{ {
std::vector<cvf::Vec3d> points { {0,0,0}, {0,0,-10}, {0,10,-20},{0,20,-20}, {0,30, -30} }; std::vector<cvf::Vec3d> points{{0, 0, 0}, {0, 0, -10}, {0, 10, -20}, {0, 20, -20}, {0, 30, -30}};
RiaPolyArcLineSampler sampler({0,0,-1}, points); RiaPolyArcLineSampler sampler({0, 0, -1}, points);
std::vector<cvf::Vec3d> sampledPoints; std::vector<cvf::Vec3d> sampledPoints;
std::vector<double> mds; std::vector<double> mds;
sampler.sampledPointsAndMDs(2, true, &sampledPoints, &mds); sampler.sampledPointsAndMDs(2, true, &sampledPoints, &mds);
#if 0 #if 0
for (size_t pIdx = 0; pIdx < sampledPoints.size(); ++pIdx) for (size_t pIdx = 0; pIdx < sampledPoints.size(); ++pIdx)
{ {
std::cout << sampledPoints[pIdx].x() << " " std::cout << sampledPoints[pIdx].x() << " "
<< sampledPoints[pIdx].y() << " " << sampledPoints[pIdx].y() << " "
<< sampledPoints[pIdx].z() << " md: " << mds[pIdx] << std::endl; << sampledPoints[pIdx].z() << " md: " << mds[pIdx] << std::endl;
} }
#endif #endif
EXPECT_EQ(27, (int)sampledPoints.size()); EXPECT_EQ(27, (int)sampledPoints.size());
EXPECT_NEAR(51.4159, mds.back(), 1e-4); EXPECT_NEAR(51.4159, mds.back(), 1e-4);
EXPECT_NEAR(points[2].y(), sampledPoints[12].y(), 2); EXPECT_NEAR(points[2].y(), sampledPoints[12].y(), 2);
EXPECT_NEAR(points[2].z(), sampledPoints[12].z(), 2); EXPECT_NEAR(points[2].z(), sampledPoints[12].z(), 2);
EXPECT_NEAR(points[4].y(), sampledPoints[25].y(), 2); EXPECT_NEAR(points[4].y(), sampledPoints[25].y(), 2);
EXPECT_NEAR(points[4].z(), sampledPoints[25].z(), 2); EXPECT_NEAR(points[4].z(), sampledPoints[25].z(), 2);
}
//--------------------------------------------------------------------------------------------------
TEST(RiaPolyArcLineSampler, TestInvalidInput)
{
{
// Two identical points after each other
std::vector<cvf::Vec3d> points{{0, 0, -20}, {0, 0, -20}};
RiaPolyArcLineSampler sampler({0, 0, -1}, points);
std::vector<cvf::Vec3d> sampledPoints;
std::vector<double> mds;
sampler.sampledPointsAndMDs(2, true, &sampledPoints, &mds);
EXPECT_EQ(0, (int)sampledPoints.size());
}
{
std::vector<cvf::Vec3d> points;
RiaPolyArcLineSampler sampler({0, 0, -1}, points);
std::vector<cvf::Vec3d> sampledPoints;
std::vector<double> mds;
sampler.sampledPointsAndMDs(2, true, &sampledPoints, &mds);
EXPECT_EQ(0, (int)sampledPoints.size());
}
{
std::vector<cvf::Vec3d> points{{0, 0, 0}};
RiaPolyArcLineSampler sampler({0, 0, -1}, points);
std::vector<cvf::Vec3d> sampledPoints;
std::vector<double> mds;
sampler.sampledPointsAndMDs(2, true, &sampledPoints, &mds);
EXPECT_EQ(0, (int)sampledPoints.size());
}
} }