inline void ConstructPolyDataHelper(vtkPointData *inPD, vtkCellData *inCD, vtkPolyData *output, const vtkSurfaceFromVolume::PointList &pt_list, const vtkSurfaceFromVolume::TriangleList &tris, int dataType, const PointGetter &pointGetter) { vtkIdType i, j; vtkPointData *outPD = output->GetPointData(); vtkCellData *outCD = output->GetCellData(); vtkIntArray *newOrigNodes = NULL; vtkIntArray *origNodes = vtkIntArray::SafeDownCast( inPD->GetArray("avtOriginalNodeNumbers")); // // Set up the output points and its point data. // vtkPoints *outPts = vtkPoints::New(dataType); vtkIdType nOutPts = pt_list.GetTotalNumberOfPoints(); outPts->SetNumberOfPoints(nOutPts); outPD->CopyAllocate(inPD, nOutPts); if (origNodes != NULL) { newOrigNodes = vtkIntArray::New(); newOrigNodes->SetNumberOfComponents(origNodes->GetNumberOfComponents()); newOrigNodes->SetNumberOfTuples(nOutPts); newOrigNodes->SetName(origNodes->GetName()); } vtkIdType nLists = pt_list.GetNumberOfLists(); vtkIdType ptIdx = 0; for (i = 0 ; i < nLists ; i++) { const vtkDataSetFromVolume::PointEntry *pe_list = NULL; vtkIdType nPts = pt_list.GetList(i, pe_list); for (j = 0 ; j < nPts ; j++) { const vtkDataSetFromVolume::PointEntry &pe = pe_list[j]; double pt[3], pt1[3], pt2[3]; pointGetter.GetPoint(pe.ptIds[0], pt1); pointGetter.GetPoint(pe.ptIds[1], pt2); double p = pe.percent; double bp = 1. - p; pt[0] = pt1[0]*p + pt2[0]*bp; pt[1] = pt1[1]*p + pt2[1]*bp; pt[2] = pt1[2]*p + pt2[2]*bp; outPts->SetPoint(ptIdx, pt); outPD->InterpolateEdge(inPD, ptIdx, pe.ptIds[0], pe.ptIds[1], bp); if (newOrigNodes) { vtkIdType id = (bp <= 0.5 ? pe.ptIds[0] : pe.ptIds[1]); newOrigNodes->SetTuple(ptIdx, origNodes->GetTuple(id)); } ptIdx++; } } output->SetPoints(outPts); outPts->Delete(); if (newOrigNodes) { // AddArray will overwrite an already existing array with // the same name, exactly what we want here. outPD->AddArray(newOrigNodes); newOrigNodes->Delete(); } // // Now set up the triangles and the cell data. // vtkIdType ntris = tris.GetTotalNumberOfTriangles(); vtkIdTypeArray *nlist = vtkIdTypeArray::New(); nlist->SetNumberOfValues(3*ntris + ntris); vtkIdType *nl = nlist->GetPointer(0); outCD->CopyAllocate(inCD, ntris); vtkIdType cellId = 0; vtkIdType nlists = tris.GetNumberOfLists(); for (i = 0 ; i < nlists ; i++) { const vtkIdType *list; vtkIdType listSize = tris.GetList(i, list); for (j = 0 ; j < listSize ; j++) { outCD->CopyData(inCD, list[0], cellId); *nl++ = 3; *nl++ = list[1]; *nl++ = list[2]; *nl++ = list[3]; list += 4; cellId++; } } vtkCellArray *cells = vtkCellArray::New(); cells->SetCells(ntris, nlist); nlist->Delete(); output->SetPolys(cells); cells->Delete(); }
void ConstructDataSetHelper(vtkPointData *inPD, vtkCellData *inCD, vtkUnstructuredGrid *output, int dataType, vtkIdType numPrevPts, vtkVolumeFromVolume::ShapeList *shapes[8], int nshapes, vtkVolumeFromVolume::PointList &pt_list, vtkVolumeFromVolume::CentroidPointList ¢roid_list, const PointGetter &pointGetter) { vtkPointData *outPD = output->GetPointData(); vtkCellData *outCD = output->GetCellData(); vtkIntArray *newOrigNodes = NULL; vtkIntArray *origNodes = vtkIntArray::SafeDownCast( inPD->GetArray("avtOriginalNodeNumbers")); // // If the isovolume only affects a small part of the dataset, we can save // on memory by only bringing over the points from the original dataset // that are used with the output. Determine which points those are here. // int *ptLookup = new int[numPrevPts]; for (vtkIdType i = 0 ; i < numPrevPts ; i++) ptLookup[i] = -1; int numUsed = 0; for (int i = 0 ; i < nshapes ; i++) { vtkIdType nlists = shapes[i]->GetNumberOfLists(); int npts_per_shape = shapes[i]->GetShapeSize(); for (vtkIdType j = 0 ; j < nlists ; j++) { const vtkIdType *list; vtkIdType listSize = shapes[i]->GetList(j, list); for (vtkIdType k = 0 ; k < listSize ; k++) { list++; // skip the cell id entry for (vtkIdType l = 0 ; l < npts_per_shape ; l++) { int pt = *list; list++; if (pt >= 0 && pt < numPrevPts) if (ptLookup[pt] == -1) ptLookup[pt] = numUsed++; } } } } // // Set up the output points and its point data. // vtkPoints *outPts = vtkPoints::New(dataType); vtkIdType centroidStart = numUsed + pt_list.GetTotalNumberOfPoints(); vtkIdType nOutPts = centroidStart + centroid_list.GetTotalNumberOfPoints(); outPts->SetNumberOfPoints(nOutPts); outPD->CopyAllocate(inPD, nOutPts); if (origNodes != NULL) { newOrigNodes = vtkIntArray::New(); newOrigNodes->SetNumberOfComponents(origNodes->GetNumberOfComponents()); newOrigNodes->SetNumberOfTuples(nOutPts); newOrigNodes->SetName(origNodes->GetName()); } // // Copy over all the points from the input that are actually used in the // output. // for (vtkIdType i = 0 ; i < numPrevPts ; i++) { if (ptLookup[i] == -1) continue; double pt[3]; pointGetter.GetPoint(i, pt); outPts->SetPoint(ptLookup[i], pt); outPD->CopyData(inPD, i, ptLookup[i]); if (newOrigNodes) newOrigNodes->SetTuple(ptLookup[i], origNodes->GetTuple(i)); } vtkIdType ptIdx = numUsed; // // Now construct all the points that are along edges and new and add // them to the points list. // vtkIdType nLists = pt_list.GetNumberOfLists(); for (vtkIdType i = 0 ; i < nLists ; i++) { const vtkVolumeFromVolume::PointEntry *pe_list = NULL; vtkIdType nPts = pt_list.GetList(i, pe_list); for (vtkIdType j = 0 ; j < nPts ; j++) { const vtkVolumeFromVolume::PointEntry &pe = pe_list[j]; double pt[3], pt1[3], pt2[3]; pointGetter.GetPoint(pe.ptIds[0], pt1); pointGetter.GetPoint(pe.ptIds[1], pt2); // Now that we have the original points, calculate the new one. double p = pe.percent; double bp = 1. - p; pt[0] = pt1[0]*p + pt2[0]*bp; pt[1] = pt1[1]*p + pt2[1]*bp; pt[2] = pt1[2]*p + pt2[2]*bp; outPts->SetPoint(ptIdx, pt); outPD->InterpolateEdge(inPD, ptIdx, pe.ptIds[0], pe.ptIds[1], bp); if (newOrigNodes) { vtkIdType id = (bp <= 0.5 ? pe.ptIds[0] : pe.ptIds[1]); newOrigNodes->SetTuple(ptIdx, origNodes->GetTuple(id)); } ptIdx++; } } // // Now construct the new "centroid" points and add them to the points list. // nLists = centroid_list.GetNumberOfLists(); vtkIdList *idList = vtkIdList::New(); for (vtkIdType i = 0 ; i < nLists ; i++) { const vtkVolumeFromVolume::CentroidPointEntry *ce_list = NULL; vtkIdType nPts = centroid_list.GetList(i, ce_list); for (vtkIdType j = 0 ; j < nPts ; j++) { const vtkVolumeFromVolume::CentroidPointEntry &ce = ce_list[j]; idList->SetNumberOfIds(ce.nPts); double pts[8][3]; double weights[8]; double pt[3] = {0., 0., 0.}; double weight_factor = 1. / ce.nPts; for (int k = 0 ; k < ce.nPts ; k++) { weights[k] = 1.0 * weight_factor; vtkIdType id = 0; if (ce.ptIds[k] < 0) id = centroidStart-1 - ce.ptIds[k]; else if (ce.ptIds[k] >= numPrevPts) id = numUsed + (ce.ptIds[k] - numPrevPts); else id = ptLookup[ce.ptIds[k]]; idList->SetId(k, id); outPts->GetPoint(id, pts[k]); pt[0] += pts[k][0]; pt[1] += pts[k][1]; pt[2] += pts[k][2]; } pt[0] *= weight_factor; pt[1] *= weight_factor; pt[2] *= weight_factor; outPts->SetPoint(ptIdx, pt); outPD->InterpolatePoint(outPD, ptIdx, idList, weights); if (newOrigNodes) { // these 'created' nodes have no original designation for (int z = 0; z < newOrigNodes->GetNumberOfComponents(); z++) newOrigNodes->SetComponent(ptIdx, z, -1); } ptIdx++; } } idList->Delete(); // // We are finally done constructing the points list. Set it with our // output and clean up memory. // output->SetPoints(outPts); outPts->Delete(); if (newOrigNodes) { // AddArray will overwrite an already existing array with // the same name, exactly what we want here. outPD->AddArray(newOrigNodes); newOrigNodes->Delete(); } // // Now set up the shapes and the cell data. // vtkIdType cellId = 0; vtkIdType nlists; vtkIdType ncells = 0; vtkIdType conn_size = 0; for (int i = 0 ; i < nshapes ; i++) { vtkIdType ns = shapes[i]->GetTotalNumberOfShapes(); ncells += ns; conn_size += (shapes[i]->GetShapeSize()+1)*ns; } outCD->CopyAllocate(inCD, ncells); vtkIdTypeArray *nlist = vtkIdTypeArray::New(); nlist->SetNumberOfValues(conn_size); vtkIdType *nl = nlist->GetPointer(0); vtkUnsignedCharArray *cellTypes = vtkUnsignedCharArray::New(); cellTypes->SetNumberOfValues(ncells); unsigned char *ct = cellTypes->GetPointer(0); vtkIdTypeArray *cellLocations = vtkIdTypeArray::New(); cellLocations->SetNumberOfValues(ncells); vtkIdType *cl = cellLocations->GetPointer(0); vtkIdType ids[1024]; // 8 (for hex) should be max, but... vtkIdType current_index = 0; for (int i = 0 ; i < nshapes ; i++) { const vtkIdType *list; nlists = shapes[i]->GetNumberOfLists(); int shapesize = shapes[i]->GetShapeSize(); int vtk_type = shapes[i]->GetVTKType(); for (vtkIdType j = 0 ; j < nlists ; j++) { int listSize = shapes[i]->GetList(j, list); for (vtkIdType k = 0 ; k < listSize ; k++) { outCD->CopyData(inCD, list[0], cellId); for (int l = 0 ; l < shapesize ; l++) { if (list[l+1] < 0) ids[l] = centroidStart-1 - list[l+1]; else if (list[l+1] >= numPrevPts) ids[l] = numUsed + (list[l+1] - numPrevPts); else ids[l] = ptLookup[list[l+1]]; } list += shapesize+1; *nl++ = shapesize; *cl++ = current_index; *ct++ = vtk_type; for (int l = 0 ; l < shapesize ; l++) *nl++ = ids[l]; current_index += shapesize+1; //output->InsertNextCell(vtk_type, shapesize, ids); cellId++; } } } vtkCellArray *cells = vtkCellArray::New(); cells->SetCells(ncells, nlist); nlist->Delete(); output->SetCells(cellTypes, cellLocations, cells); cellTypes->Delete(); cellLocations->Delete(); cells->Delete(); delete [] ptLookup; }