diff --git a/docs/changelog/tube-cell-fields.md b/docs/changelog/tube-cell-fields.md new file mode 100644 index 000000000..540e86a13 --- /dev/null +++ b/docs/changelog/tube-cell-fields.md @@ -0,0 +1,19 @@ +# Fix handling of cell fields in Tube filter + +The `Tube` filter wraps a tube of polygons around poly line cells. +During this process it had a strange (and wrong) handling of cell data. +It assumed that each line had an independent field entry for each +segment of each line. It thus had lots of extra code to find the length +and offsets of the segment data in the cell data. + +This is simply not how cell fields work in VTK-m. In VTK-m, each cell +has exactly one entry in the cell field array. Even if a polyline has +100 segments, it only gets one cell field value. This behavior is +consistent with how VTK treats cell field arrays. + +The behavior the `Tube` filter was trying to implement was closer to an +"edge" field. However, edge fields are currently not supported in VTK-m. +The proper implementation would be to add edge fields to VTK-m. (This +would also get around some problems with the implementation that was +removed here when mixing polylines with other cell types and degenerate +lines.) diff --git a/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx b/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx index a6a7e8736..560f11566 100644 --- a/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx +++ b/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx @@ -62,14 +62,12 @@ void TestTubeFilters() ptVar.push_back(1); ptVar.push_back(2); cellVar.push_back(100); - cellVar.push_back(101); //Polyline 2. ptVar.push_back(10); ptVar.push_back(11); ptVar.push_back(12); cellVar.push_back(110); - cellVar.push_back(111); //Add some degenerate polylines. //Polyline 3: (only 1 point) @@ -79,7 +77,6 @@ void TestTubeFilters() ptVar.push_back(-1); ptVar.push_back(-1); cellVar.push_back(-1); - cellVar.push_back(-1); ds.AddPointField("pointVar", ptVar); ds.AddCellField("cellVar", cellVar); @@ -117,10 +114,10 @@ void TestTubeFilters() vtkm::cont::ArrayHandle cellArr; output.GetField("cellVar").GetData().AsArrayHandle(cellArr); VTKM_TEST_ASSERT(cellArr.GetNumberOfValues() == 36, "Wrong number of values in cell field"); - std::vector cellVals = { 100, 100, 100, 100, 100, 100, 101, 101, 101, - 101, 101, 101, 100, 100, 100, 101, 101, 101, - 110, 110, 110, 110, 110, 110, 111, 111, 111, - 111, 111, 111, 110, 110, 110, 111, 111, 111 }; + std::vector cellVals = { 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 100, + 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110 }; portal = cellArr.ReadPortal(); for (vtkm::Id i = 0; i < 36; i++) VTKM_TEST_ASSERT(portal.Get(i) == cellVals[static_cast(i)], diff --git a/vtkm/filter/geometry_refinement/worklet/Tube.h b/vtkm/filter/geometry_refinement/worklet/Tube.h index 22be15f6e..981e8e034 100644 --- a/vtkm/filter/geometry_refinement/worklet/Tube.h +++ b/vtkm/filter/geometry_refinement/worklet/Tube.h @@ -48,7 +48,6 @@ public: FieldOut ptsPerPolyline, FieldOut ptsPerTube, FieldOut numTubeConnIds, - FieldOut linesPerPolyline, FieldOut validCell); using ExecutionSignature = void(CellShape shapeType, PointCount numPoints, @@ -58,8 +57,7 @@ public: _4 ptsPerPolyline, _5 ptsPerTube, _6 numTubeConnIds, - _7 linesPerPolyline, - _8 validCell); + _7 validCell); using InputDomain = _1; template @@ -71,7 +69,6 @@ public: vtkm::Id& ptsPerPolyline, vtkm::Id& ptsPerTube, vtkm::Id& numTubeConnIds, - vtkm::Id& linesPerPolyline, vtkm::Id& validCell) const { // We only support polylines that contain 2 or more points. @@ -97,7 +94,6 @@ public: ptsPerTube = this->NumSides * numNonCoincidentPoints; // (two tris per segment) X (numSides) X numVertsPerCell numTubeConnIds = (numNonCoincidentPoints - 1) * 2 * this->NumSides * this->NumVertsPerCell; - linesPerPolyline = numNonCoincidentPoints - 1; //Capping adds center vertex in middle of cap, plus NumSides triangles for cap. if (this->Capping) @@ -113,7 +109,6 @@ public: nonIncidentPtsPerPolyline = 0; ptsPerTube = 0; numTubeConnIds = 0; - linesPerPolyline = 0; } } @@ -481,24 +476,23 @@ public: FieldInCell ptsPerPolyline, FieldInCell tubePointOffsets, FieldInCell tubeConnOffsets, - FieldInCell segOffset, WholeArrayOut outConnectivity, WholeArrayOut outCellSrcIdx); using ExecutionSignature = void(CellShape shapeType, + InputIndex inCellIndex, _2 ptsPerPolyline, _3 tubePointOffset, _4 tubeConnOffsets, - _5 segOffset, - _6 outConn, - _7 outCellSrcIdx); + _5 outConn, + _6 outCellSrcIdx); using InputDomain = _1; template VTKM_EXEC void operator()(const CellShapeTag& shapeType, + vtkm::Id inCellIndex, const vtkm::IdComponent& numPoints, const vtkm::Id& tubePointOffset, const vtkm::Id& tubeConnOffset, - const vtkm::Id& segOffset, OutConnType& outConn, OutCellSrcIdxType& outCellSrcIdx) const { @@ -517,7 +511,7 @@ public: outConn.Set(outIdx + 1, tubePtOffset + i * this->NumSides + (j + 1) % this->NumSides); outConn.Set(outIdx + 2, tubePtOffset + (i + 1) * this->NumSides + (j + 1) % this->NumSides); - outCellSrcIdx.Set(outIdx / 3, segOffset + static_cast(i)); + outCellSrcIdx.Set(outIdx / 3, inCellIndex); outIdx += 3; //Triangle 2: verts 0,2,3 @@ -525,7 +519,7 @@ public: outConn.Set(outIdx + 1, tubePtOffset + (i + 1) * this->NumSides + (j + 1) % this->NumSides); outConn.Set(outIdx + 2, tubePtOffset + (i + 1) * this->NumSides + j); - outCellSrcIdx.Set(outIdx / 3, segOffset + static_cast(i)); + outCellSrcIdx.Set(outIdx / 3, inCellIndex); outIdx += 3; } } @@ -539,7 +533,7 @@ public: outConn.Set(outIdx + 0, startCenterPt); outConn.Set(outIdx + 1, startCenterPt + 1 + j); outConn.Set(outIdx + 2, startCenterPt + 1 + ((j + 1) % this->NumSides)); - outCellSrcIdx.Set(outIdx / 3, segOffset); + outCellSrcIdx.Set(outIdx / 3, inCellIndex); outIdx += 3; } @@ -552,7 +546,7 @@ public: outConn.Set(outIdx + 0, endCenterPt); outConn.Set(outIdx + 1, endOffsetPt + j); outConn.Set(outIdx + 2, endOffsetPt + ((j + 1) % this->NumSides)); - outCellSrcIdx.Set(outIdx / 3, segOffset + static_cast(numPoints - 2)); + outCellSrcIdx.Set(outIdx / 3, inCellIndex); outIdx += 3; } } @@ -622,8 +616,7 @@ public: } //Count number of polyline pts, tube pts and tube cells - vtkm::cont::ArrayHandle ptsPerPolyline, ptsPerTube, numTubeConnIds, segPerPolyline, - validCell; + vtkm::cont::ArrayHandle ptsPerPolyline, ptsPerTube, numTubeConnIds, validCell; vtkm::cont::ArrayHandle nonIncidentPtsPerPolyline; CountSegments countSegs(this->Capping, this->NumSides); vtkm::worklet::DispatcherMapTopology countInvoker(countSegs); @@ -633,7 +626,6 @@ public: ptsPerPolyline, ptsPerTube, numTubeConnIds, - segPerPolyline, validCell); vtkm::Id totalPolylinePts = vtkm::cont::Algorithm::Reduce(ptsPerPolyline, vtkm::Id(0)); @@ -645,14 +637,13 @@ public: vtkm::Id totalTubeCells = totalTubeConnIds / 3; vtkm::cont::ArrayHandle polylinePtOffset, nonIncidentPolylinePtOffset, - tubePointOffsets, tubeConnOffsets, segOffset; + tubePointOffsets, tubeConnOffsets; vtkm::cont::Algorithm::ScanExclusive(ptsPerPolyline, polylinePtOffset); vtkm::cont::Algorithm::ScanExclusive( vtkm::cont::make_ArrayHandleCast(nonIncidentPtsPerPolyline), nonIncidentPolylinePtOffset); vtkm::cont::Algorithm::ScanExclusive(ptsPerTube, tubePointOffsets); vtkm::cont::Algorithm::ScanExclusive(numTubeConnIds, tubeConnOffsets); - vtkm::cont::Algorithm::ScanExclusive(segPerPolyline, segOffset); //Generate normals at each point on all polylines NormalsType normals; @@ -686,7 +677,6 @@ public: nonIncidentPtsPerPolyline, tubePointOffsets, tubeConnOffsets, - segOffset, newConnectivity, this->OutputCellSourceIndex); newCells.Fill(totalTubePts, vtkm::CELL_SHAPE_TRIANGLE, 3, newConnectivity);