3D Well log curves: Use the new generalized interpolation for normals

* Don't have to perform the normal generation again for grid points.
This commit is contained in:
Gaute Lindkvist 2018-04-13 14:36:37 +02:00
parent 1bb1b3004e
commit b48adbbaa9
4 changed files with 41 additions and 91 deletions

View File

@ -113,15 +113,19 @@ void Riv3dWellLogCurveGeometryGenerator::createCurveVerticesAndIndices(const std
maxZClipHeight = wellPathClipBoundingBox.max().z() + wellPathCollection->wellPathClipZDistance; maxZClipHeight = wellPathClipBoundingBox.max().z() + wellPathCollection->wellPathClipZDistance;
} }
std::vector<cvf::Vec3d> interpolatedWellPathPoints; std::vector<cvf::Vec3d> wellPathNormals = RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle);
std::vector<cvf::Vec3d> interpolatedWellPathPoints;
std::vector<cvf::Vec3d> interpolatedNormals;
// Iterate from bottom of well path and up to be able to stop at given Z max clipping height // Iterate from bottom of well path and up to be able to stop at given Z max clipping height
for (auto md = resultMds.rbegin(); md != resultMds.rend(); md++) for (auto md = resultMds.rbegin(); md != resultMds.rend(); md++)
{ {
cvf::Vec3d point = wellPathGeometry()->interpolatedPointAlongWellPath(*md); cvf::Vec3d point = wellPathGeometry()->interpolatedPointAlongWellPath(*md);
cvf::Vec3d normal = wellPathGeometry()->interpolatedVectorAlongWellPath(wellPathNormals, *md);
if (point.z() > maxZClipHeight) break; if (point.z() > maxZClipHeight) break;
interpolatedWellPathPoints.push_back(point); interpolatedWellPathPoints.push_back(point);
interpolatedNormals.push_back(normal.getNormalized());
} }
if (interpolatedWellPathPoints.empty()) return; if (interpolatedWellPathPoints.empty()) return;
@ -132,12 +136,6 @@ void Riv3dWellLogCurveGeometryGenerator::createCurveVerticesAndIndices(const std
std::vector<double> resultValuesForInterpolatedPoints(resultValues.end() - interpolatedWellPathPoints.size(), std::vector<double> resultValuesForInterpolatedPoints(resultValues.end() - interpolatedWellPathPoints.size(),
resultValues.end()); resultValues.end());
std::vector<cvf::Vec3d> pairsOfWellPathPoints;
RigWellPathGeometryTools::calculatePairsOfClosestSamplingPointsAlongWellPath(wellPathGeometry(), interpolatedWellPathPoints, &pairsOfWellPathPoints);
std::vector<cvf::Vec3d> pointNormals = RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle, pairsOfWellPathPoints, RigWellPathGeometryTools::LINE_SEGMENTS);
if (interpolatedWellPathPoints.size() != pointNormals.size()) return;
double maxResult = -HUGE_VAL; double maxResult = -HUGE_VAL;
double minResult = HUGE_VAL; double minResult = HUGE_VAL;
@ -153,7 +151,7 @@ void Riv3dWellLogCurveGeometryGenerator::createCurveVerticesAndIndices(const std
double plotRangeToResultRangeFactor = planeWidth / (maxResult - minResult); double plotRangeToResultRangeFactor = planeWidth / (maxResult - minResult);
for (size_t i = 0; i < pointNormals.size(); i++) for (size_t i = 0; i < interpolatedNormals.size(); i++)
{ {
double scaledResult = 0; double scaledResult = 0;
@ -164,7 +162,7 @@ void Riv3dWellLogCurveGeometryGenerator::createCurveVerticesAndIndices(const std
} }
(*vertices)[i] = cvf::Vec3f( (*vertices)[i] = cvf::Vec3f(
displayCoordTransform->transformToDisplayCoord(interpolatedWellPathPoints[i] + scaledResult * pointNormals[i])); displayCoordTransform->transformToDisplayCoord(interpolatedWellPathPoints[i] + scaledResult * interpolatedNormals[i]));
} }
std::vector<std::pair<size_t, size_t>> valuesIntervals = std::vector<std::pair<size_t, size_t>> valuesIntervals =

View File

@ -92,42 +92,17 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform*
std::map< DrawableId, cvf::ref<cvf::DrawableGeo> > drawables; std::map< DrawableId, cvf::ref<cvf::DrawableGeo> > drawables;
std::vector<cvf::Vec3d> gridPoints;
size_t newStartIndex = originalWellPathSize - wellPathPoints.size();
double firstMd = wellPathGeometry()->m_measuredDepths.at(newStartIndex);
double lastMd = wellPathGeometry()->m_measuredDepths.back();
double md = lastMd;
while (md >= firstMd)
{
cvf::Vec3d point = wellPathGeometry()->interpolatedPointAlongWellPath(md);
gridPoints.push_back(point);
md -= gridIntervalSize;
}
std::vector<cvf::Vec3d> pointNormals;
std::vector<cvf::Vec3d> closestPoints;
RigWellPathGeometryTools::calculatePairsOfClosestSamplingPointsAlongWellPath(wellPathGeometry(), gridPoints, &closestPoints);
pointNormals = RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle, closestPoints, RigWellPathGeometryTools::LINE_SEGMENTS);
if (pointNormals.size() != gridPoints.size())
{
return std::map< DrawableId, cvf::ref<cvf::DrawableGeo> >();
}
// calculateLineSegmentNormals returns normals for the whole well path. Erase the part which is clipped off // calculateLineSegmentNormals returns normals for the whole well path. Erase the part which is clipped off
std::vector<cvf::Vec3d> wellPathSegmentNormals = std::vector<cvf::Vec3d> wellPathSegmentNormals =
RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle, wellPathGeometry()->m_wellPathPoints, RigWellPathGeometryTools::POLYLINE); RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle);
wellPathSegmentNormals.erase(wellPathSegmentNormals.begin(), wellPathSegmentNormals.end() - wellPathPoints.size()); wellPathSegmentNormals.erase(wellPathSegmentNormals.begin(), wellPathSegmentNormals.end() - wellPathPoints.size());
{ {
std::vector<cvf::Vec3f> vertices; std::vector<cvf::Vec3f> vertices;
vertices.reserve(gridPoints.size()); vertices.reserve(wellPathPoints.size());
std::vector<cvf::uint> indices; std::vector<cvf::uint> indices;
indices.reserve(gridPoints.size()); indices.reserve(wellPathPoints.size());
cvf::uint indexCounter = 0; cvf::uint indexCounter = 0;
// Line along and close to well // Line along and close to well
for (size_t i = 0; i < wellPathPoints.size(); i++) for (size_t i = 0; i < wellPathPoints.size(); i++)
@ -162,20 +137,37 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform*
drawables[GridBorder] = gridBorderDrawable; drawables[GridBorder] = gridBorderDrawable;
} }
{ {
std::vector<cvf::Vec3d> interpolatedGridPoints;
std::vector<cvf::Vec3d> interpolatedGridNormals;
size_t newStartIndex = originalWellPathSize - wellPathPoints.size();
double firstMd = wellPathGeometry()->m_measuredDepths.at(newStartIndex);
double lastMd = wellPathGeometry()->m_measuredDepths.back();
double md = lastMd;
while (md >= firstMd)
{
cvf::Vec3d point = wellPathGeometry()->interpolatedPointAlongWellPath(md);
cvf::Vec3d normal = wellPathGeometry()->interpolatedVectorAlongWellPath(wellPathSegmentNormals, md);
interpolatedGridPoints.push_back(point);
interpolatedGridNormals.push_back(normal.getNormalized());
md -= gridIntervalSize;
}
std::vector<cvf::Vec3f> vertices; std::vector<cvf::Vec3f> vertices;
vertices.reserve(gridPoints.size()); vertices.reserve(interpolatedGridPoints.size());
std::vector<cvf::uint> indices; std::vector<cvf::uint> indices;
indices.reserve(gridPoints.size()); indices.reserve(interpolatedGridPoints.size());
cvf::uint indexCounter = 0; cvf::uint indexCounter = 0;
// Normal lines. Start from one to avoid drawing at surface edge. // Normal lines. Start from one to avoid drawing at surface edge.
for (size_t i = 1; i < pointNormals.size(); i++) for (size_t i = 1; i < interpolatedGridNormals.size(); i++)
{ {
vertices.push_back(cvf::Vec3f( vertices.push_back(cvf::Vec3f(
displayCoordTransform->transformToDisplayCoord(gridPoints[i] + pointNormals[i] * planeOffsetFromWellPathCenter))); displayCoordTransform->transformToDisplayCoord(interpolatedGridPoints[i] + interpolatedGridNormals[i] * planeOffsetFromWellPathCenter)));
vertices.push_back(cvf::Vec3f(displayCoordTransform->transformToDisplayCoord( vertices.push_back(cvf::Vec3f(displayCoordTransform->transformToDisplayCoord(
gridPoints[i] + pointNormals[i] * (planeOffsetFromWellPathCenter + planeWidth)))); interpolatedGridPoints[i] + interpolatedGridNormals[i] * (planeOffsetFromWellPathCenter + planeWidth))));
indices.push_back(indexCounter++); indices.push_back(indexCounter++);
indices.push_back(indexCounter++); indices.push_back(indexCounter++);

View File

@ -30,37 +30,27 @@
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
std::vector<cvf::Vec3d> RigWellPathGeometryTools::calculateLineSegmentNormals(const RigWellPath* wellPathGeometry, std::vector<cvf::Vec3d> RigWellPathGeometryTools::calculateLineSegmentNormals(const RigWellPath* wellPathGeometry,
double planeAngle, double planeAngle)
const std::vector<cvf::Vec3d>& vertices,
VertexOrganization organization)
{ {
std::vector<cvf::Vec3d> pointNormals; std::vector<cvf::Vec3d> pointNormals;
if (!wellPathGeometry) return pointNormals; if (!wellPathGeometry) return pointNormals;
const std::vector<cvf::Vec3d>& vertices = wellPathGeometry->wellPathPoints();
if (vertices.empty()) return pointNormals; if (vertices.empty()) return pointNormals;
pointNormals.reserve(vertices.size());
cvf::Vec3d up(0, 0, 1); cvf::Vec3d up(0, 0, 1);
// Project onto normal plane
cvf::Vec3d dominantDirection = estimateDominantDirectionInXYPlane(wellPathGeometry); cvf::Vec3d dominantDirection = estimateDominantDirectionInXYPlane(wellPathGeometry);
const cvf::Vec3d projectionPlaneNormal = (up ^ dominantDirection).getNormalized(); const cvf::Vec3d projectionPlaneNormal = (up ^ dominantDirection).getNormalized();
CVF_ASSERT(projectionPlaneNormal * dominantDirection <= std::numeric_limits<double>::epsilon()); CVF_ASSERT(projectionPlaneNormal * dominantDirection <= std::numeric_limits<double>::epsilon());
size_t intervalSize;
if (organization == LINE_SEGMENTS)
{
pointNormals.reserve(vertices.size() / 2);
intervalSize = 2;
}
else // organization == POLYLINE
{
pointNormals.reserve(vertices.size());
intervalSize = 1;
}
cvf::Vec3d lastNormal; cvf::Vec3d lastNormal;
for (size_t i = 0; i < vertices.size() - 1; i += intervalSize) for (size_t i = 0; i < vertices.size() - 1; ++i)
{ {
cvf::Vec3d p1 = vertices[i]; cvf::Vec3d p1 = vertices[i];
cvf::Vec3d p2 = vertices[i + 1]; cvf::Vec3d p2 = vertices[i + 1];
@ -77,35 +67,11 @@ std::vector<cvf::Vec3d> RigWellPathGeometryTools::calculateLineSegmentNormals(co
lastNormal = normal; lastNormal = normal;
} }
if (organization == POLYLINE) pointNormals.push_back(lastNormal);
{
pointNormals.push_back(lastNormal);
}
return interpolateUndefinedNormals(up, pointNormals, vertices); return interpolateUndefinedNormals(up, pointNormals, vertices);
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigWellPathGeometryTools::calculatePairsOfClosestSamplingPointsAlongWellPath(const RigWellPath* wellPathGeometry,
const std::vector<cvf::Vec3d>& points,
std::vector<cvf::Vec3d>* closestWellPathPoints)
{
CVF_ASSERT(closestWellPathPoints != nullptr);
for (const cvf::Vec3d point : points)
{
cvf::Vec3d p1 = cvf::Vec3d::UNDEFINED;
cvf::Vec3d p2 = cvf::Vec3d::UNDEFINED;
wellPathGeometry->twoClosestPoints(point, &p1, &p2);
if (p1.isUndefined() || p2.isUndefined()) continue;
closestWellPathPoints->push_back(p1);
closestWellPathPoints->push_back(p2);
}
}
std::vector<cvf::Vec3d> RigWellPathGeometryTools::interpolateUndefinedNormals(const cvf::Vec3d& planeNormal, std::vector<cvf::Vec3d> RigWellPathGeometryTools::interpolateUndefinedNormals(const cvf::Vec3d& planeNormal,
const std::vector<cvf::Vec3d>& normals, const std::vector<cvf::Vec3d>& normals,
const std::vector<cvf::Vec3d>& vertices) const std::vector<cvf::Vec3d>& vertices)

View File

@ -39,13 +39,7 @@ public:
public: public:
static std::vector<cvf::Vec3d> calculateLineSegmentNormals(const RigWellPath* wellPathGeometry, static std::vector<cvf::Vec3d> calculateLineSegmentNormals(const RigWellPath* wellPathGeometry,
double angle, double angle);
const std::vector<cvf::Vec3d>& vertices,
VertexOrganization organization);
static void calculatePairsOfClosestSamplingPointsAlongWellPath(const RigWellPath* wellPathGeometry,
const std::vector<cvf::Vec3d>& points,
std::vector<cvf::Vec3d>* closestWellPathPoints);
private: private:
static std::vector<cvf::Vec3d> interpolateUndefinedNormals(const cvf::Vec3d& planeNormal, static std::vector<cvf::Vec3d> interpolateUndefinedNormals(const cvf::Vec3d& planeNormal,
const std::vector<cvf::Vec3d>& normals, const std::vector<cvf::Vec3d>& normals,