#3353 Improve error messages from arc based geometry calculators.

Color dogleg text red if the constaint is not satisfied
This commit is contained in:
Jacob Støren 2018-09-24 15:31:58 +02:00
parent e55fc4990d
commit 41b24a8de2
9 changed files with 169 additions and 60 deletions

View File

@ -27,16 +27,17 @@
/// + p2 /// + p2
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RiaArcCurveCalculator::RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::Vec3d p2) RiaArcCurveCalculator::RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::Vec3d p2)
: m_isCalculationOK(false) : m_radius(std::numeric_limits<double>::infinity())
, m_radius(std::numeric_limits<double>::infinity())
, m_arcCS(cvf::Mat4d::ZERO) , m_arcCS(cvf::Mat4d::ZERO)
, m_endAzi(0) , m_endAzi(0)
, m_endInc(0) , m_endInc(0)
, m_curveStatus(OK)
{ {
bool isOk = t1.normalize(); bool isOk = t1.normalize();
if (!isOk) if (!isOk)
{ {
// No tangent. Bail out // No tangent. Bail out
m_curveStatus = FAILED_INPUT_OVERLAP;
return; return;
} }
@ -45,6 +46,8 @@ RiaArcCurveCalculator::RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::
if (!isOk) if (!isOk)
{ {
// p1 and p2 in the same place. // p1 and p2 in the same place.
m_curveStatus = FAILED_INPUT_OVERLAP;
return; return;
} }
@ -52,9 +55,12 @@ RiaArcCurveCalculator::RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::
if (!isOk) if (!isOk)
{ {
// P2 is on the p1 + k*t1 line. We have a straight line // P2 is on the p1 + k*t1 line. We have a straight line
m_curveStatus = OK_STRAIGHT_LINE;
RiaOffshoreSphericalCoords endTangent(t1); RiaOffshoreSphericalCoords endTangent(t1);
m_endAzi = endTangent.azi(); m_endAzi = endTangent.azi();
m_endInc = endTangent.inc(); m_endInc = endTangent.inc();
m_radius = std::numeric_limits<double>::infinity();
return; return;
} }
@ -74,8 +80,6 @@ RiaArcCurveCalculator::RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::
RiaOffshoreSphericalCoords endTangent(t2); RiaOffshoreSphericalCoords endTangent(t2);
m_endAzi = endTangent.azi(); m_endAzi = endTangent.azi();
m_endInc = endTangent.inc(); m_endInc = endTangent.inc();
m_isCalculationOK = true;
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -34,25 +34,31 @@ public:
RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::Vec3d p2); RiaArcCurveCalculator(cvf::Vec3d p1, cvf::Vec3d t1, cvf::Vec3d p2);
RiaArcCurveCalculator(cvf::Vec3d p1, double azi1, double inc1, cvf::Vec3d p2); RiaArcCurveCalculator(cvf::Vec3d p1, double azi1, double inc1, cvf::Vec3d p2);
bool isOk() const { return m_isCalculationOK;} enum CurveStatus
{
OK,
OK_STRAIGHT_LINE,
FAILED_INPUT_OVERLAP
};
CurveStatus curveStatus() const { return m_curveStatus;}
cvf::Mat4d arcCS() const { return m_arcCS; } cvf::Mat4d arcCS() const { return m_arcCS; }
double radius() const { return m_radius;} double radius() const { return m_radius;}
cvf::Vec3d center() const { return m_arcCS.translation();} cvf::Vec3d center() const { return m_arcCS.translation();}
cvf::Vec3d normal() const { return cvf::Vec3d(m_arcCS.col(2));} cvf::Vec3d normal() const { return cvf::Vec3d(m_arcCS.col(2));}
double endAzimuth() const { return m_endAzi; } double endAzimuth() const { return m_endAzi; }
double endInclination() const { return m_endInc; } double endInclination() const { return m_endInc; }
private: private:
bool m_isCalculationOK; CurveStatus m_curveStatus;
double m_radius; double m_radius;
cvf::Mat4d m_arcCS; cvf::Mat4d m_arcCS;
double m_endAzi;
double m_endInc;
double m_endAzi;
double m_endInc;
}; };

View File

@ -26,10 +26,10 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
RiaJCurveCalculator::RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1, double r1, RiaJCurveCalculator::RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1, double r1,
cvf::Vec3d p2) cvf::Vec3d p2)
: m_isCalculationOK(false) : m_c1( cvf::Vec3d::UNDEFINED)
, m_c1( cvf::Vec3d::UNDEFINED)
, m_n1( cvf::Vec3d::UNDEFINED) , m_n1( cvf::Vec3d::UNDEFINED)
, m_radius( std::numeric_limits<double>::infinity())
, m_curveStatus(OK)
{ {
cvf::Vec3d t1 (RiaOffshoreSphericalCoords::unitVectorFromAziInc(azi1, inc1)); cvf::Vec3d t1 (RiaOffshoreSphericalCoords::unitVectorFromAziInc(azi1, inc1));
@ -40,9 +40,11 @@ RiaJCurveCalculator::RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1
if (!isOk) if (!isOk)
{ {
// p2 is on the p1 + t12 line. Degenerates to a line. // p2 is on the p1 + t12 line. Degenerates to a line.
m_curveStatus = OK_STRAIGHT_LINE;
m_firstArcEndpoint = p2; m_firstArcEndpoint = p2;
m_endAzi = azi1; m_endAzi = azi1;
m_endInc = inc1; m_endInc = inc1;
return; return;
} }
@ -53,15 +55,18 @@ RiaJCurveCalculator::RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1
if (p2c1Length < r1) if (p2c1Length < r1)
{ {
// Radius is too big. We can not get to point 2 using the requested radius. // Radius is too big. We can not get to point 2 using the requested radius.
m_isCalculationOK = false; m_curveStatus = FAILED_RADIUS_TOO_LARGE;
RiaArcCurveCalculator arc(p1, t1, p2); RiaArcCurveCalculator arc(p1, t1, p2);
if ( arc.isOk() ) if ( arc.curveStatus() == RiaArcCurveCalculator::OK
|| arc.curveStatus() == RiaArcCurveCalculator::OK_STRAIGHT_LINE )
{ {
m_c1 = arc.center(); m_c1 = arc.center();
m_n1 = arc.normal(); m_n1 = arc.normal();
m_firstArcEndpoint = p2; m_firstArcEndpoint = p2;
m_endAzi = arc.endAzimuth(); m_endAzi = arc.endAzimuth();
m_endInc = arc.endInclination(); m_endInc = arc.endInclination();
m_radius = arc.radius();
} }
else else
{ {
@ -83,7 +88,6 @@ RiaJCurveCalculator::RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1
m_firstArcEndpoint = p2 - d*tp11p2; m_firstArcEndpoint = p2 - d*tp11p2;
m_c1 = c1; m_c1 = c1;
m_n1 = nc1; m_n1 = nc1;
m_isCalculationOK = true;
RiaOffshoreSphericalCoords endTangent(tp11p2); RiaOffshoreSphericalCoords endTangent(tp11p2);
m_endAzi = endTangent.azi(); m_endAzi = endTangent.azi();

View File

@ -20,29 +20,50 @@
#include "cvfBase.h" #include "cvfBase.h"
#include "cvfVector3.h" #include "cvfVector3.h"
//--------------------------------------------------------------------------------------------------
/// + p1
/// t1 //
/// | r1 + C
/// \
/// + firstArcEndpoint
/// \
/// \
/// + p2
//--------------------------------------------------------------------------------------------------
class RiaJCurveCalculator class RiaJCurveCalculator
{ {
public: public:
RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1, double r1, RiaJCurveCalculator(cvf::Vec3d p1, double azi1, double inc1, double r1,
cvf::Vec3d p2); cvf::Vec3d p2);
enum CurveStatus
{
OK,
OK_STRAIGHT_LINE,
FAILED_INPUT_OVERLAP,
FAILED_RADIUS_TOO_LARGE
};
bool isOk() const { return m_isCalculationOK;} CurveStatus curveStatus() const { return m_curveStatus;}
cvf::Vec3d firstArcEndpoint() const { return m_firstArcEndpoint; }
cvf::Vec3d firstCenter() const { return m_c1; }
cvf::Vec3d firstNormal() const { return m_n1; }
double endAzimuth() const { return m_endAzi; } cvf::Vec3d firstArcEndpoint() const { return m_firstArcEndpoint; }
double endInclination() const { return m_endInc; }
private: double radius() const { return m_radius; }
bool m_isCalculationOK; cvf::Vec3d firstCenter() const { return m_c1; }
cvf::Vec3d firstNormal() const { return m_n1; }
double endAzimuth() const { return m_endAzi; }
double endInclination() const { return m_endInc; }
private:
CurveStatus m_curveStatus;
cvf::Vec3d m_firstArcEndpoint; cvf::Vec3d m_firstArcEndpoint;
cvf::Vec3d m_c1;
cvf::Vec3d m_n1; double m_radius;
double m_endAzi; cvf::Vec3d m_c1;
double m_endInc; cvf::Vec3d m_n1;
double m_endAzi;
double m_endInc;
}; };

View File

@ -83,6 +83,9 @@ void RiaPolyArcLineSampler::sampledPointsAndMDs(double sampleInterval,
void RiaPolyArcLineSampler::sampleSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent) void RiaPolyArcLineSampler::sampleSegment(cvf::Vec3d t1, cvf::Vec3d p1, cvf::Vec3d p2, cvf::Vec3d* endTangent)
{ {
cvf::Vec3d p1p2 = p2 - p1; cvf::Vec3d p1p2 = p2 - p1;
CVF_ASSERT (p1p2.lengthSquared() > 1e-20);
if (cvf::GeometryTools::getAngle(t1, p1p2) < 1e-5) if (cvf::GeometryTools::getAngle(t1, p1p2) < 1e-5)
{ {
sampleLine(p1, p2, endTangent); sampleLine(p1, p2, endTangent);

View File

@ -387,6 +387,9 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
RimWellPathTarget* target1 = activeWellPathTargets[tIdx]; RimWellPathTarget* target1 = activeWellPathTargets[tIdx];
RimWellPathTarget* target2 = activeWellPathTargets[tIdx+1]; RimWellPathTarget* target2 = activeWellPathTargets[tIdx+1];
target1->flagRadius2AsIncorrect(false, 0);
target2->flagRadius1AsIncorrect(false, 0);
if ( target1->targetType() == RimWellPathTarget::POINT_AND_TANGENT if ( target1->targetType() == RimWellPathTarget::POINT_AND_TANGENT
&& target2->targetType() == RimWellPathTarget::POINT_AND_TANGENT) && target2->targetType() == RimWellPathTarget::POINT_AND_TANGENT)
{ {
@ -399,7 +402,7 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
target2->inclination(), target2->inclination(),
target2->radius1()); target2->radius1());
if (!sCurveCalc.isOk()) if ( sCurveCalc.solveStatus() != RiaSCurveCalculator::CONVERGED )
{ {
double p1p2Length = (target2->targetPointXYZ() - target1->targetPointXYZ()).length(); double p1p2Length = (target2->targetPointXYZ() - target1->targetPointXYZ()).length();
sCurveCalc = RiaSCurveCalculator::fromTangentsAndLength(target1->targetPointXYZ(), sCurveCalc = RiaSCurveCalculator::fromTangentsAndLength(target1->targetPointXYZ(),
@ -412,6 +415,9 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
0.2*p1p2Length); 0.2*p1p2Length);
RiaLogging::warning("Using fall-back calculation of well path geometry between active target number: " + QString::number(tIdx+1) + " and " + QString::number(tIdx+2)); RiaLogging::warning("Using fall-back calculation of well path geometry between active target number: " + QString::number(tIdx+1) + " and " + QString::number(tIdx+2));
target1->flagRadius2AsIncorrect(true, sCurveCalc.firstRadius());
target2->flagRadius1AsIncorrect(true, sCurveCalc.secondRadius());
} }
endPoints.push_back( sCurveCalc.firstArcEndpoint() + referencePointXyz() ); endPoints.push_back( sCurveCalc.firstArcEndpoint() + referencePointXyz() );
@ -431,7 +437,7 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
target2->inclination(), target2->inclination(),
target2->radius1()); target2->radius1());
if (!sCurveCalc.isOk()) if ( sCurveCalc.solveStatus() != RiaSCurveCalculator::CONVERGED )
{ {
double p1p2Length = (target2->targetPointXYZ() - target1->targetPointXYZ()).length(); double p1p2Length = (target2->targetPointXYZ() - target1->targetPointXYZ()).length();
sCurveCalc = RiaSCurveCalculator::fromTangentsAndLength(target1->targetPointXYZ(), sCurveCalc = RiaSCurveCalculator::fromTangentsAndLength(target1->targetPointXYZ(),
@ -444,6 +450,9 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
0.2*p1p2Length); 0.2*p1p2Length);
RiaLogging::warning("Using fall-back calculation of well path geometry between active target number: " + QString::number(tIdx+1) + " and " + QString::number(tIdx+2)); RiaLogging::warning("Using fall-back calculation of well path geometry between active target number: " + QString::number(tIdx+1) + " and " + QString::number(tIdx+2));
target1->flagRadius2AsIncorrect(true, sCurveCalc.firstRadius());
target2->flagRadius1AsIncorrect(true, sCurveCalc.secondRadius());
} }
endPoints.push_back( sCurveCalc.firstArcEndpoint() + referencePointXyz() ); endPoints.push_back( sCurveCalc.firstArcEndpoint() + referencePointXyz() );
@ -458,10 +467,16 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
target1->inclination(), target1->inclination(),
target1->radius2(), target1->radius2(),
target2->targetPointXYZ()); target2->targetPointXYZ());
if ( jCurve.isOk() )
if ( jCurve.curveStatus() == RiaJCurveCalculator::OK )
{ {
endPoints.push_back(jCurve.firstArcEndpoint() + referencePointXyz()); endPoints.push_back(jCurve.firstArcEndpoint() + referencePointXyz());
} }
else if ( jCurve.curveStatus() == RiaJCurveCalculator::FAILED_RADIUS_TOO_LARGE )
{
target1->flagRadius2AsIncorrect(true, jCurve.radius());
}
endPoints.push_back( target2->targetPointXYZ() + referencePointXyz() ); endPoints.push_back( target2->targetPointXYZ() + referencePointXyz() );
prevSegmentEndAzi = jCurve.endAzimuth(); prevSegmentEndAzi = jCurve.endAzimuth();
prevSegmentEndInc = jCurve.endInclination(); prevSegmentEndInc = jCurve.endInclination();
@ -477,10 +492,16 @@ std::vector<cvf::Vec3d> RimWellPathGeometryDef::lineArcEndpoints() const
prevSegmentEndInc, prevSegmentEndInc,
target1->radius2(), target1->radius2(),
target2->targetPointXYZ()); target2->targetPointXYZ());
if ( jCurve.isOk() )
if ( jCurve.curveStatus() == RiaJCurveCalculator::OK )
{ {
endPoints.push_back(jCurve.firstArcEndpoint() + referencePointXyz()); endPoints.push_back(jCurve.firstArcEndpoint() + referencePointXyz());
} }
else if ( jCurve.curveStatus() == RiaJCurveCalculator::FAILED_RADIUS_TOO_LARGE )
{
target1->flagRadius2AsIncorrect(true, jCurve.radius());
}
endPoints.push_back( target2->targetPointXYZ() + referencePointXyz() ); endPoints.push_back( target2->targetPointXYZ() + referencePointXyz() );
prevSegmentEndAzi = jCurve.endAzimuth(); prevSegmentEndAzi = jCurve.endAzimuth();
prevSegmentEndInc = jCurve.endInclination(); prevSegmentEndInc = jCurve.endInclination();

View File

@ -157,10 +157,11 @@ double RimWellPathTarget::radius1() const
// Needs to be aware of unit to select correct DLS conversion // Needs to be aware of unit to select correct DLS conversion
// Degrees pr 100 ft // Degrees pr 100 ft
// Degrees pr 10m // Degrees pr 10m
// Degrees pr 30m
// Degrees pr 30m
return 30.0/cvf::Math::toRadians(m_dogleg1); return 30.0/cvf::Math::toRadians(m_dogleg1);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -169,11 +170,50 @@ double RimWellPathTarget::radius2() const
// Needs to be aware of unit to select correct DLS conversion // Needs to be aware of unit to select correct DLS conversion
// Degrees pr 100 ft // Degrees pr 100 ft
// Degrees pr 10m // Degrees pr 10m
// Degrees pr 30m
// Degrees pr 30m
return 30.0/cvf::Math::toRadians(m_dogleg2); return 30.0/cvf::Math::toRadians(m_dogleg2);
} }
double doglegFromRadius(double radius)
{
return cvf::Math::toDegrees(30.0/radius);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTarget::flagRadius1AsIncorrect(bool isIncorrect, double actualRadius)
{
if (isIncorrect)
{
m_dogleg1.uiCapability()->setUiContentTextColor(Qt::red);
m_dogleg1.uiCapability()->setUiToolTip("The dogleg constraint is not satisfied! Actual Dogleg: " + QString::number(doglegFromRadius(actualRadius)));
}
else
{
m_dogleg1.uiCapability()->setUiContentTextColor(QColor());
m_dogleg1.uiCapability()->setUiToolTip("");
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathTarget::flagRadius2AsIncorrect(bool isIncorrect, double actualRadius)
{
if (isIncorrect)
{
m_dogleg2.uiCapability()->setUiContentTextColor(Qt::red);
m_dogleg2.uiCapability()->setUiToolTip("The dogleg constraint is not satisfied! Actual Dogleg: " + QString::number(doglegFromRadius(actualRadius)));
}
else
{
m_dogleg2.uiCapability()->setUiContentTextColor(QColor());
m_dogleg2.uiCapability()->setUiToolTip("");
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -46,6 +46,8 @@ public:
cvf::Vec3d tangent() const; cvf::Vec3d tangent() const;
double radius1() const; double radius1() const;
double radius2() const; double radius2() const;
void flagRadius1AsIncorrect(bool isIncorrect, double actualRadius);
void flagRadius2AsIncorrect(bool isIncorrect, double actualRadius);
private: private:
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override; virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;

View File

@ -804,23 +804,31 @@ TEST(RiaSCurveCalculator, ControlPointCurve)
TEST(RiaJCurveCalculator, Basic) TEST(RiaJCurveCalculator, Basic)
{ {
RiaJCurveCalculator calc({ 0,0,0 }, 0, M_PI/2, 100, { 0,100,-1000 }); {
RiaJCurveCalculator calc({ 0,0,0 }, 0, M_PI/2, 100, { 0,100,-1000 });
EXPECT_TRUE(calc.isOk() ); EXPECT_TRUE(calc.curveStatus() == RiaJCurveCalculator::OK);
cvf::Vec3d p11 = calc.firstArcEndpoint();
EXPECT_NEAR( 0, p11.x(), 1e-5);
EXPECT_NEAR( 100, p11.y(), 1e-5);
EXPECT_NEAR( -100, p11.z(), 1e-5);
cvf::Vec3d n = calc.firstNormal(); cvf::Vec3d p11 = calc.firstArcEndpoint();
EXPECT_NEAR(-1, n.x(), 1e-5); EXPECT_NEAR(0, p11.x(), 1e-5);
EXPECT_NEAR( 0, n.y(), 1e-5); EXPECT_NEAR(100, p11.y(), 1e-5);
EXPECT_NEAR( 0, n.z(), 1e-5); EXPECT_NEAR(-100, p11.z(), 1e-5);
cvf::Vec3d n = calc.firstNormal();
EXPECT_NEAR(-1, n.x(), 1e-5);
EXPECT_NEAR(0, n.y(), 1e-5);
EXPECT_NEAR(0, n.z(), 1e-5);
cvf::Vec3d c = calc.firstCenter();
EXPECT_NEAR(0, c.x(), 1e-5);
EXPECT_NEAR(0, c.y(), 1e-5);
EXPECT_NEAR(-100, c.z(), 1e-5);
}
{
RiaJCurveCalculator calc({ 0,0,0 }, 0, 0, 100, { 0, 0,-1000 });
EXPECT_TRUE(calc.curveStatus() == RiaJCurveCalculator::OK_STRAIGHT_LINE);
}
cvf::Vec3d c = calc.firstCenter();
EXPECT_NEAR( 0, c.x(), 1e-5);
EXPECT_NEAR( 0, c.y(), 1e-5);
EXPECT_NEAR(-100, c.z(), 1e-5);
} }