Commit e1eddfef authored by bonnell's avatar bonnell
Browse files

Fix bugs with node-pick. Resolves #2816

git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@31191 18c085ea-50e0-402c-830e-de6fd14e8384
parent 24b25b69
......@@ -63,7 +63,7 @@
// Method: avtLocateNodeQuery constructor
//
// Programmer: Kathleen Bonnell
// Creation: May 18, 2004
// Creation: May 18, 2004
//
// Modifications:
//
......@@ -81,8 +81,8 @@ avtLocateNodeQuery::avtLocateNodeQuery()
// Defines the destructor. Note: this should not be inlined in the header
// because it causes problems for certain compilers.
//
// Programmer: Kathleen Bonnell
// Creation: May 18, 2004
// Programmer: Kathleen Bonnell
// Creation: May 18, 2004
//
// ****************************************************************************
......@@ -98,38 +98,43 @@ avtLocateNodeQuery::~avtLocateNodeQuery()
// Purpose:
// Processes a single domain.
//
// Programmer: Kathleen Bonnell
// Creation: May 18, 2004
// Programmer: Kathleen Bonnell
// Creation: May 18, 2004
//
// Modifications:
// Kathleen Bonnell, Thu Jun 17 14:05:22 PDT 2004
// Handle finding the Node for mat-selected plots differently, as they
// may have created new points in the mesh.
//
// Kathleen Bonnell, Thu Jul 29 08:34:18 PDT 2004
// Make sure that node found for mat-slected plots is actually used!
//
// Kathleen Bonnell, Thu Jul 29 08:34:18 PDT 2004
// Make sure that node found for mat-slected plots is actually used!
//
// Kathleen Bonnell, Wed Oct 6 10:43:10 PDT 2004
// Terminate early if the ray doesn't intersect the dataset.
// Terminate early if the ray doesn't intersect the dataset.
//
// Kathleen Bonnell, Tue Nov 30 09:25:28 PST 2004
// Set foundElement = foundNode when MatSelected and No subdivision
// occurred, or when not MatSelected and Points not transformed.
// Set foundElement = foundNode when MatSelected and No subdivision
// occurred, or when not MatSelected and Points not transformed.
//
// Hank Childs, Thu Mar 10 10:27:57 PST 2005
// Fix memory leak.
//
// Kathleen Bonnell, Fri Jul 8 14:15:21 PDT 2005
// Kathleen Bonnell, Fri Jul 8 14:15:21 PDT 2005
// Set foundElement = foundNode when points not transformed only if
// ghost zones not created.
//
// Kathleen Bonnell, Tue Aug 29 08:04:41 PDT 2006
// Kathleen Bonnell, Tue Aug 29 08:04:41 PDT 2006
// Set foundElement = foundNode only if OriginalZones intact (eg not
// clipped, contoured, etc).
// clipped, contoured, etc).
//
// Kathleen Bonnell, Thu Oct 26 10:27:36 PDT 2006
// Kathleen Bonnell, Thu Oct 26 10:27:36 PDT 2006
// Added test for NodesPreserved.
//
// Kathleen Biagas, Wed Jun 28 16:32:38 PDT 2017
// If the plot was MatSelected, and we can find a cell, but for some reason
// not the node, pass along enough information for PickNode to possibly
// resolve the information.
//
// ****************************************************************************
void
......@@ -148,6 +153,7 @@ avtLocateNodeQuery::Execute(vtkDataSet *ds, const int dom)
avtDataObjectInformation &info = GetInput()->GetInfo();
double dist, isect[3] = { 0., 0., 0.};
int foundNode = -1;
int foundCell = -1;
int origNode = -1;
int topodim = info.GetAttributes().GetTopologicalDimension();
int spatdim = info.GetAttributes().GetSpatialDimension();
......@@ -163,19 +169,19 @@ avtLocateNodeQuery::Execute(vtkDataSet *ds, const int dom)
}
else
{
int foundCell = LocatorFindCell(ds, dist, isect);
foundCell = LocatorFindCell(ds, dist, isect);
if (foundCell != -1)
{
if (!pickAtts.GetMatSelected())
foundNode = DeterminePickedNode(ds, foundCell, isect);
else
else
foundNode = FindClosestPoint(ds,foundCell,isect,origNode);
}
}
}
else
{
foundNode = RGridFindNode(ds, dist, isect);
foundNode = RGridFindNode(ds, dist, isect);
}
if ((foundNode != -1) && (dist < minDist))
......@@ -185,7 +191,7 @@ avtLocateNodeQuery::Execute(vtkDataSet *ds, const int dom)
pickAtts.SetPickPoint(isect);
if (!pickAtts.GetMatSelected())
{
vtkDataArray *origNodes =
vtkDataArray *origNodes =
ds->GetPointData()->GetArray("avtOriginalNodeNumbers");
if (origNodes)
......@@ -197,35 +203,45 @@ avtLocateNodeQuery::Execute(vtkDataSet *ds, const int dom)
info.GetValidity().GetOriginalZonesIntact() &&
(info.GetValidity().GetZonesPreserved() ||
!info.GetValidity().GetPointsWereTransformed()) &&
info.GetAttributes().GetContainsGhostZones()
info.GetAttributes().GetContainsGhostZones()
!= AVT_CREATED_GHOSTS)
{
foundElement = foundNode;
}
// else ... Zones not preserved or we created ghosts, or points
// were transformed, so node id found here is not valid, so don't
// else ... Zones not preserved or we created ghosts, or points
// were transformed, so node id found here is not valid, so don't
// set it.
}
else if (origNode != -1)
{
// MaterialSelection occurred, but we found an original node,
// MaterialSelection occurred, but we found an original node,
// use that
foundElement = origNode;
foundElement = origNode;
}
else if (!info.GetValidity().SubdivisionOccurred())
{
// MaterialSelection occurred without subdivision, can use the
// node id found here.
foundElement = foundNode;
foundElement = foundNode;
}
// else ... MaterialSelection occurred with subdivision, and the
// original nodes array was not present, so the node id found here
// else ... MaterialSelection occurred with subdivision, and the
// original nodes array was not present, so the node id found here
// will not be valid, so don't set it.
pickAtts.SetCellPoint(isect);
pickAtts.SetNodePoint(ds->GetPoint(foundNode));
foundDomain = dom;
} // if node was found
else if ((foundCell != -1) && (dist < minDist) &&
pickAtts.GetMatSelected())
{
// If we found an intersected cell, we should be able to find the
// node as well, so give NodePick a chance to figure this out.
minDist = dist;
pickAtts.SetCellPoint(isect);
pickAtts.SetPickPoint(isect);
foundDomain = dom;
}
}
......@@ -233,35 +249,35 @@ avtLocateNodeQuery::Execute(vtkDataSet *ds, const int dom)
// Method: avtLocateNodeQuery::RGridFindNode
//
// Purpose:
// Uses rectilinear-grid specific code to find the node closest by
// Uses rectilinear-grid specific code to find the node closest by
// the pick ray. Ignores ghost zones.
//
// Arguments:
// ds The dataset to query.
// dist A place to store the distance along the ray of the
// intersection point.
// isect A place to store the intersetion point of the ray with the
// dataset.
// dist A place to store the distance along the ray of the
// intersection point.
// isect A place to store the intersetion point of the ray with the
// dataset.
//
// Returns:
// The id of the node that was cosest (-1 if none found).
//
// Programmer: Kathleen Bonnell
// Programmer: Kathleen Bonnell
// Creation: May 18, 2004
//
// Modifications:
//
//
// Hank Childs, Fri Aug 27 16:02:58 PDT 2004
// Rename ghost data array.
//
// Kathleen Bonnell, Thu Oct 21 18:02:50 PDT 2004
// Correct test for whether a node is ghost or not.
// Kathleen Bonnell, Thu Oct 21 18:02:50 PDT 2004
// Correct test for whether a node is ghost or not.
//
// Kathleen Bonnell, Mon Jun 27 15:54:52 PDT 2005
// Match new interface for RGridIsect.
// Match new interface for RGridIsect.
//
// Kathleen Bonnell, Tue Oct 2 08:30:04 PDT 2007
// Don't throw away a 'duplicated node' ghost node.
// Kathleen Bonnell, Tue Oct 2 08:30:04 PDT 2007
// Don't throw away a 'duplicated node' ghost node.
//
// ****************************************************************************
......@@ -279,7 +295,7 @@ avtLocateNodeQuery::RGridFindNode(vtkDataSet *ds, double &dist, double *isect)
vtkUnsignedCharArray *ghostNodes = (vtkUnsignedCharArray *)ds->
GetPointData()->GetArray("avtGhostNodes");
unsigned char gn = ghostNodes ? ghostNodes->GetValue(nodeId): 0;
if (ghostNodes && gn > 0 &&
if (ghostNodes && gn > 0 &&
!avtGhostData::IsGhostNodeType(gn, DUPLICATED_NODE))
{
nodeId = -1;
......@@ -293,20 +309,20 @@ avtLocateNodeQuery::RGridFindNode(vtkDataSet *ds, double &dist, double *isect)
// Method: avtLocateNodeQuery::DeterminePickedNode
//
// Purpose:
// Finds the closest node-point to the picked point.
// Finds the closest node-point to the picked point.
//
// Arguments:
// ds The dataset to retrieve information from.
// foundCell the picked ZONE
// foundCell the picked ZONE
// ppoint the node's coordinates.
//
// Notes: Moved from avtLocateCellQuery.
//
// Programmer: Kathleen Bonnell
// Creation: June 2, 2004
// Programmer: Kathleen Bonnell
// Creation: June 2, 2004
//
// Modifications:
//
//
// Hank Childs, Thu Mar 10 10:27:57 PST 2005
// Fix memory leak.
//
......@@ -316,10 +332,10 @@ avtLocateNodeQuery::RGridFindNode(vtkDataSet *ds, double &dist, double *isect)
// ****************************************************************************
int
avtLocateNodeQuery::DeterminePickedNode(vtkDataSet *ds, int foundCell,
avtLocateNodeQuery::DeterminePickedNode(vtkDataSet *ds, int foundCell,
double *ppoint)
{
vtkIdType minId = -1;
vtkIdType minId = -1;
vtkIdList *ptIds = vtkIdList::New();
vtkIdType id;
......@@ -344,8 +360,8 @@ avtLocateNodeQuery::DeterminePickedNode(vtkDataSet *ds, int foundCell,
dist2 = vtkMath::Distance2BetweenPoints(ppoint, ds->GetPoint(id));
if (dist2 < minDist2)
{
minDist2 = dist2;
minId = id;
minDist2 = dist2;
minId = id;
}
}
}
......@@ -360,23 +376,23 @@ avtLocateNodeQuery::DeterminePickedNode(vtkDataSet *ds, int foundCell,
// Method: avtLocateNodeQuery::FindClosestPoint
//
// Purpose:
// Finds the closest node-point to the intersection point.
// Finds the closest node-point to the intersection point.
//
// Arguments:
// ds The dataset to retrieve information from.
// isect the intersection point.
// origNode the original node Id, if any.
//
// Programmer: Kathleen Bonnell
// Creation: June 17, 2004
// Programmer: Kathleen Bonnell
// Creation: June 17, 2004
//
// Modifications:
// Kathleen Bonnell, Thu Jul 29 08:34:18 PDT 2004
// Test for coincident points, return the one that is part of the
// original intersected cell.
//
// Kathleen Bonnell, Tue Aug 10 09:06:54 PDT 2004
// Set id when validOrigNodes size is 1.
//
// Kathleen Bonnell, Tue Aug 10 09:06:54 PDT 2004
// Set id when validOrigNodes size is 1.
//
// Kathleen Bonnell, Mon Aug 30 18:20:50 PDT 2004
// Revamped: FindClosestNPoints orders the points in increasing distance
......@@ -384,13 +400,13 @@ avtLocateNodeQuery::DeterminePickedNode(vtkDataSet *ds, int foundCell,
// keep the first node that has a valid OrigNode associated with it AND is
// part of the isectedCell.
//
// Kathleen Bonnell, Fri May 13 15:16:12 PDT 2005
// Fix memory leak.
// Kathleen Bonnell, Fri May 13 15:16:12 PDT 2005
// Fix memory leak.
//
// Kathleen Bonnell, Mon May 23 12:17:37 PDT 2005
// Kathleen Bonnell, Mon May 23 12:17:37 PDT 2005
// Arg origNode was not getting set.
//
// Kathleen Bonnell, Thu Nov 8 09:01:31 PST 2007
// Kathleen Bonnell, Thu Nov 8 09:01:31 PST 2007
// Rework to only consider 'original' nodes from cells that have same
// original cell as isectedCell.
//
......@@ -471,7 +487,7 @@ avtLocateNodeQuery::FindClosestPoint(vtkDataSet *ds, const int isectedCell,
// Method: avtLocateQuery::FindClosestPointOnLine
//
// Purpose:
// Uses a locator to find the closest point to the given point.
// Uses a locator to find the closest point to the given point.
//
// Arguments:
// ds The dataset to query.
......@@ -480,18 +496,18 @@ avtLocateNodeQuery::FindClosestPoint(vtkDataSet *ds, const int isectedCell,
// Returns:
// The id of the closest point (-1 if none found).
//
// Programmer: Kathleen Bonnell
// Creation: June 10, 2004
// Programmer: Kathleen Bonnell
// Creation: June 10, 2004
//
// Modifications:
//
//
// Hank Childs, Thu Mar 10 10:27:57 PST 2005
// Fix memory leak.
//
// ****************************************************************************
int
avtLocateNodeQuery::FindClosestPointOnLine(vtkDataSet *ds, double &minDist,
avtLocateNodeQuery::FindClosestPointOnLine(vtkDataSet *ds, double &minDist,
double isect[3])
{
if (ds->GetNumberOfPoints() == 0)
......@@ -500,12 +516,12 @@ avtLocateNodeQuery::FindClosestPointOnLine(vtkDataSet *ds, double &minDist,
}
double *rayPt1 = pickAtts.GetRayPoint1();
vtkVisItPointLocator *pointLocator = vtkVisItPointLocator::New();
vtkVisItPointLocator *pointLocator = vtkVisItPointLocator::New();
pointLocator->SetDataSet(ds);
pointLocator->IgnoreDisconnectedPointsOn();
pointLocator->BuildLocator();
vtkIdType foundPoint = -1;
vtkIdType foundPoint = -1;
double pt[3] = {rayPt1[0], rayPt1[1], 0.};
double dist, rad = minDist;
foundPoint = pointLocator->FindClosestPointWithinRadius(rad, pt, dist);
......
......@@ -44,6 +44,7 @@
#include <float.h>
#include <vtkCell.h>
#include <vtkCellData.h>
#include <vtkDataSet.h>
#include <vtkFieldData.h>
......@@ -58,6 +59,7 @@
#include <avtParallel.h>
#include <avtOriginatingSource.h>
#include <avtVector.h>
#include <vtkVisItCellLocator.h>
#include <DebugStream.h>
......@@ -69,7 +71,7 @@ using std::string;
// Method: avtNodePickQuery constructor
//
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
// Creation: May 13, 2004
//
// Modifications:
//
......@@ -88,8 +90,8 @@ avtNodePickQuery::avtNodePickQuery()
// Defines the destructor. Note: this should not be inlined in the header
// because it causes problems for certain compilers.
//
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
//
// Modifications:
//
......@@ -106,39 +108,39 @@ avtNodePickQuery::~avtNodePickQuery()
// Purpose:
// Processes a single domain.
//
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
//
// Modifications:
// Kathleen Bonnell, Tue Aug 10 09:06:54 PDT 2004
// When material-selection has been applied, ensure that RetriveVarInfo
// will be using the correct zone ids for this dataset.
//
// Kathleen Bonnell, Thu Aug 26 09:50:31 PDT 2004
// Kathleen Bonnell, Thu Aug 26 09:50:31 PDT 2004
// Handle case when pickatts.domain has not yet been set. (e.g. when
// picking 2d contour or boundary plots.)
//
// Kathleen Bonnell, Mon Aug 30 17:53:58 PDT 2004
// Modified early-return test -- split into two, and use new flag
// skippedLocate.
// Modified early-return test -- split into two, and use new flag
// skippedLocate.
//
// Kathleen Bonnell, Thu Sep 23 17:38:15 PDT 2004
// Kathleen Bonnell, Thu Sep 23 17:38:15 PDT 2004
// Removed 'needRealId' test, no longer needed (we are reporting ghost
// zones when ghostType == AVT_HAS_GHOSTS).
// zones when ghostType == AVT_HAS_GHOSTS).
//
// Kathleen Bonnell, Mon Dec 6 14:30:39 PST 2004
// Added special logic for when locate was skipped.
// Kathleen Bonnell, Mon Dec 6 14:30:39 PST 2004
// Added special logic for when locate was skipped.
//
// Hank Childs, Thu Mar 10 10:35:37 PST 2005
// Fix memory leak.
//
// Kathleen Bonnell, Tue Jun 28 10:45:28 PDT 2005
// Kathleen Bonnell, Tue Jun 28 10:45:28 PDT 2005
// Calculate 'real' ids under the proper circumstances (Created ghosts,
// the ghost array is available, we don't have the picked node right
// away and the ds is structured).
// away and the ds is structured).
//
// Kathleen Bonnell, Fri Jul 8 14:15:21 PDT 2005
// Changed test for determining if the 'real' id needs to be calculated.
// Kathleen Bonnell, Fri Jul 8 14:15:21 PDT 2005
// Changed test for determining if the 'real' id needs to be calculated.
// Also, transform the point to be used as 'pick letter' when this
// pick did not use the locate query to determine that point.
//
......@@ -150,7 +152,7 @@ avtNodePickQuery::~avtNodePickQuery()
void
avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
{
if (ds == NULL || pickAtts.GetFulfilled())
if (ds == NULL || pickAtts.GetFulfilled())
{
return;
}
......@@ -163,7 +165,7 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
int type = ds->GetDataObjectType();
//
// We may need the real id when picking on a Contour plot of
// an AMR dataset.
// an AMR dataset.
//
bool needRealId = false;
......@@ -179,17 +181,17 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
if (pickedNode == -1 && pickAtts.GetDomain() != -1)
{
// the node could not be found, no further processing required.
// SetDomain and ElementNumber to -1 to indicate failure.
// SetDomain and ElementNumber to -1 to indicate failure.
pickAtts.SetDomain(-1);
pickAtts.SetElementNumber(-1);
debug4 << "PICK BIG PROBLEM! "
<< "Could not find zone corresponding to pick point"
<< "Could not find zone corresponding to pick point"
<< endl;
pickAtts.SetErrorMessage("Pick encountered an internal "
"error (could not find closest node).\n"
"Please contact a VisIt developer");
"Please contact a VisIt developer");
pickAtts.SetError(true);
return;
return;
}
}
if (skippedLocate)
......@@ -199,20 +201,20 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
return;
}
double dist = vtkMath::Distance2BetweenPoints(pickAtts.GetPickPoint(),
ds->GetPoint(pickedNode));
double dist = vtkMath::Distance2BetweenPoints(pickAtts.GetPickPoint(),
ds->GetPoint(pickedNode));
if (dist < minDist)
{
minDist = dist;
}
else
else
{
return;
}
}
pickAtts.SetCellPoint(ds->GetPoint(pickedNode));
pickAtts.SetCellPoint(ds->GetPoint(pickedNode));
if (!pickAtts.GetMatSelected())
{
......@@ -226,26 +228,26 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
else
{
// the zones could not be found, no further processing required.
// SetDomain and ElementNumber to -1 to indicate failure.
// SetDomain and ElementNumber to -1 to indicate failure.
pickAtts.SetDomain(-1);
pickAtts.SetElementNumber(-1);
pickAtts.SetErrorMessage("Pick encountered an internal "
"error (could not determine incident zones).\n"
"Please contact a VisIt developer");
"Please contact a VisIt developer");
pickAtts.SetError(true);
return;
return;
}
}
//
// The database needs a valid domain
//
//
if (pickAtts.GetDomain() == -1)
pickAtts.SetDomain(dom);
//
// Allow the database to add any missing information.
//
//
src->Query(&pickAtts);
if (pickAtts.GetMatSelected() ||
......@@ -258,13 +260,13 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
//
intVector pickedZones = pickAtts.GetIncidentElements();
intVector currentZones = GetCurrentZoneForOriginal(ds, pickedZones);
RetrieveVarInfo(ds, pickAtts.GetElementNumber(), currentZones);
RetrieveVarInfo(ds, pickAtts.GetElementNumber(), currentZones);
}
//
// Set the domain and zone of pickAtts in relation to the
// blockOrigin and cellOrigin of the problem.
//
// blockOrigin and cellOrigin of the problem.
//
if (singleDomain)
{
//
......@@ -311,7 +313,7 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
{
pickAtts.SetPickPoint(pickAtts.GetNodePoint());
}
else
else
{
avtVector v1(pickAtts.GetCellPoint());
v1 = (*transform) *v1;
......@@ -328,7 +330,7 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
pickAtts.SetNeedTransformMessage(false);
pickAtts.SetPickPoint(pickAtts.GetNodePoint());
}
else
else
{
pickAtts.SetPickPoint(pickAtts.GetCellPoint());
}
......@@ -337,7 +339,7 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
{
if (!needRealId)
foundNode = pickedNode;
else
else
foundNode = pickAtts.GetRealElementNumber();
foundDomain = dom;
}
......@@ -348,7 +350,7 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
// Method: avtNodePickQuery::DeterminePickedNode
//
// Purpose:
// Finds the closest node-point to the picked point.
// Finds the closest node-point to the picked point.
//
// Arguments:
// ds The dataset to retrieve information from.
......@@ -356,24 +358,31 @@ avtNodePickQuery::Execute(vtkDataSet *ds, const int dom)
// Returns:
// The node id closest to PickPoint. (-1 if there is some kind of failure).
//
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
// Programmer: Kathleen Bonnell
// Creation: May 13, 2004
//
// Modifications:
// Kathleen Bonnell, Mon Dec 6 14:30:39 PST 2004
// Add logic to return -1 when pickpoint does not lie in dataset bounds,
// and if 'FindPoint' returns a ghost node.
//
// Kathleen Bonnell, Tue Jun 28 10:47:35 PDT 2005
//
// Kathleen Bonnell, Tue Jun 28 10:47:35 PDT 2005
// Find intersected cell and test if it is a ghost before proceeding
// further.
// further.
//
// Hank Childs, Fri Jun 9 14:43:27 PDT 2006
// Move currently unused variable into section removed by preprocessor
// directive. Purpose is to remove compiler warning.
//
// Kathleen Bonnell, Tue Oct 2 08:30:04 PDT 2007
// Don't throw away a 'duplicated node' ghost node.
// Kathleen Bonnell, Tue Oct 2 08:30:04 PDT 2007
// Don't throw away a 'duplicated node' ghost node.
//
// Kathleen Biagas, Wed Jun 28 08:24:35 PDT 2017
// Resolving #2816, Use cell locator instead of vtkVisItUtility::FindCell,
// it yields better results in more cases. Added logic to search for
// closest node on faces instead of entire cell, as closest node may not
// lie on the face that was intersected, but user will be expecting a
// result on the intersected face.