void avtLineScanQuery::WalkChain1(vtkPolyData *pd, int ptId, int cellId, vtkIntArray *lineids, int lineid, int &newPtId, int &newCellId) { static vtkIdList *list = vtkIdList::New(); list->Reset(); pd->GetCellPoints(cellId, list); if (list->GetNumberOfIds() != 2) { EXCEPTION0(ImproperUseException); } int id1 = list->GetId(0); int id2 = list->GetId(1); newPtId = (id1 == ptId ? id2 : id1); int seg1, seg2; int numMatches = GetCellsForPoint(newPtId, pd, lineids, lineid, seg1, seg2); if (numMatches <= 1) newCellId = -1; else if (numMatches > 2) { EXCEPTION0(ImproperUseException); } else { newCellId = (seg1 == cellId ? seg2 : seg1); } }
int avtLineScanQuery::WalkChain(vtkPolyData *pd, int ptId, int cellId, std::vector<bool> &usedPoint, vtkIntArray *lineids, int lineid) { static vtkIdList *list = vtkIdList::New(); bool haventFoundEnd = true; int curCell = cellId; int curPt = ptId; int endOfChain = -1; int counter = 0; while (haventFoundEnd) { list->Reset(); pd->GetCellPoints(curCell, list); if (list->GetNumberOfIds() != 2) { EXCEPTION0(ImproperUseException); } int id1 = list->GetId(0); int id2 = list->GetId(1); int newId = (id1 == curPt ? id2 : id1); usedPoint[newId] = true; int seg1, seg2; int numMatches = GetCellsForPoint(newId, pd, lineids, lineid, seg1, seg2); if (numMatches <= 1) { haventFoundEnd = false; endOfChain = newId; } else if (numMatches > 2) { // This is an error condition. It is believed to occur when // a line coincides with an edge. Empirically, it is believed // to happen about one time when you cast 100K lines over 90M // zones. So: it doesn't happen often, but it happens enough. // In this case, just ignoring the line won't affect statistics. haventFoundEnd = false; endOfChain = -1; } else { curPt = newId; curCell = (seg1 == curCell ? seg2 : seg1); } if (counter++ > 1000000) { haventFoundEnd = false; endOfChain = -1; } } return endOfChain; }
void avtAggregateChordLengthDistributionQuery::ExecuteLineScan(vtkPolyData *pd) { vtkIntArray *lineids = (vtkIntArray *) pd->GetCellData()->GetArray("avtLineID"); if (lineids == NULL) EXCEPTION0(ImproperUseException); int npts = pd->GetNumberOfPoints(); std::vector<bool> usedPoint(npts, false); pd->BuildLinks(); pd->BuildCells(); // When we determine which line segments are on one side of another, // we need to examine the other segments. But we only want to consider // segments that are from the same line (i.e. have the same lineid). // So we are using this data structure to keep track of which segments // come from which line. (Instead of having to iterate through all the // other segments each time we examine a segment.) // // So why hash? // The lines are spread out over many processors. So proc X may have // lines 100,000 - 100,500. So we either have to have vectors that are // way too big (100,500 entries with the first 100,000 empty), // or we have to do some clever indexing. So we are doing // some clever indexing. In this case, hashing. int hashSize = 10000; std::vector< std::vector<int> > hashed_lineid_lookup(hashSize); std::vector< std::vector<double> > hashed_segment_length(hashSize); for (int i = 0 ; i < npts ; i++) { if (usedPoint[i]) continue; int seg1, seg2; int numMatches = GetCellsForPoint(i, pd, lineids, -1, seg1, seg2); if (numMatches == 0) continue; if (numMatches > 2) { // We found an error condition. Give up on this line. This // happens infrequently enough that it should not affect our // statistics. continue; } int oneSide = i; int otherSide = i; int lineid = lineids->GetValue(seg1); if (numMatches == 1) { oneSide = i; otherSide = WalkChain(pd, i, seg1, usedPoint, lineids, lineid); } else if (numMatches == 2) { oneSide = WalkChain(pd, i, seg1, usedPoint, lineids, lineid); otherSide = WalkChain(pd, i, seg2, usedPoint, lineids, lineid); } if (oneSide == -1 || otherSide == -1) { // We found an error condition. Give up on this line. This // happens infrequently enough that it should not affect our // statistics. continue; } double pt1[3]; double pt2[3]; pd->GetPoint(oneSide, pt1); pd->GetPoint(otherSide, pt2); double dist = sqrt((pt2[0]-pt1[0])*(pt2[0]-pt1[0]) + (pt2[1]-pt1[1])*(pt2[1]-pt1[1]) + (pt2[2]-pt1[2])*(pt2[2]-pt1[2])); int hashid = lineid % hashSize; hashed_lineid_lookup[hashid].push_back(lineid); hashed_segment_length[hashid].push_back(dist); } for (int i = 0 ; i < hashSize ; i++) { std::vector<int> already_considered; for (int j = 0 ; j < hashed_lineid_lookup[i].size() ; j++) { bool alreadyDoneLineId = false; int k; for (k = 0 ; k < already_considered.size() ; k++) if (hashed_lineid_lookup[i][j] == already_considered[k]) alreadyDoneLineId = true; if (alreadyDoneLineId) continue; int lineid = hashed_lineid_lookup[i][j]; already_considered.push_back(lineid); double length = 0.; for (k = j ; k < hashed_lineid_lookup[i].size() ; k++) { if (hashed_lineid_lookup[i][k] == lineid) length += hashed_segment_length[i][k]; } int bin = (int)((length-minLength)/(maxLength-minLength) * numBins); if (bin < 0) bin = 0; if (bin >= numBins) bin = numBins-1; numChords[bin]++; } } }
void avtIndividualChordLengthDistributionQuery::ExecuteLineScan(vtkPolyData *pd) { vtkIntArray *lineids = (vtkIntArray *) pd->GetCellData()->GetArray("avtLineID"); if (lineids == NULL) EXCEPTION0(ImproperUseException); int npts = pd->GetNumberOfPoints(); std::vector<bool> usedPoint(npts, false); pd->BuildLinks(); pd->BuildCells(); for (int i = 0 ; i < npts ; i++) { if (usedPoint[i]) continue; int seg1, seg2; int numMatches = GetCellsForPoint(i, pd, lineids, -1, seg1, seg2); if (numMatches == 0) continue; if (numMatches > 2) { // We found an error condition. Give up on this line. This // happens infrequently enough that it should not affect our // statistics. continue; } int oneSide = i; int otherSide = i; int lineid = lineids->GetValue(seg1); if (numMatches == 1) { oneSide = i; otherSide = WalkChain(pd, i, seg1, usedPoint, lineids, lineid); } else if (numMatches == 2) { oneSide = WalkChain(pd, i, seg1, usedPoint, lineids, lineid); otherSide = WalkChain(pd, i, seg2, usedPoint, lineids, lineid); } if (oneSide == -1 || otherSide == -1) { // We found an error condition. Give up on this line. This // happens infrequently enough that it should not affect our // statistics. continue; } double pt1[3]; double pt2[3]; pd->GetPoint(oneSide, pt1); pd->GetPoint(otherSide, pt2); double dist = sqrt((pt2[0]-pt1[0])*(pt2[0]-pt1[0]) + (pt2[1]-pt1[1])*(pt2[1]-pt1[1]) + (pt2[2]-pt1[2])*(pt2[2]-pt1[2])); int bin = (int)((dist-minLength) / (maxLength-minLength) * numBins); if (bin < 0) bin = 0; if (bin >= numBins) bin = numBins-1; numChords[bin]++; } }
void avtMassDistributionQuery::ExecuteLineScan(vtkPolyData *pd) { vtkIntArray *lineids = (vtkIntArray *) pd->GetCellData()->GetArray("avtLineID"); if (lineids == NULL) EXCEPTION0(ImproperUseException); int npts = pd->GetNumberOfPoints(); std::vector<bool> usedPoint(npts, false); vtkDataArray *arr = pd->GetCellData()->GetArray(varname.c_str()); pd->BuildLinks(); pd->BuildCells(); int extraMsg = 100; int totalProg = totalNodes * extraMsg; int amtPerMsg = npts / extraMsg + 1; UpdateProgress(extraMsg*currentNode+2*extraMsg/3, totalProg); int lastMilestone = 0; for (int i = 0 ; i < npts ; i++) { if (usedPoint[i]) continue; int seg1 = 0, seg2 = 0; int numMatches = GetCellsForPoint(i, pd, lineids, -1, seg1, seg2); if (numMatches == 0) continue; if (numMatches > 2) { // We found an error condition. Give up on this line. This // happens infrequently enough that it should not affect our // statistics. continue; } int oneSide = i; int otherSide = i; int lineid = lineids->GetValue(seg1); if (numMatches == 1) { oneSide = i; otherSide = WalkChain(pd, i, seg1, usedPoint, lineids, lineid); } else if (numMatches == 2) { oneSide = WalkChain(pd, i, seg1, usedPoint, lineids, lineid); otherSide = WalkChain(pd, i, seg2, usedPoint, lineids, lineid); } if (oneSide == -1 || otherSide == -1) { // We found an error condition. Give up on this line. This // happens infrequently enough that it should not affect our // statistics. continue; } double pt1[3]; double pt2[3]; pd->GetPoint(oneSide, pt1); pd->GetPoint(otherSide, pt2); double dist = sqrt((pt2[0]-pt1[0])*(pt2[0]-pt1[0]) + (pt2[1]-pt1[1])*(pt2[1]-pt1[1]) + (pt2[2]-pt1[2])*(pt2[2]-pt1[2])); int bin = (int)((dist-minLength) / (maxLength-minLength) * numBins); if (bin < 0) bin = 0; if (bin >= numBins) bin = numBins-1; int curId = oneSide; numMatches = GetCellsForPoint(curId, pd, lineids, -1, seg1, seg2); int curCell = seg1; double curSegMass = 0.; while (curId != otherSide) { double curSegDen = (arr != NULL ? arr->GetTuple1(curCell) : 1.); int newPtId, newCellId; WalkChain1(pd, curId, curCell, lineids, lineid, newPtId, newCellId); pd->GetPoint(curId, pt1); pd->GetPoint(newPtId, pt2); double dist = sqrt((pt2[0]-pt1[0])*(pt2[0]-pt1[0]) + (pt2[1]-pt1[1])*(pt2[1]-pt1[1]) + (pt2[2]-pt1[2])*(pt2[2]-pt1[2])); curSegMass += curSegDen*dist; curId = newPtId; curCell = newCellId; if (curCell == -1 && curId != otherSide) { debug1 << "INTERNAL ERROR: path could not be reproduced." << endl; break; } } mass[bin] += curSegMass; int currentMilestone = (int)(((float) i) / amtPerMsg); if (currentMilestone > lastMilestone) { UpdateProgress((int)( extraMsg*currentNode+2*extraMsg/3.+currentMilestone/3), extraMsg*totalNodes); lastMilestone = currentMilestone; } } }