From 5bd60a0b779b5b97c274eb990fdc85f02fcdea8d Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Wed, 26 Jan 2022 17:11:11 -0700 Subject: [PATCH] Add `CreateResult` to `NewFilter` and absorb field mapping The original version of `Filter` classes had a helper header file named `CreateResult.h` that had several forms of a `CreateResult` function that helped correctly create the `DataSet` to be returned from a filter's `DoExecute`. With the move to the `NewFilter` structure, these functions did not line up very well with how `DataSet`s should actually be created. A replacement for these functions have been added as protected helper methods to `NewFilter` and `NewFilterField`. In addition to moving them into the filter themselves, the behavior of `CreateResult` has been merged with the map field to output functionality. The original implementation of `Filter` did this mapping internally in a different step. The first design of `NewFilter` required the filter implementer to call a `MapFieldsOntoOutput` themselves. This new implementation wraps the functionality of `CreateResult` and `MapFieldsOntoOutput` together so that the `DataSet` will be created correctly with a single call to `CreateResult`. This makes it easier to correctly create the output. --- .../changelog/create-result-does-field-map.md | 18 ++ vtkm/cont/DataSet.h | 8 + vtkm/filter/CreateResult.h | 3 + vtkm/filter/NewFilter.cxx | 11 ++ vtkm/filter/NewFilter.h | 157 +++++++++++++++--- vtkm/filter/NewFilterField.cxx | 10 ++ vtkm/filter/NewFilterField.h | 92 ++++++++++ vtkm/filter/clean_grid/CleanGrid.cxx | 42 ++--- .../CellSetConnectivity.cxx | 5 +- .../ImageConnectivity.cxx | 5 +- .../entity_extraction/ExternalFaces.cxx | 15 +- .../entity_extraction/ExtractGeometry.cxx | 8 +- .../entity_extraction/ExtractPoints.cxx | 7 +- .../entity_extraction/ExtractStructured.cxx | 8 +- .../entity_extraction/GhostCellRemove.cxx | 8 +- vtkm/filter/entity_extraction/Mask.cxx | 8 +- vtkm/filter/entity_extraction/MaskPoints.cxx | 7 +- vtkm/filter/entity_extraction/Threshold.cxx | 8 +- .../entity_extraction/ThresholdPoints.cxx | 7 +- vtkm/filter/field_transform/GenerateIds.cxx | 4 +- vtkm/filter/vector_calculus/CrossProduct.cxx | 9 +- vtkm/filter/vector_calculus/DotProduct.cxx | 13 +- 22 files changed, 311 insertions(+), 142 deletions(-) create mode 100644 docs/changelog/create-result-does-field-map.md diff --git a/docs/changelog/create-result-does-field-map.md b/docs/changelog/create-result-does-field-map.md new file mode 100644 index 000000000..01e5b8453 --- /dev/null +++ b/docs/changelog/create-result-does-field-map.md @@ -0,0 +1,18 @@ +# Add `CreateResult` to `NewFilter` and absorb field mapping + +The original version of `Filter` classes had a helper header file named +`CreateResult.h` that had several forms of a `CreateResult` function that +helped correctly create the `DataSet` to be returned from a filter's +`DoExecute`. With the move to the `NewFilter` structure, these functions +did not line up very well with how `DataSet`s should actually be created. + +A replacement for these functions have been added as protected helper +methods to `NewFilter` and `NewFilterField`. In addition to moving them +into the filter themselves, the behavior of `CreateResult` has been merged +with the map field to output functionality. The original implementation of +`Filter` did this mapping internally in a different step. The first design +of `NewFilter` required the filter implementer to call a +`MapFieldsOntoOutput` themselves. This new implementation wraps the +functionality of `CreateResult` and `MapFieldsOntoOutput` together so that +the `DataSet` will be created correctly with a single call to +`CreateResult`. This makes it easier to correctly create the output. diff --git a/vtkm/cont/DataSet.h b/vtkm/cont/DataSet.h index a4e9295df..7dddff5b4 100644 --- a/vtkm/cont/DataSet.h +++ b/vtkm/cont/DataSet.h @@ -221,6 +221,14 @@ public: vtkm::cont::CoordinateSystem& GetCoordinateSystem(const std::string& name); //@} + /// Returns an `std::vector` of `CoordinateSystem`s held in this `DataSet`. + /// + VTKM_CONT + std::vector GetCoordinateSystems() const + { + return this->CoordSystems; + } + template VTKM_CONT void SetCellSet(const CellSetType& cellSet) { diff --git a/vtkm/filter/CreateResult.h b/vtkm/filter/CreateResult.h index 0e676a049..6060df28e 100644 --- a/vtkm/filter/CreateResult.h +++ b/vtkm/filter/CreateResult.h @@ -16,6 +16,9 @@ #include +// Once all the filters move to the NewFilter base classes, this header should +// be deprecated. + namespace vtkm { namespace filter diff --git a/vtkm/filter/NewFilter.cxx b/vtkm/filter/NewFilter.cxx index c893e28aa..b75fb7186 100644 --- a/vtkm/filter/NewFilter.cxx +++ b/vtkm/filter/NewFilter.cxx @@ -100,6 +100,17 @@ vtkm::cont::PartitionedDataSet NewFilter::Execute(const vtkm::cont::PartitionedD return output; } +vtkm::cont::DataSet NewFilter::CreateResult(const vtkm::cont::DataSet& inDataSet) const +{ + vtkm::cont::DataSet clone; + clone.CopyStructure(inDataSet); + this->MapFieldsOntoOutput( + inDataSet, clone, [](vtkm::cont::DataSet& out, const vtkm::cont::Field& fieldToPass) { + out.AddField(fieldToPass); + }); + return clone; +} + vtkm::Id NewFilter::DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input) { vtkm::Id numDS = input.GetNumberOfPartitions(); diff --git a/vtkm/filter/NewFilter.h b/vtkm/filter/NewFilter.h index 7589accb1..d031af733 100644 --- a/vtkm/filter/NewFilter.h +++ b/vtkm/filter/NewFilter.h @@ -128,17 +128,18 @@ namespace filter /// full control over the execution, including any mapping of fields to output (described in next /// sub-section). /// -/// \subsection FilterMappingFields MapFieldsOntoOutput +/// \subsection Creating results and mapping fields /// /// For subclasses that map input fields into output fields, the implementation of its -/// `DoExecute(DataSet&)` should call `NewFilter::MapFieldsOntoOutput` with a properly defined -/// `Mapper`, before returning the output DataSet. For example: +/// `DoExecute(DataSet&)` should create the `DataSet` to be returned with a call to +/// `NewFilter::CreateResult` or a similar method in a subclass (such as +/// `NewFilterField::CreateResultField`). /// /// \code{cpp} /// VTKM_CONT DataSet SomeFilter::DoExecute(const vtkm::cont::DataSet& input) /// { -/// vtkm::cont::DataSet output; -/// output = ... // Generation of the new DataSet +/// vtkm::cont::UnknownCellSet outCellSet; +/// outCellSet = ... // Generation of the new CellSet /// /// // Mapper is a callable object (function object, lambda, etc.) that takes an input Field /// // and maps it to an output Field and then add the output Field to the output DataSet @@ -146,18 +147,19 @@ namespace filter /// auto outputField = ... // Business logic for mapping input field to output field /// output.AddField(outputField); /// }; -/// this->MapFieldsOntoOutput(input, output, mapper); -/// -/// return output; +/// // This passes coordinate systems directly from input to output. If the points of +/// // the cell set change at all, they will have to be mapped by hand. +/// return this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper); /// } /// \endcode /// -/// `MapFieldsOntoOutput` iterates through each `FieldToPass` in the input DataSet and calls the -/// Mapper to map the input Field to output Field. For simple filters that just pass on input +/// In addition to creating a new `DataSet` filled with the proper cell structure and coordinate +/// systems, `CreateResult` iterates through each `FieldToPass` in the input DataSet and calls the +/// FieldMapper to map the input Field to output Field. For simple filters that just pass on input /// fields to the output DataSet without any computation, an overload of -/// `MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)` is also +/// `CreateResult(const vtkm::cont::DataSet& input)` is also /// provided as a convenience that uses the default mapper which trivially adds input Field to -/// output DaaSet (via a shallow copy). +/// output DataSet (via a shallow copy). /// /// \subsection FilterThreadSafety CanThread /// @@ -302,24 +304,115 @@ public: protected: vtkm::cont::Invoker Invoke; - template - VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, - vtkm::cont::DataSet& output, - Mapper&& mapper) + /// \brief Create the output data set for `DoExecute`. + /// + /// This form of `CreateResult` will create an output data set with the same cell + /// structure and coordinate system as the input and pass all fields (as requested + /// by the `Filter` state). + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed into + /// `DoExecute`). The returned `DataSet` is filled with the cell set, coordinate system, and + /// fields of `inDataSet` (as selected by the `FieldsToPass` state of the filter). + /// + VTKM_CONT vtkm::cont::DataSet CreateResult(const vtkm::cont::DataSet& inDataSet) const; + + /// \brief Create the output data set for `DoExecute`. + /// + /// This form of `CreateResult` will create an output data set with the given `CellSet`. You must + /// also provide a field mapper function, which is a function that takes the output `DataSet` + /// being created and a `Field` from the input and then applies any necessary transformations to + /// the field array and adds it to the `DataSet`. + /// + /// This form of `CreateResult` returns a `DataSet` with _no_ coordinate systems. The calling + /// program must add any necessary `CoordinateSystem`s. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultCellSet The `CellSet` of the output will be set to this. + /// \param[in] fieldMapper A function or functor that takes a `DataSet` as its first + /// argument and a `Field` as its second argument. The `DataSet` is the data being + /// created and will eventually be returned by `CreateResult`. The `Field` comes from + /// `inDataSet`. The function should map the `Field` to match `resultCellSet` and then + /// add the resulting field to the `DataSet`. If the mapping is not possible, then + /// the function should do nothing. + /// + template + VTKM_CONT vtkm::cont::DataSet CreateResult(const vtkm::cont::DataSet& inDataSet, + const vtkm::cont::UnknownCellSet& resultCellSet, + FieldMapper&& fieldMapper) const { - for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc) + vtkm::cont::DataSet outDataSet; + outDataSet.SetCellSet(resultCellSet); + this->MapFieldsOntoOutput(inDataSet, outDataSet, fieldMapper); + return outDataSet; + } + + /// \brief Create the output data set for `DoExecute`. + /// + /// This form of `CreateResult` will create an output data set with the given `CellSet` + /// and set of `CoordinateSystem`s. You must also provide a field mapper function, which + /// is a function that takes the output `DataSet` being created and a `Field` from the + /// input and then applies any necessary transformations to the field array and adds it + /// to the `DataSet`. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultCellSet The `CellSet` of the output will be set to this. + /// \param[in] resultCoordSystems These `CoordinateSystem`s will be added to the output. + /// \param[in] fieldMapper A function or functor that takes a `DataSet` as its first + /// argument and a `Field` as its second argument. The `DataSet` is the data being + /// created and will eventually be returned by `CreateResult`. The `Field` comes from + /// `inDataSet`. The function should map the `Field` to match `resultCellSet` and then + /// add the resulting field to the `DataSet`. If the mapping is not possible, then + /// the function should do nothing. + /// + template + VTKM_CONT vtkm::cont::DataSet CreateResult( + const vtkm::cont::DataSet& inDataSet, + const vtkm::cont::UnknownCellSet& resultCellSet, + const std::vector& resultCoordSystems, + FieldMapper&& fieldMapper) const + { + vtkm::cont::DataSet outDataSet = this->CreateResult(inDataSet, resultCellSet, fieldMapper); + for (auto&& cs : resultCoordSystems) { - auto field = input.GetField(cc); - if (this->GetFieldsToPass().IsFieldSelected(field)) - { - mapper(output, field); - } + outDataSet.AddCoordinateSystem(cs); } + return outDataSet; } - VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output) + /// \brief Create the output data set for `DoExecute`. + /// + /// This form of `CreateResult` will create an output data set with the given `CellSet` + /// and `CoordinateSystem`. You must also provide a field mapper function, which is a + /// function that takes the output `DataSet` being created and a `Field` from the input + /// and then applies any necessary transformations to the field array and adds it to + /// the `DataSet`. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultCellSet The `CellSet` of the output will be set to this. + /// \param[in] resultCoordSystem This `CoordinateSystem` will be added to the output. + /// \param[in] fieldMapper A function or functor that takes a `DataSet` as its first + /// argument and a `Field` as its second argument. The `DataSet` is the data being + /// created and will eventually be returned by `CreateResult`. The `Field` comes from + /// `inDataSet`. The function should map the `Field` to match `resultCellSet` and then + /// add the resulting field to the `DataSet`. If the mapping is not possible, then + /// the function should do nothing. + /// + template + VTKM_CONT vtkm::cont::DataSet CreateResult(const vtkm::cont::DataSet& inDataSet, + const vtkm::cont::UnknownCellSet& resultCellSet, + const vtkm::cont::CoordinateSystem& resultCoordSystem, + FieldMapper&& fieldMapper) const { - this->MapFieldsOntoOutput(input, output, defaultMapper); + return this->CreateResult(inDataSet, + resultCellSet, + std::vector{ resultCoordSystem }, + fieldMapper); } VTKM_CONT virtual vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) = 0; @@ -330,10 +423,20 @@ private: VTKM_CONT virtual vtkm::Id DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input); - static void defaultMapper(vtkm::cont::DataSet& output, const vtkm::cont::Field& field) + template + VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, + vtkm::cont::DataSet& output, + FieldMapper&& fieldMapper) const { - output.AddField(field); - }; + for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc) + { + auto field = input.GetField(cc); + if (this->GetFieldsToPass().IsFieldSelected(field)) + { + fieldMapper(output, field); + } + } + } vtkm::filter::FieldSelection FieldsToPass = vtkm::filter::FieldSelection::MODE_ALL; bool RunFilterWithMultipleThreads = false; diff --git a/vtkm/filter/NewFilterField.cxx b/vtkm/filter/NewFilterField.cxx index 81b83d73c..fd088664d 100644 --- a/vtkm/filter/NewFilterField.cxx +++ b/vtkm/filter/NewFilterField.cxx @@ -14,6 +14,16 @@ namespace vtkm namespace filter { +vtkm::cont::DataSet NewFilterField::CreateResultField(const vtkm::cont::DataSet& inDataSet, + const vtkm::cont::Field& resultField) const +{ + vtkm::cont::DataSet outDataSet = this->CreateResult(inDataSet); + outDataSet.AddField(resultField); + VTKM_ASSERT(!resultField.GetName().empty()); + VTKM_ASSERT(outDataSet.HasField(resultField.GetName(), resultField.GetAssociation())); + return outDataSet; +} + void NewFilterField::ResizeIfNeeded(size_t index_st) { if (this->ActiveFieldNames.size() <= index_st) diff --git a/vtkm/filter/NewFilterField.h b/vtkm/filter/NewFilterField.h index ac09f6e67..ef634c8f7 100644 --- a/vtkm/filter/NewFilterField.h +++ b/vtkm/filter/NewFilterField.h @@ -161,6 +161,7 @@ protected: field.GetData(), std::forward(functor), std::forward(args)...); } + private: template struct ScalarToVec @@ -190,6 +191,97 @@ protected: field.GetData(), std::forward(functor), std::forward(args)...); } + /// \brief Create the output data set for `DoExecute` + /// + /// This form of `CreateResult` will create an output data set with the same cell + /// structure and coordinate system as the input and pass all fields (as requested + /// by the `Filter` state). Additionally, it will add the provided field to the + /// result. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultField A `Field` that is added to the returned `DataSet`. + /// + VTKM_CONT vtkm::cont::DataSet CreateResultField(const vtkm::cont::DataSet& inDataSet, + const vtkm::cont::Field& resultField) const; + + /// \brief Create the output data set for `DoExecute` + /// + /// This form of `CreateResult` will create an output data set with the same cell + /// structure and coordinate system as the input and pass all fields (as requested + /// by the `Filter` state). Additionally, it will add a field matching the provided + /// specifications to the result. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultFieldName The name of the field added to the returned `DataSet`. + /// \param[in] resultFieldAssociation The association of the field (e.g. point or cell) + /// added to the returned `DataSet`. + /// \param[in] resultFieldArray An array containing the data for the field added to the + /// returned `DataSet`. + /// + VTKM_CONT vtkm::cont::DataSet CreateResultField( + const vtkm::cont::DataSet& inDataSet, + const std::string& resultFieldName, + vtkm::cont::Field::Association resultFieldAssociation, + const vtkm::cont::UnknownArrayHandle& resultFieldArray) const + { + return this->CreateResultField( + inDataSet, vtkm::cont::Field{ resultFieldName, resultFieldAssociation, resultFieldArray }); + } + + /// \brief Create the output data set for `DoExecute` + /// + /// This form of `CreateResult` will create an output data set with the same cell + /// structure and coordinate system as the input and pass all fields (as requested + /// by the `Filter` state). Additionally, it will add a point field matching the + /// provided specifications to the result. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultFieldName The name of the field added to the returned `DataSet`. + /// \param[in] resultFieldArray An array containing the data for the field added to the + /// returned `DataSet`. + /// + VTKM_CONT vtkm::cont::DataSet CreateResultFieldPoint( + const vtkm::cont::DataSet& inDataSet, + const std::string& resultFieldName, + const vtkm::cont::UnknownArrayHandle& resultFieldArray) const + { + return this->CreateResultField(inDataSet, + vtkm::cont::Field{ resultFieldName, + vtkm::cont::Field::Association::POINTS, + resultFieldArray }); + } + + /// \brief Create the output data set for `DoExecute` + /// + /// This form of `CreateResult` will create an output data set with the same cell + /// structure and coordinate system as the input and pass all fields (as requested + /// by the `Filter` state). Additionally, it will add a cell field matching the + /// provided specifications to the result. + /// + /// \param[in] inDataSet The input data set being modified (usually the one passed + /// into `DoExecute`). The returned `DataSet` is filled with fields of `inDataSet` + /// (as selected by the `FieldsToPass` state of the filter). + /// \param[in] resultFieldName The name of the field added to the returned `DataSet`. + /// \param[in] resultFieldArray An array containing the data for the field added to the + /// returned `DataSet`. + /// + VTKM_CONT vtkm::cont::DataSet CreateResultFieldCell( + const vtkm::cont::DataSet& inDataSet, + const std::string& resultFieldName, + const vtkm::cont::UnknownArrayHandle& resultFieldArray) const + { + return this->CreateResultField(inDataSet, + vtkm::cont::Field{ resultFieldName, + vtkm::cont::Field::Association::CELL_SET, + resultFieldArray }); + } + private: void ResizeIfNeeded(size_t index_st); diff --git a/vtkm/filter/clean_grid/CleanGrid.cxx b/vtkm/filter/clean_grid/CleanGrid.cxx index 1dd3ebc07..ae42f1282 100644 --- a/vtkm/filter/clean_grid/CleanGrid.cxx +++ b/vtkm/filter/clean_grid/CleanGrid.cxx @@ -31,7 +31,7 @@ struct SharedStates } // New Filter Design: DoMapField is now a free function in an anonymous namespace. It should be -// considered as a convenience/extension to the lambda passed to the MapFieldsOntoOutput. +// considered as a convenience/extension to the lambda passed to CreateResult. // Being a free function discourages the developer to "pass" mutable states from DoExecute phase // to DoMapField phase via data member. However, there is nothing to prevent developer doing // stupid thing to circumvent the protection. One example here is that the developer could @@ -167,17 +167,18 @@ vtkm::cont::DataSet CleanGrid::GenerateOutput(const vtkm::cont::DataSet& inData, outputCellSet = worklets.CellCompactor.Run(outputCellSet); } - // Construct resulting data set with new cell sets - vtkm::cont::DataSet outData; - outData.SetCellSet(outputCellSet); - - // Pass the coordinate systems - for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex) - { - outData.AddCoordinateSystem(outputCoordinateSystems[coordSystemIndex]); - } - - return outData; + // New Filter Design: We pass the actions needed to be done as a lambda to the generic + // CreateResult method. CreateResult now acts as thrust::transform_if on the + // Fields. Shared mutable state is captured by the lambda. We could also put all the logic + // of field mapping in the lambda. However, it is cleaner to put it in the filter specific + // implementation of DoMapField which takes mutable state as an extra parameter. + // + // For filters that do not need to do interpolation for mapping fields, we provide an overload + // that does not take the extra arguments and just AddField. + auto mapper = [&, this](auto& outDataSet, const auto& f) { + DoMapField(outDataSet, f, *this, worklets); + }; + return this->CreateResult(inData, outputCellSet, outputCoordinateSystems, mapper); } vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::DataSet& inData) @@ -221,22 +222,7 @@ vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::DataSet& inData) // New Filter Design: The share, mutable state is pass to other methods via parameter, not as // a data member. - auto outData = this->GenerateOutput(inData, outputCellSet, worklets); - - // New Filter Design: We pass the actions needed to be done as a lambda to the generic - // MapFieldsOntoOutput method. MapFieldsOntoOutput now acts as thrust::transform_if on the - // Fields. Shared mutable state is captured by the lambda. We could also put all the logic - // of field mapping in the lambda. However, it is cleaner to put it in the filter specific - // implementation of DoMapField which takes mutable state as an extra parameter. - // - // For filters that do not need to do interpolation for mapping fields, we provide an overload - // that does not take the extra arguments and just AddField. - auto mapper = [&, this](auto& outDataSet, const auto& f) { - DoMapField(outDataSet, f, *this, worklets); - }; - this->MapFieldsOntoOutput(inData, outData, mapper); - - return outData; + return this->GenerateOutput(inData, outputCellSet, worklets); } } //namespace clean_grid } //namespace filter diff --git a/vtkm/filter/connected_components/CellSetConnectivity.cxx b/vtkm/filter/connected_components/CellSetConnectivity.cxx index 0b7e02b14..363b8f31f 100644 --- a/vtkm/filter/connected_components/CellSetConnectivity.cxx +++ b/vtkm/filter/connected_components/CellSetConnectivity.cxx @@ -24,10 +24,7 @@ VTKM_CONT vtkm::cont::DataSet CellSetConnectivity::DoExecute(const vtkm::cont::D vtkm::worklet::connectivity::CellSetConnectivity().Run(input.GetCellSet(), component); - auto output = CreateResultFieldCell(input, component, this->GetOutputFieldName()); - this->MapFieldsOntoOutput(input, output); - - return output; + return this->CreateResultFieldCell(input, this->GetOutputFieldName(), component); } } // namespace connected_components } // namespace filter diff --git a/vtkm/filter/connected_components/ImageConnectivity.cxx b/vtkm/filter/connected_components/ImageConnectivity.cxx index 23a8674f5..7706e5ccd 100644 --- a/vtkm/filter/connected_components/ImageConnectivity.cxx +++ b/vtkm/filter/connected_components/ImageConnectivity.cxx @@ -35,10 +35,7 @@ VTKM_CONT vtkm::cont::DataSet ImageConnectivity::DoExecute(const vtkm::cont::Dat const auto& fieldArray = field.GetData(); this->CastAndCallScalarField(fieldArray, resolveType); - auto output = CreateResultFieldPoint(input, component, this->GetOutputFieldName()); - this->MapFieldsOntoOutput(input, output); - - return output; + return this->CreateResultFieldPoint(input, this->GetOutputFieldName(), component); } } // namespace connected_components } // namespace filter diff --git a/vtkm/filter/entity_extraction/ExternalFaces.cxx b/vtkm/filter/entity_extraction/ExternalFaces.cxx index 1fb314fdc..b52bd9a76 100644 --- a/vtkm/filter/entity_extraction/ExternalFaces.cxx +++ b/vtkm/filter/entity_extraction/ExternalFaces.cxx @@ -56,11 +56,11 @@ vtkm::cont::DataSet ExternalFaces::GenerateOutput(const vtkm::cont::DataSet& inp } //4. create the output dataset - vtkm::cont::DataSet output; - output.SetCellSet(outCellSet); - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - - return output; + auto mapper = [&, this](auto& result, const auto& f) { + // New Design: We are still using the old MapFieldOntoOutput to demonstrate the transition + this->MapFieldOntoOutput(result, f); + }; + return this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper); } //----------------------------------------------------------------------------- @@ -87,11 +87,6 @@ vtkm::cont::DataSet ExternalFaces::DoExecute(const vtkm::cont::DataSet& input) // New Filter Design: we generate new output and map the fields first. auto output = this->GenerateOutput(input, outCellSet); - auto mapper = [&, this](auto& result, const auto& f) { - // New Design: We are still using the old MapFieldOntoOutput to demonstrate the transition - this->MapFieldOntoOutput(result, f); - }; - this->MapFieldsOntoOutput(input, output, mapper); // New Filter Design: then we remove entities if requested. if (this->CompactPoints) diff --git a/vtkm/filter/entity_extraction/ExtractGeometry.cxx b/vtkm/filter/entity_extraction/ExtractGeometry.cxx index 187836a1e..9f20297cb 100644 --- a/vtkm/filter/entity_extraction/ExtractGeometry.cxx +++ b/vtkm/filter/entity_extraction/ExtractGeometry.cxx @@ -107,14 +107,8 @@ vtkm::cont::DataSet ExtractGeometry::DoExecute(const vtkm::cont::DataSet& input) cells.CastAndCallForTypes(worker); // create the output dataset - vtkm::cont::DataSet output; - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - output.SetCellSet(outCells); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); }; - this->MapFieldsOntoOutput(input, output, mapper); - - return output; + return this->CreateResult(input, outCells, input.GetCoordinateSystems(), mapper); } } // namespace entity_extraction diff --git a/vtkm/filter/entity_extraction/ExtractPoints.cxx b/vtkm/filter/entity_extraction/ExtractPoints.cxx index fd53ede8e..3699ea929 100644 --- a/vtkm/filter/entity_extraction/ExtractPoints.cxx +++ b/vtkm/filter/entity_extraction/ExtractPoints.cxx @@ -59,12 +59,9 @@ vtkm::cont::DataSet ExtractPoints::DoExecute(const vtkm::cont::DataSet& input) outCellSet = worklet.Run(cells, coords.GetData(), this->Function, this->ExtractInside); // create the output dataset - vtkm::cont::DataSet output; - output.SetCellSet(outCellSet); - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f); }; - this->MapFieldsOntoOutput(input, output, mapper); + vtkm::cont::DataSet output = + this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper); // compact the unused points in the output dataset if (this->CompactPoints) diff --git a/vtkm/filter/entity_extraction/ExtractStructured.cxx b/vtkm/filter/entity_extraction/ExtractStructured.cxx index 257da786a..9e7fd93f9 100644 --- a/vtkm/filter/entity_extraction/ExtractStructured.cxx +++ b/vtkm/filter/entity_extraction/ExtractStructured.cxx @@ -62,10 +62,6 @@ vtkm::cont::DataSet ExtractStructured::DoExecute(const vtkm::cont::DataSet& inpu auto coords = worklet.MapCoordinates(coordinates); vtkm::cont::CoordinateSystem outputCoordinates(coordinates.GetName(), coords); - vtkm::cont::DataSet output; - output.SetCellSet(vtkm::cont::UnknownCellSet(cellset)); - output.AddCoordinateSystem(outputCoordinates); - // Create map arrays for mapping fields. Could potentially save some time to first check to see // if these arrays would be used. auto CellFieldMap = @@ -76,9 +72,7 @@ vtkm::cont::DataSet ExtractStructured::DoExecute(const vtkm::cont::DataSet& inpu auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, CellFieldMap, PointFieldMap); }; - this->MapFieldsOntoOutput(input, output, mapper); - - return output; + return this->CreateResult(input, cellset, outputCoordinates, mapper); } } // namespace entity_extraction diff --git a/vtkm/filter/entity_extraction/GhostCellRemove.cxx b/vtkm/filter/entity_extraction/GhostCellRemove.cxx index 31b48b02b..b5bb4f326 100644 --- a/vtkm/filter/entity_extraction/GhostCellRemove.cxx +++ b/vtkm/filter/entity_extraction/GhostCellRemove.cxx @@ -368,14 +368,8 @@ VTKM_CONT vtkm::cont::DataSet GhostCellRemove::DoExecute(const vtkm::cont::DataS throw vtkm::cont::ErrorFilterExecution("Unsupported ghost cell removal type"); } - vtkm::cont::DataSet output; - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - output.SetCellSet(cellOut); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); }; - this->MapFieldsOntoOutput(input, output, mapper); - - return output; + return this->CreateResult(input, cellOut, input.GetCoordinateSystems(), mapper); } } diff --git a/vtkm/filter/entity_extraction/Mask.cxx b/vtkm/filter/entity_extraction/Mask.cxx index bbd74b27e..cfa9c2b23 100644 --- a/vtkm/filter/entity_extraction/Mask.cxx +++ b/vtkm/filter/entity_extraction/Mask.cxx @@ -70,14 +70,8 @@ VTKM_CONT vtkm::cont::DataSet Mask::DoExecute(const vtkm::cont::DataSet& input) cells.CastAndCallForTypes(workletCaller); // create the output dataset - vtkm::cont::DataSet output; - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - output.SetCellSet(cellOut); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); }; - this->MapFieldsOntoOutput(input, output, mapper); - - return output; + return this->CreateResult(input, cellOut, input.GetCoordinateSystems(), mapper); } } // namespace entity_extraction } // namespace filter diff --git a/vtkm/filter/entity_extraction/MaskPoints.cxx b/vtkm/filter/entity_extraction/MaskPoints.cxx index 20064efa3..a091362fe 100644 --- a/vtkm/filter/entity_extraction/MaskPoints.cxx +++ b/vtkm/filter/entity_extraction/MaskPoints.cxx @@ -55,12 +55,9 @@ VTKM_CONT vtkm::cont::DataSet MaskPoints::DoExecute(const vtkm::cont::DataSet& i outCellSet = worklet.Run(cells, this->Stride); // create the output dataset - vtkm::cont::DataSet output; - output.SetCellSet(outCellSet); - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f); }; - this->MapFieldsOntoOutput(input, output, mapper); + vtkm::cont::DataSet output = + this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper); // compact the unused points in the output dataset if (this->CompactPoints) diff --git a/vtkm/filter/entity_extraction/Threshold.cxx b/vtkm/filter/entity_extraction/Threshold.cxx index 7dbd1b7cd..26113340a 100644 --- a/vtkm/filter/entity_extraction/Threshold.cxx +++ b/vtkm/filter/entity_extraction/Threshold.cxx @@ -98,14 +98,8 @@ vtkm::cont::DataSet Threshold::DoExecute(const vtkm::cont::DataSet& input) fieldArray.CastAndCallForTypes( ResolveArrayType); - vtkm::cont::DataSet output; - output.SetCellSet(cellOut); - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); }; - this->MapFieldsOntoOutput(input, output, mapper); - - return output; + return this->CreateResult(input, cellOut, input.GetCoordinateSystems(), mapper); } } // namespace entity_extraction } // namespace filter diff --git a/vtkm/filter/entity_extraction/ThresholdPoints.cxx b/vtkm/filter/entity_extraction/ThresholdPoints.cxx index f04b40f3e..9fcc43c5d 100644 --- a/vtkm/filter/entity_extraction/ThresholdPoints.cxx +++ b/vtkm/filter/entity_extraction/ThresholdPoints.cxx @@ -173,12 +173,9 @@ VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(const vtkm::cont::DataS this->CastAndCallScalarField(field, resolveType); // create the output dataset - vtkm::cont::DataSet output; - output.SetCellSet(outCellSet); - output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f); }; - this->MapFieldsOntoOutput(input, output, mapper); + vtkm::cont::DataSet output = + this->CreateResult(input, outCellSet, input.GetCoordinateSystems(), mapper); // compact the unused points in the output dataset if (this->CompactPoints) diff --git a/vtkm/filter/field_transform/GenerateIds.cxx b/vtkm/filter/field_transform/GenerateIds.cxx index 21e9566da..754840bf3 100644 --- a/vtkm/filter/field_transform/GenerateIds.cxx +++ b/vtkm/filter/field_transform/GenerateIds.cxx @@ -43,7 +43,7 @@ namespace field_transform { vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input) { - vtkm::cont::DataSet output = input; + vtkm::cont::DataSet output = this->CreateResult(input); if (this->GetGeneratePointIds()) { @@ -56,8 +56,6 @@ vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input) output.AddCellField(this->GetCellFieldName(), GenerateArray(*this, input.GetNumberOfCells())); } - this->MapFieldsOntoOutput(input, output); - return output; } } // namespace field_transform diff --git a/vtkm/filter/vector_calculus/CrossProduct.cxx b/vtkm/filter/vector_calculus/CrossProduct.cxx index cb66d65d6..2b13918cc 100644 --- a/vtkm/filter/vector_calculus/CrossProduct.cxx +++ b/vtkm/filter/vector_calculus/CrossProduct.cxx @@ -77,13 +77,8 @@ VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(const vtkm::cont::DataSet& this->CastAndCallVecField<3>(primaryArray, resolveType); - vtkm::cont::DataSet outDataSet; - outDataSet.CopyStructure(inDataSet); - outDataSet.AddField({ this->GetOutputFieldName(), primaryField.GetAssociation(), outArray }); - - this->MapFieldsOntoOutput(inDataSet, outDataSet); - - return outDataSet; + return this->CreateResultField( + inDataSet, this->GetOutputFieldName(), primaryField.GetAssociation(), outArray); } } diff --git a/vtkm/filter/vector_calculus/DotProduct.cxx b/vtkm/filter/vector_calculus/DotProduct.cxx index 72329c3a8..3ac001ac3 100644 --- a/vtkm/filter/vector_calculus/DotProduct.cxx +++ b/vtkm/filter/vector_calculus/DotProduct.cxx @@ -108,15 +108,10 @@ VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& i DoDotProduct(primaryArray.ExtractArrayFromComponents(), secondaryField); } - vtkm::cont::DataSet outDataSet; - outDataSet.CopyStructure(inDataSet); - outDataSet.AddField({ this->GetOutputFieldName(), - this->GetFieldFromDataSet(inDataSet).GetAssociation(), - outArray }); - - this->MapFieldsOntoOutput(inDataSet, outDataSet); - - return outDataSet; + return this->CreateResultField(inDataSet, + this->GetOutputFieldName(), + this->GetFieldFromDataSet(inDataSet).GetAssociation(), + outArray); } } // namespace vector_calculus -- GitLab