From 2e88f4220a4b9cd86cb191fa1b200722e586c9a2 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Fri, 22 Dec 2017 10:31:02 -0700 Subject: [PATCH 01/70] Connected component for triangle mesh --- examples/CMakeLists.txt | 1 + examples/connected_component_labeling/CCL.cpp | 153 ++++++++++++ .../CMakeLists.txt | 7 + examples/game_of_life/CMakeLists.txt | 2 +- examples/isosurface/IsosurfaceUniformGrid.cxx | 4 +- .../internal/DeviceAdapterAlgorithmGeneral.h | 22 ++ vtkm/cont/internal/FunctorsGeneral.h | 31 +++ .../worklet/connectivities/CellSetDualGraph.h | 218 ++++++++++++++++++ .../connectivities/GraphConnectivity.h | 145 ++++++++++++ vtkm/worklet/connectivities/InnerJoin.h | 105 +++++++++ vtkm/worklet/testing/CMakeLists.txt | 95 ++++---- vtkm/worklet/testing/UnitTestDualGraph.cxx | 217 +++++++++++++++++ .../testing/UnitTestGraphConnectivity.cpp | 209 +++++++++++++++++ vtkm/worklet/testing/UnitTestInnerJoin.cxx | 53 +++++ 14 files changed, 1213 insertions(+), 49 deletions(-) create mode 100644 examples/connected_component_labeling/CCL.cpp create mode 100644 examples/connected_component_labeling/CMakeLists.txt create mode 100644 vtkm/worklet/connectivities/CellSetDualGraph.h create mode 100644 vtkm/worklet/connectivities/GraphConnectivity.h create mode 100644 vtkm/worklet/connectivities/InnerJoin.h create mode 100644 vtkm/worklet/testing/UnitTestDualGraph.cxx create mode 100644 vtkm/worklet/testing/UnitTestGraphConnectivity.cpp create mode 100644 vtkm/worklet/testing/UnitTestInnerJoin.cxx diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d18cd770a..d871ee791 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -25,6 +25,7 @@ set(CMAKE_PREFIX_PATH ${VTKm_BINARY_DIR}/${VTKm_INSTALL_CONFIG_DIR}) add_subdirectory(clipping) add_subdirectory(contour_tree) +add_subdirectory(connected_component_labeling) add_subdirectory(cosmotools) add_subdirectory(demo) add_subdirectory(dynamic_dispatcher) diff --git a/examples/connected_component_labeling/CCL.cpp b/examples/connected_component_labeling/CCL.cpp new file mode 100644 index 000000000..367713acb --- /dev/null +++ b/examples/connected_component_labeling/CCL.cpp @@ -0,0 +1,153 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +//#include +#include +//#include +#include + +void populate(std::vector& pixels, + std::vector& components, + vtkm::UInt32 width, + vtkm::UInt32 height) +{ + for (auto& pixel : pixels) { + pixel = 0.0f; + } + + for (int i = 6; i <= 8; i++) { + pixels[i] = 1.0f; + } + + for (int i = 16; i <= 18; i++) { + pixels[i] = 1.0f; + } + + for (int i = 0; i < width*height; ++i) { + components[i] = i; + } +} + +struct UpdateComponent : public vtkm::worklet::WorkletPointNeighborhood3x3x3 +{ + typedef void ControlSignature(FieldInNeighborhood pixel, + CellSetIn, + FieldInNeighborhood prevComponent, + FieldOut component); + + typedef void ExecutionSignature(_1, _3, _4); + + //verify input domain can be something other than first parameter + typedef _2 InputDomain; + + template + VTKM_EXEC void operator()(const vtkm::exec::arg::Neighborhood<1, FieldIn>& pixel, + const vtkm::exec::arg::Neighborhood<1, FieldIn1>& prevComponent, + FieldOut& component) const + //FieldIn1& component) const + { + //vtkm::UInt8 color = + std::cout << "pixel: " << pixel.Get(0, 0, 0) + << ", component: " << prevComponent.Get(0, 0, 0) + << std::endl; + + vtkm::Float32 color = pixel.Get(0, 0, 0); + if (color == pixel.Get(-1, 0, 0)) { + component = prevComponent.Get(-1, 0, 0); + } else if (color == pixel.Get(0, -1, 0)) { + component = prevComponent.Get(0, -1, 0); + } else { + component = prevComponent.Get(0, 0, 0); + } + } +}; + +struct FindRoot : public vtkm::worklet::WorkletMapField +{ + typedef void ControlSignature(FieldIn, + WholeArrayInOut component); + typedef void ExecutionSignature(_1, _2); + typedef _1 Inputdomain; + + template + VTKM_EXEC void operator()(const FieldIn& id, FieldOut& component) const { + //while (id != component.Get(id)) { +// if (id != component.Get(id)) { +// std::cout << "id: " << id << ", component: " << component.Get(id) << std::endl; +// component.Set(id, this->operator()(component.Get(id), component)); +// } + vtkm::Id parent = component.Get(id); + while (parent != component.Get(parent)) { + parent = component.Get(parent); + component.Set(id, parent); + + std::cout << "id: " << id << ", component: " << component.Get(id) << std::endl; + } + }; +}; + +int main(int argc, char *argv[]) +{ + vtkm::cont::DataSetBuilderUniform builder; + vtkm::cont::DataSet data = builder.Create(vtkm::Id2(5, 5)); + std::vector pixels(5*5); + std::vector components(5*5); + populate(pixels, components, 5, 5); + vtkm::cont::Field pixelField("pixels", vtkm::cont::Field::ASSOC_POINTS, pixels); + data.AddField(pixelField); + + vtkm::cont::Field componentField("components", vtkm::cont::Field::ASSOC_POINTS, components); + data.AddField(componentField); + + vtkm::worklet::DispatcherPointNeighborhood dispatcher; + + vtkm::cont::ArrayHandle output; + dispatcher.Invoke(data.GetField("pixels"), + data.GetCellSet(), + data.GetField("components"), + output); + + for (int i = 0; i < output.GetNumberOfValues(); i++) { + std::cout << output.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + + vtkm::worklet::DispatcherMapField findRootDispatcher; + findRootDispatcher.Invoke(data.GetField("components"), output); + for (int i = 0; i < output.GetNumberOfValues(); i++) { + std::cout << output.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; +} \ No newline at end of file diff --git a/examples/connected_component_labeling/CMakeLists.txt b/examples/connected_component_labeling/CMakeLists.txt new file mode 100644 index 000000000..940653b0f --- /dev/null +++ b/examples/connected_component_labeling/CMakeLists.txt @@ -0,0 +1,7 @@ +find_package(VTKm REQUIRED QUIET + OPTIONAL_COMPONENTS Serial #CUDA TBB OpenGL GLUT + ) + +add_executable(CCL CCL.cpp) +target_link_libraries(CCL PRIVATE ${VTKm_LIBRARIES}) +target_compile_options(CCL PRIVATE ${VTKm_COMPILE_OPTIONS}) diff --git a/examples/game_of_life/CMakeLists.txt b/examples/game_of_life/CMakeLists.txt index 7b67e0e5c..5389e12dc 100644 --- a/examples/game_of_life/CMakeLists.txt +++ b/examples/game_of_life/CMakeLists.txt @@ -20,7 +20,7 @@ ## ##============================================================================= -cmake_minimum_required(VERSION 3.8 FATAL_ERROR) +#cmake_minimum_required(VERSION 3.8 FATAL_ERROR) project(GameOfLife CXX) #Find the VTK-m package diff --git a/examples/isosurface/IsosurfaceUniformGrid.cxx b/examples/isosurface/IsosurfaceUniformGrid.cxx index 0c0842c59..57fff6769 100644 --- a/examples/isosurface/IsosurfaceUniformGrid.cxx +++ b/examples/isosurface/IsosurfaceUniformGrid.cxx @@ -48,7 +48,7 @@ #include -static vtkm::Id3 dims(256, 256, 256); +static vtkm::Id3 dims(4, 4, 4); static vtkm::cont::ArrayHandle> verticesArray, normalsArray; static vtkm::cont::ArrayHandle scalarsArray; static Quaternion qrot; @@ -245,7 +245,7 @@ int main(int argc, char* argv[]) vtkm::filter::MarchingCubes filter; filter.SetGenerateNormals(true); filter.SetMergeDuplicatePoints(false); - filter.SetIsoValue(0, 0.5); + filter.SetIsoValue(0, 0.1); vtkm::filter::Result result = filter.Execute(dataSet, dataSet.GetField("nodevar")); filter.MapFieldOntoOutput(result, dataSet.GetField("nodevar")); diff --git a/vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h b/vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h index f477c34fa..2a8eac79e 100644 --- a/vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h +++ b/vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h @@ -763,6 +763,28 @@ public: DerivedAlgorithm::Sort(zipHandle, internal::KeyCompare(binary_compare)); } + template + VTKM_CONT static void Transform(vtkm::cont::ArrayHandle& input1, + vtkm::cont::ArrayHandle& input2, + vtkm::cont::ArrayHandle& output, + BinaryFunctor binaryFunctor) + { + vtkm::Id numValues = vtkm::Min(input1.GetNumberOfValues(), input2.GetNumberOfValues()); + if (numValues <= 0) + { + return; + } + + auto input1Portal = input1.PrepareForInput(DeviceAdapterTag()); + auto input2Portal = input2.PrepareForInput(DeviceAdapterTag()); + auto outputPortal = output.PrepareForOutput(numValues, DeviceAdapterTag()); + + BinaryTransformKernel + binaryKernel(input1Portal, input2Portal, outputPortal, binaryFunctor); + DerivedAlgorithm::Schedule(binaryKernel, numValues); + } + + //}; //-------------------------------------------------------------------------- // Unique template diff --git a/vtkm/cont/internal/FunctorsGeneral.h b/vtkm/cont/internal/FunctorsGeneral.h index 008e0db9c..916dfc563 100644 --- a/vtkm/cont/internal/FunctorsGeneral.h +++ b/vtkm/cont/internal/FunctorsGeneral.h @@ -881,6 +881,37 @@ struct ScanKernel : vtkm::exec::FunctorBase } } }; + +template +struct BinaryTransformKernel : vtkm::exec::FunctorBase +{ + using ValueType = typename InPortalType::ValueType; + + InPortalType InPortal1; + InPortalType InPortal2; + OutPortalType OutPortal; + BinaryFunctor BinaryOperator; + + VTKM_CONT + BinaryTransformKernel(const InPortalType& inPortal1, + const InPortalType& inPortal2, + const OutPortalType& outPortal, + BinaryFunctor binaryOperator) + : InPortal1(inPortal1) + , InPortal2(inPortal2) + , OutPortal(outPortal) + , BinaryOperator(binaryOperator) + { + } + + VTKM_SUPPRESS_EXEC_WARNINGS + VTKM_EXEC + void operator()(vtkm::Id index) const + { + this->OutPortal.Set( + index, this->BinaryOperator(this->InPortal1.Get(index), this->InPortal2.Get(index))); + } +}; } } } // namespace vtkm::cont::internal diff --git a/vtkm/worklet/connectivities/CellSetDualGraph.h b/vtkm/worklet/connectivities/CellSetDualGraph.h new file mode 100644 index 000000000..b4b417eff --- /dev/null +++ b/vtkm/worklet/connectivities/CellSetDualGraph.h @@ -0,0 +1,218 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ + +#ifndef vtk_m_worklet_CellSetDualGraph_h +#define vtk_m_worklet_CellSetDualGraph_h + +#include + +struct EdgeCount : public vtkm::worklet::WorkletMapPointToCell +{ + typedef void ControlSignature(CellSetIn, FieldOutCell<> numEdgesInCell); + typedef _2 ExecutionSignature(CellShape, PointCount); + using InputDomain = _1; + + template + VTKM_EXEC vtkm::IdComponent operator()(CellShapeTag cellShape, vtkm::IdComponent pointCount) const + { + return vtkm::exec::CellEdgeNumberOfEdges(pointCount, cellShape, *this); + } +}; + +struct EdgeExtract : public vtkm::worklet::WorkletMapPointToCell +{ + typedef void ControlSignature(CellSetIn, FieldOutCell<> cellIndices, FieldOutCell<> edgeIndices); + + typedef void ExecutionSignature(CellShape, InputIndex, PointIndices, VisitIndex, _2, _3); + using InputDomain = _1; + + using ScatterType = vtkm::worklet::ScatterCounting; + VTKM_CONT ScatterType GetScatter() const { return this->Scatter; } + + VTKM_CONT EdgeExtract(const ScatterType& scatter) + : Scatter(scatter) + { + } + + template + VTKM_EXEC void operator()(CellShapeTag cellShape, + CellIndexType cellIndex, + PointIndexVecType& pointIndices, + vtkm::IdComponent visitIndex, + CellIndexType& cellIndexOut, + EdgeIndexVecType& edgeIndices) const + { + cellIndexOut = cellIndex; + edgeIndices = vtkm::exec::CellEdgeCanonicalId( + pointIndices.GetNumberOfComponents(), visitIndex, cellShape, pointIndices, *this); + }; + +private: + ScatterType Scatter; +}; + +struct CellToCellConnectivity : public vtkm::worklet::WorkletMapField +{ + typedef void ControlSignature(FieldIn<> index, + WholeArrayIn<> cells, + WholeArrayOut<> from, + WholeArrayOut<> to); + + typedef void ExecutionSignature(_1, InputIndex, _2, _3, _4); + using InputDomain = _1; + + template + VTKM_EXEC void operator()(vtkm::Id offset, + vtkm::Id index, + const CellIdPortalType& cells, + ConnectivityPortalType& from, + ConnectivityPortalType& to) const + { + from.Set(index * 2, cells.Get(offset)); + to.Set(index * 2, cells.Get(offset + 1)); + from.Set(index * 2 + 1, cells.Get(offset + 1)); + to.Set(index * 2 + 1, cells.Get(offset)); + } +}; + +template +class CellSetDualGraph +{ +public: + using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + + struct degree2 + { + VTKM_EXEC + bool operator()(vtkm::Id degree) const { return degree == 2; } + }; + + template + void EdgeToCellConnectivity(const vtkm::cont::CellSetSingleType& cellSet, + vtkm::cont::ArrayHandle& cellIds, + vtkm::cont::ArrayHandle& cellEdges) const + { + // Get number of edges for each cell and use it as scatter count. + vtkm::cont::ArrayHandle numEdgesPerCell; + vtkm::worklet::DispatcherMapTopology edgesPerCellDisp; + edgesPerCellDisp.Invoke(cellSet, numEdgesPerCell); + + // Get uncompress Cell to Edge mapping + vtkm::worklet::ScatterCounting scatter{ numEdgesPerCell, DeviceAdapter() }; + vtkm::worklet::DispatcherMapTopology edgeExtractDisp{ scatter }; + edgeExtractDisp.Invoke(cellSet, cellIds, cellEdges); + } + + template + void Run(vtkm::cont::CellSetSingleType& cellSet, + vtkm::cont::ArrayHandle& numIndicesArray, + vtkm::cont::ArrayHandle& indexOffsetArray, + vtkm::cont::ArrayHandle& connectivityArray) const + { + // calculate the uncompressed Edge to Cell connectivity from Point to Cell connectivity + // in the CellSet + vtkm::cont::ArrayHandle cellIds; + vtkm::cont::ArrayHandle cellEdges; + EdgeToCellConnectivity(cellSet, cellIds, cellEdges); + // for (int i = 0; i < cellIds.GetNumberOfValues(); i++) { + // std::cout << cellIds.GetPortalConstControl().Get(i) << " " + // << cellEdges.GetPortalConstControl().Get(i) << std::endl; + // } + + // sort cell ids by cell edges, this groups cells by cell edges + Algorithm::SortByKey(cellEdges, cellIds); + // for (int i = 0; i < cellIds.GetNumberOfValues(); i++) { + // std::cout << cellEdges.GetPortalConstControl().Get(i) << " " + // << cellIds.GetPortalConstControl().Get(i) << std::endl; + // } + + // count how many times an edge is shared by cells. + vtkm::cont::ArrayHandle uniqueEdges; + vtkm::cont::ArrayHandle uniqueEdgeDegree; + Algorithm::ReduceByKey( + cellEdges, + vtkm::cont::ArrayHandleConstant(1, cellEdges.GetNumberOfValues()), + uniqueEdges, + uniqueEdgeDegree, + vtkm::Add()); + // for (int i = 0; i < uniqueEdges.GetNumberOfValues(); i++) { + // std::cout << uniqueEdges.GetPortalConstControl().Get(i) << " " + // << uniqueEdgeDegree.GetPortalConstControl().Get(i) << std::endl; + // } + + // Extract edges shared by two cells + vtkm::cont::ArrayHandle sharedEdges; + Algorithm::CopyIf(uniqueEdges, uniqueEdgeDegree, sharedEdges, degree2()); + // for (int i = 0; i < sharedEdges.GetNumberOfValues(); i++) { + // std::cout << "graph edge: " << sharedEdges.GetPortalConstControl().Get(i) + // << std::endl; + // } + + // find shared edges within all the edges. + vtkm::cont::ArrayHandle lb; + Algorithm::LowerBounds(cellEdges, sharedEdges, lb); + // for (int i = 0; i < lb.GetNumberOfValues(); i++) { + // std::cout << "lower bound: " << lb.GetPortalConstControl().Get(i) + // << std::endl; + // } + + // take each shared edge and the cells to create 2 edges of the dual graph + vtkm::cont::ArrayHandle connFrom; + vtkm::cont::ArrayHandle connTo; + connFrom.Allocate(sharedEdges.GetNumberOfValues() * 2); + connTo.Allocate(sharedEdges.GetNumberOfValues() * 2); + vtkm::worklet::DispatcherMapField c2cDisp; + c2cDisp.Invoke(lb, cellIds, connFrom, connTo); + + // for (int i = 0; i < connFrom.GetNumberOfValues(); i++) { + // std::cout << "from cell: " << connFrom.GetPortalConstControl().Get(i) + // << ", to cell: " << connTo.GetPortalConstControl().Get(i) + // << std::endl; + // } + + // Turn + Algorithm::SortByKey(connFrom, connTo); + // for (int i = 0; i < connFrom.GetNumberOfValues(); i++) { + // std::cout << "from cell: " << connFrom.GetPortalConstControl().Get(i) + // << ", to cell: " << connTo.GetPortalConstControl().Get(i) + // << std::endl; + // } + Algorithm::Copy(connTo, connectivityArray); + + vtkm::cont::ArrayHandle dualGraphVertices; + Algorithm::ReduceByKey( + connFrom, + vtkm::cont::ArrayHandleConstant(1, connFrom.GetNumberOfValues()), + dualGraphVertices, + numIndicesArray, + vtkm::Add()); + // for (int i = 0; i < dualGraphVertices.GetNumberOfValues(); i++) { + // std::cout << "dual graph vertex: " << dualGraphVertices.GetPortalConstControl().Get(i) + // << ", degree: " << numIndicesArray.GetPortalConstControl().Get(i) + // << std::endl; + // } + + Algorithm::ScanExclusive(numIndicesArray, indexOffsetArray); + } +}; +#endif //vtk_m_worklet_CellSetDualGraph_h diff --git a/vtkm/worklet/connectivities/GraphConnectivity.h b/vtkm/worklet/connectivities/GraphConnectivity.h new file mode 100644 index 000000000..d327dc2eb --- /dev/null +++ b/vtkm/worklet/connectivities/GraphConnectivity.h @@ -0,0 +1,145 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ + +#ifndef vtk_m_worklet_connectivity_graph_connectivity_h +#define vtk_m_worklet_connectivity_graph_connectivity_h + +#include +#include + +class Graft : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn index, + FieldIn start, + FieldIn degree, + WholeArrayIn ids, + WholeArrayInOut comp); + + typedef void ExecutionSignature(_1, _2, _3, _4, _5); + typedef _1 InputDomain; + + // TODO: Use Scatter? + template + VTKM_EXEC void operator()(vtkm::Id index, + vtkm::Id start, + vtkm::Id degree, + const InPortalType& conn, + InOutPortalType& comp) const + { + for (vtkm::Id offset = start; offset < start + degree; offset++) + { + vtkm::Id neighbor = conn.Get(offset); + if ((comp.Get(index) == comp.Get(comp.Get(index))) && (comp.Get(neighbor) < comp.Get(index))) + { + comp.Set(comp.Get(index), comp.Get(neighbor)); + } + } + } +}; + +class PointerJumping : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn index, WholeArrayInOut comp); + typedef void ExecutionSignature(_1, _2); + typedef _1 InputDomain; + + template + VTKM_EXEC void operator()(vtkm::Id index, InOutPortalType& comp) const + { + while (comp.Get(comp.Get(index)) != comp.Get(index)) + comp.Set(index, comp.Get(comp.Get(index))); + + //vtkm::Id parent = comp.Get(index); + //comp.Set(index, comp.Get(comp.Get(index))); + }; +}; + +class IsStar : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn index, WholeArrayIn comp, FieldOut); + typedef _3 ExecutionSignature(_1, _2); + typedef _1 InputDomain; + + template + VTKM_EXEC bool operator()(vtkm::Id index, InOutPortalType& comp) const + { + return comp.Get(index) == comp.Get(comp.Get(index)); + } +}; + +template +class GraphConnectivity +{ +public: + using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + + template + void Run(const InputPortalType& numIndexArray, + const InputPortalType& indexOffsetArray, + const InputPortalType& connectivityArray, + OutputPortalType& componentsOut) const + { + using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + + bool allStar = false; + vtkm::cont::ArrayHandle components; + vtkm::cont::ArrayHandle isStar; + vtkm::cont::ArrayHandle cellIds; + Algorithm::Copy( + vtkm::cont::ArrayHandleCounting(0, 1, numIndexArray.GetNumberOfValues()), cellIds); + Algorithm::Copy(cellIds, components); + + do + { + vtkm::worklet::DispatcherMapField graftDispatcher; + graftDispatcher.Invoke( + cellIds, indexOffsetArray, numIndexArray, connectivityArray, components); + + // Detection of allStar has be come before pointer jumping. Don't try to rearrange it. + vtkm::worklet::DispatcherMapField isStarDisp; + isStarDisp.Invoke(cellIds, components, isStar); + allStar = Algorithm::Reduce(isStar, true, vtkm::LogicalAnd()); + + vtkm::worklet::DispatcherMapField pointJumpingDispatcher; + pointJumpingDispatcher.Invoke(cellIds, components); + } while (!allStar); + + // renumber connected component to the range of [0, number of components). + vtkm::cont::ArrayHandle uniqueComponents; + Algorithm::Copy(components, uniqueComponents); + Algorithm::Sort(uniqueComponents); + Algorithm::Unique(uniqueComponents); + + vtkm::cont::ArrayHandle uniqueColor; + Algorithm::Copy( + vtkm::cont::ArrayHandleCounting(0, 1, uniqueComponents.GetNumberOfValues()), + uniqueColor); + vtkm::cont::ArrayHandle cellColors; + vtkm::cont::ArrayHandle cellIdsOut; + InnerJoin().Run( + components, cellIds, uniqueComponents, uniqueColor, cellColors, cellIdsOut, componentsOut); + + Algorithm::SortByKey(cellIdsOut, componentsOut); + } +}; +#endif //vtk_m_worklet_connectivity_graph_connectivity_h diff --git a/vtkm/worklet/connectivities/InnerJoin.h b/vtkm/worklet/connectivities/InnerJoin.h new file mode 100644 index 000000000..4763c0937 --- /dev/null +++ b/vtkm/worklet/connectivities/InnerJoin.h @@ -0,0 +1,105 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ + +#ifndef vtk_m_worklet_InnerJoin_h +#define vtk_m_worklet_InnerJoin_h + + + +template +class InnerJoin +{ +public: + struct Merge : vtkm::worklet::WorkletMapField + { + typedef void ControlSignature(FieldIn, + FieldIn, + FieldIn, + WholeArrayIn, + FieldOut<>, + FieldOut<>, + FieldOut<>); + typedef void ExecutionSignature(_1, _2, _3, VisitIndex, _4, _5, _6, _7); + using InputDomain = _1; + + using ScatterType = vtkm::worklet::ScatterCounting; + + VTKM_CONT + ScatterType GetScatter() const { return this->Scatter; } + + VTKM_CONT + Merge(const ScatterType& scatter) + : Scatter(scatter) + { + } + + template + VTKM_EXEC void operator()(vtkm::Id key, + vtkm::Id value1, + vtkm::Id lowerBounds, + vtkm::Id visitIndex, + const InPortalType& value2, + vtkm::Id& keyOut, + vtkm::Id& value1Out, + vtkm::Id& value2Out) const + { + auto v2 = value2.Get(lowerBounds + visitIndex); + keyOut = key; + value1Out = value1; + value2Out = v2; + } + + private: + ScatterType Scatter; + }; + + using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + + // TODO: not mutating input keys and values? + template + void Run(vtkm::cont::ArrayHandle& key1, + vtkm::cont::ArrayHandle& value1, + vtkm::cont::ArrayHandle& key2, + vtkm::cont::ArrayHandle& value2, + vtkm::cont::ArrayHandle& keyOut, + vtkm::cont::ArrayHandle& value1Out, + vtkm::cont::ArrayHandle& value2Out) const + { + Algorithm::SortByKey(key1, value1); + Algorithm::SortByKey(key2, value2); + + vtkm::cont::ArrayHandle lbs; + vtkm::cont::ArrayHandle ubs; + Algorithm::LowerBounds(key2, key1, lbs); + Algorithm::UpperBounds(key2, key1, ubs); + + vtkm::cont::ArrayHandle counts; + Algorithm::Transform(ubs, lbs, counts, vtkm::Subtract()); + + vtkm::cont::ArrayHandle output_offset; + Algorithm::ScanExclusive(counts, output_offset); + + vtkm::worklet::ScatterCounting scatter{ counts, DeviceAdapter() }; + Merge merge(scatter); + vtkm::worklet::DispatcherMapField mergeDisp(merge); + mergeDisp.Invoke(key1, value1, lbs, value2, keyOut, value1Out, value2Out); + }; +}; +#endif //vtk_m_worklet_InnerJoin_h diff --git a/vtkm/worklet/testing/CMakeLists.txt b/vtkm/worklet/testing/CMakeLists.txt index 52d9a96dc..840abae2d 100644 --- a/vtkm/worklet/testing/CMakeLists.txt +++ b/vtkm/worklet/testing/CMakeLists.txt @@ -19,52 +19,55 @@ ##============================================================================ set(unit_tests - UnitTestAverageByKey.cxx - UnitTestCellAverage.cxx - UnitTestCellDeepCopy.cxx - UnitTestCellGradient.cxx - UnitTestClipping.cxx - UnitTestContourTreeUniform.cxx - UnitTestCosmoTools.cxx - UnitTestExternalFaces.cxx - UnitTestExtractGeometry.cxx - UnitTestExtractPoints.cxx - UnitTestExtractStructured.cxx - UnitTestFieldHistogram.cxx - UnitTestFieldStatistics.cxx - UnitTestKdTreeBuildNNS.cxx - UnitTestKeys.cxx - UnitTestMagnitude.cxx - UnitTestMarchingCubes.cxx - UnitTestMask.cxx - UnitTestMaskPoints.cxx - UnitTestNDimsEntropy.cxx - UnitTestNDimsHistogram.cxx - UnitTestNDimsHistMarginalization.cxx - UnitTestParticleAdvection.cxx - UnitTestPointElevation.cxx - UnitTestPointGradient.cxx - UnitTestRemoveUnusedPoints.cxx - UnitTestScatterCounting.cxx - UnitTestScatterPermutation.cxx - UnitTestSplatKernels.cxx - UnitTestStreamingSine.cxx - UnitTestStreamLineUniformGrid.cxx - UnitTestSurfaceNormals.cxx - UnitTestTetrahedralize.cxx - UnitTestThreshold.cxx - UnitTestThresholdPoints.cxx - UnitTestTriangulate.cxx - UnitTestWholeCellSetIn.cxx - UnitTestWorkletMapField.cxx - UnitTestWorkletMapFieldExecArg.cxx - UnitTestWorkletMapFieldWholeArray.cxx - UnitTestWorkletMapPointNeighborhood.cxx - UnitTestWorkletMapTopologyExplicit.cxx - UnitTestWorkletMapTopologyUniform.cxx - UnitTestWorkletReduceByKey.cxx - UnitTestVertexClustering.cxx - UnitTestWaveletCompressor.cxx +# UnitTestAverageByKey.cxx +# UnitTestCellAverage.cxx +# UnitTestCellDeepCopy.cxx +# UnitTestCellGradient.cxx +# UnitTestClipping.cxx +# UnitTestContourTreeUniform.cxx +# UnitTestCosmoTools.cxx + UnitTestDualGraph.cxx +# UnitTestExternalFaces.cxx +# UnitTestExtractGeometry.cxx +# UnitTestExtractPoints.cxx +# UnitTestExtractStructured.cxx +# UnitTestFieldHistogram.cxx +# UnitTestFieldStatistics.cxx + UnitTestGraphConnectivity.cpp + UnitTestInnerJoin.cxx +# UnitTestKdTreeBuildNNS.cxx +# UnitTestKeys.cxx +# UnitTestMagnitude.cxx +# UnitTestMarchingCubes.cxx +# UnitTestMask.cxx +# UnitTestMaskPoints.cxx +# UnitTestNDimsEntropy.cxx +# UnitTestNDimsHistogram.cxx +# UnitTestNDimsHistMarginalization.cxx +# UnitTestParticleAdvection.cxx +# UnitTestPointElevation.cxx +# UnitTestPointGradient.cxx +# UnitTestRemoveUnusedPoints.cxx +# UnitTestScatterCounting.cxx +# UnitTestScatterPermutation.cxx +# UnitTestSplatKernels.cxx +# UnitTestStreamingSine.cxx +# UnitTestStreamLineUniformGrid.cxx +# UnitTestSurfaceNormals.cxx +# UnitTestTetrahedralize.cxx +# UnitTestThreshold.cxx +# UnitTestThresholdPoints.cxx +# UnitTestTriangulate.cxx +# UnitTestWholeCellSetIn.cxx +# UnitTestWorkletMapField.cxx +# UnitTestWorkletMapFieldExecArg.cxx +# UnitTestWorkletMapFieldWholeArray.cxx +# UnitTestWorkletMapPointNeighborhood.cxx +# UnitTestWorkletMapTopologyExplicit.cxx +# UnitTestWorkletMapTopologyUniform.cxx +# UnitTestWorkletReduceByKey.cxx +# UnitTestVertexClustering.cxx +# UnitTestWaveletCompressor.cxx ) vtkm_save_worklet_unit_tests(${unit_tests}) diff --git a/vtkm/worklet/testing/UnitTestDualGraph.cxx b/vtkm/worklet/testing/UnitTestDualGraph.cxx new file mode 100644 index 000000000..f5c944dfb --- /dev/null +++ b/vtkm/worklet/testing/UnitTestDualGraph.cxx @@ -0,0 +1,217 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class TangleField : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn vertexId, FieldOut v); + typedef void ExecutionSignature(_1, _2); + typedef _1 InputDomain; + + const vtkm::Id xdim, ydim, zdim; + const vtkm::FloatDefault xmin, ymin, zmin, xmax, ymax, zmax; + const vtkm::Id cellsPerLayer; + + VTKM_CONT + TangleField(const vtkm::Id3 dims, + const vtkm::FloatDefault mins[3], + const vtkm::FloatDefault maxs[3]) + : xdim(dims[0]) + , ydim(dims[1]) + , zdim(dims[2]) + , xmin(mins[0]) + , ymin(mins[1]) + , zmin(mins[2]) + , xmax(maxs[0]) + , ymax(maxs[1]) + , zmax(maxs[2]) + , cellsPerLayer((xdim) * (ydim)) + { + } + + VTKM_EXEC + void operator()(const vtkm::Id& vertexId, vtkm::Float32& v) const + { + const vtkm::Id x = vertexId % (xdim); + const vtkm::Id y = (vertexId / (xdim)) % (ydim); + const vtkm::Id z = vertexId / cellsPerLayer; + + const vtkm::FloatDefault fx = + static_cast(x) / static_cast(xdim - 1); + const vtkm::FloatDefault fy = + static_cast(y) / static_cast(xdim - 1); + const vtkm::FloatDefault fz = + static_cast(z) / static_cast(xdim - 1); + + const vtkm::Float32 xx = 3.0f * vtkm::Float32(xmin + (xmax - xmin) * (fx)); + const vtkm::Float32 yy = 3.0f * vtkm::Float32(ymin + (ymax - ymin) * (fy)); + const vtkm::Float32 zz = 3.0f * vtkm::Float32(zmin + (zmax - zmin) * (fz)); + + v = (xx * xx * xx * xx - 5.0f * xx * xx + yy * yy * yy * yy - 5.0f * yy * yy + + zz * zz * zz * zz - 5.0f * zz * zz + 11.8f) * + 0.2f + + 0.5f; + } +}; + +vtkm::cont::DataSet MakeIsosurfaceTestDataSet(vtkm::Id3 dims) +{ + vtkm::cont::DataSet dataSet; + + const vtkm::Id3 vdims(dims[0] + 1, dims[1] + 1, dims[2] + 1); + + vtkm::FloatDefault mins[3] = { -1.0f, -1.0f, -1.0f }; + vtkm::FloatDefault maxs[3] = { 1.0f, 1.0f, 1.0f }; + + vtkm::cont::ArrayHandle pointFieldArray; + vtkm::cont::ArrayHandleIndex vertexCountImplicitArray(vdims[0] * vdims[1] * vdims[2]); + vtkm::worklet::DispatcherMapField tangleFieldDispatcher( + TangleField(vdims, mins, maxs)); + tangleFieldDispatcher.Invoke(vertexCountImplicitArray, pointFieldArray); + + vtkm::Id numCells = dims[0] * dims[1] * dims[2]; + auto cellFieldArray = vtkm::cont::make_ArrayHandleCounting(0, 1, numCells); + + vtkm::Vec origin(0.0f, 0.0f, 0.0f); + vtkm::Vec spacing(1.0f / static_cast(dims[0]), + 1.0f / static_cast(dims[2]), + 1.0f / static_cast(dims[1])); + + vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(vdims, origin, spacing); + dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates)); + + static const vtkm::IdComponent ndim = 3; + vtkm::cont::CellSetStructured cellSet("cells"); + cellSet.SetPointDimensions(vdims); + dataSet.AddCellSet(cellSet); + + dataSet.AddField(vtkm::cont::Field("nodevar", vtkm::cont::Field::ASSOC_POINTS, pointFieldArray)); + dataSet.AddField( + vtkm::cont::Field("cellvar", vtkm::cont::Field::ASSOC_CELL_SET, "cells", cellFieldArray)); + + return dataSet; +} + + +template +class TestDualGraph +{ +public: + void TestTriangleMesh() const + { + // cell2vertices connectivityusing Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + //std::vector connectivity = {0, 2, 1, 1, 2, 4, 1, 4, 3, 2, 5, 4}; + std::vector connectivity = { 0, 2, 4, 1, 3, 5, 2, 6, 4, 5, 3, 7, 2, 9, 6, 4, 6, 8 }; + + vtkm::cont::CellSetSingleType<> cellSet; + cellSet.Fill(8, vtkm::CELL_SHAPE_TRIANGLE, 3, vtkm::cont::make_ArrayHandle(connectivity)); + + vtkm::cont::ArrayHandle numIndicesArray; + vtkm::cont::ArrayHandle indexOffsetArray; + vtkm::cont::ArrayHandle connectivityArray; + + CellSetDualGraph().Run( + cellSet, numIndicesArray, indexOffsetArray, connectivityArray); + std::cout << "numIndices: "; + for (int i = 0; i < numIndicesArray.GetNumberOfValues(); i++) + { + std::cout << numIndicesArray.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + + std::cout << "indexOffset: "; + for (int i = 0; i < indexOffsetArray.GetNumberOfValues(); i++) + { + std::cout << indexOffsetArray.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + + std::cout << "connectivity: "; + for (int i = 0; i < connectivityArray.GetNumberOfValues(); i++) + { + std::cout << connectivityArray.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + } + + void TestIsosurface() const + { + vtkm::Id3 dims(3, 3, 3); + vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims); + + vtkm::filter::MarchingCubes filter; + filter.SetGenerateNormals(true); + filter.SetMergeDuplicatePoints(true); + filter.SetIsoValue(0, 0.5); + vtkm::filter::Result result = filter.Execute(dataSet, dataSet.GetField("nodevar")); + vtkm::cont::DataSet& outputData = result.GetDataSet(); + + auto cellSet = outputData.GetCellSet().Cast>(); + vtkm::cont::ArrayHandle numIndicesArray; + vtkm::cont::ArrayHandle indexOffsetArray; + vtkm::cont::ArrayHandle connectivityArray; + + CellSetDualGraph().Run( + cellSet, numIndicesArray, indexOffsetArray, connectivityArray); + std::cout << "numIndices: "; + for (int i = 0; i < numIndicesArray.GetNumberOfValues(); i++) + { + std::cout << numIndicesArray.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + + std::cout << "indexOffset: "; + for (int i = 0; i < indexOffsetArray.GetNumberOfValues(); i++) + { + std::cout << indexOffsetArray.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + + std::cout << "connectivity: "; + for (int i = 0; i < connectivityArray.GetNumberOfValues(); i++) + { + std::cout << connectivityArray.GetPortalConstControl().Get(i) << " "; + } + std::cout << std::endl; + } + void operator()() const + { + //this->TestTriangleMesh(); + this->TestIsosurface(); + } +}; + +int UnitTestDualGraph(int, char* []) +{ + return vtkm::cont::testing::Testing::Run(TestDualGraph()); +} \ No newline at end of file diff --git a/vtkm/worklet/testing/UnitTestGraphConnectivity.cpp b/vtkm/worklet/testing/UnitTestGraphConnectivity.cpp new file mode 100644 index 000000000..9c6594bba --- /dev/null +++ b/vtkm/worklet/testing/UnitTestGraphConnectivity.cpp @@ -0,0 +1,209 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class TangleField : public vtkm::worklet::WorkletMapField +{ +public: + typedef void ControlSignature(FieldIn vertexId, FieldOut v); + typedef void ExecutionSignature(_1, _2); + typedef _1 InputDomain; + + const vtkm::Id xdim, ydim, zdim; + const vtkm::FloatDefault xmin, ymin, zmin, xmax, ymax, zmax; + const vtkm::Id cellsPerLayer; + + VTKM_CONT + TangleField(const vtkm::Id3 dims, + const vtkm::FloatDefault mins[3], + const vtkm::FloatDefault maxs[3]) + : xdim(dims[0]) + , ydim(dims[1]) + , zdim(dims[2]) + , xmin(mins[0]) + , ymin(mins[1]) + , zmin(mins[2]) + , xmax(maxs[0]) + , ymax(maxs[1]) + , zmax(maxs[2]) + , cellsPerLayer((xdim) * (ydim)) + { + } + + VTKM_EXEC + void operator()(const vtkm::Id& vertexId, vtkm::Float32& v) const + { + const vtkm::Id x = vertexId % (xdim); + const vtkm::Id y = (vertexId / (xdim)) % (ydim); + const vtkm::Id z = vertexId / cellsPerLayer; + + const vtkm::FloatDefault fx = + static_cast(x) / static_cast(xdim - 1); + const vtkm::FloatDefault fy = + static_cast(y) / static_cast(xdim - 1); + const vtkm::FloatDefault fz = + static_cast(z) / static_cast(xdim - 1); + + const vtkm::Float32 xx = 3.0f * vtkm::Float32(xmin + (xmax - xmin) * (fx)); + const vtkm::Float32 yy = 3.0f * vtkm::Float32(ymin + (ymax - ymin) * (fy)); + const vtkm::Float32 zz = 3.0f * vtkm::Float32(zmin + (zmax - zmin) * (fz)); + + v = (xx * xx * xx * xx - 5.0f * xx * xx + yy * yy * yy * yy - 5.0f * yy * yy + + zz * zz * zz * zz - 5.0f * zz * zz + 11.8f) * + 0.2f + + 0.5f; + } +}; + +static vtkm::cont::DataSet MakeIsosurfaceTestDataSet(vtkm::Id3 dims) +{ + vtkm::cont::DataSet dataSet; + + const vtkm::Id3 vdims(dims[0] + 1, dims[1] + 1, dims[2] + 1); + + vtkm::FloatDefault mins[3] = { -1.0f, -1.0f, -1.0f }; + vtkm::FloatDefault maxs[3] = { 1.0f, 1.0f, 1.0f }; + + vtkm::cont::ArrayHandle pointFieldArray; + vtkm::cont::ArrayHandleIndex vertexCountImplicitArray(vdims[0] * vdims[1] * vdims[2]); + vtkm::worklet::DispatcherMapField tangleFieldDispatcher( + TangleField(vdims, mins, maxs)); + tangleFieldDispatcher.Invoke(vertexCountImplicitArray, pointFieldArray); + + vtkm::Id numCells = dims[0] * dims[1] * dims[2]; + auto cellFieldArray = vtkm::cont::make_ArrayHandleCounting(0, 1, numCells); + + vtkm::Vec origin(0.0f, 0.0f, 0.0f); + vtkm::Vec spacing(1.0f / static_cast(dims[0]), + 1.0f / static_cast(dims[2]), + 1.0f / static_cast(dims[1])); + + vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(vdims, origin, spacing); + dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates)); + + static const vtkm::IdComponent ndim = 3; + vtkm::cont::CellSetStructured cellSet("cells"); + cellSet.SetPointDimensions(vdims); + dataSet.AddCellSet(cellSet); + + dataSet.AddField(vtkm::cont::Field("nodevar", vtkm::cont::Field::ASSOC_POINTS, pointFieldArray)); + dataSet.AddField( + vtkm::cont::Field("cellvar", vtkm::cont::Field::ASSOC_CELL_SET, "cells", cellFieldArray)); + + return dataSet; +} + + +template +class TestGraphConnectivity +{ +public: + void TestGrafting() const + { +// std::vector ids = {0, 1, 2, 3}; +// std::vector conn = {1, 0, 2, 3, 1, 1}; +// std::vector starts = {0, 1, 4, 5}; +// std::vector ends = {1, 4, 5, 6}; +// std::vector degrees = {1, 3, 1, 1}; +// std::vector comp = {0, 1, 2, 3}; + +// std::vector ids = {0, 1, 2, 3, 4}; +// std::vector conn = {1, 2, 0, 2, 0, 1, 4, 3}; +// std::vector starts = {0, 2, 4, 6, 7}; +// std::vector ends = {2, 4, 6, 7, 8}; +// std::vector degrees = {2, 2, 2, 1, 1}; +// std::vector comp = {0, 1, 2, 3, 4}; + +// vtkm::cont::ArrayHandle idsArr = vtkm::cont::make_ArrayHandle(ids); +// vtkm::cont::ArrayHandle connArr = vtkm::cont::make_ArrayHandle(conn); +// vtkm::cont::ArrayHandle startsArr = vtkm::cont::make_ArrayHandle(starts); +// vtkm::cont::ArrayHandle endsArr = vtkm::cont::make_ArrayHandle(ends); +// vtkm::cont::ArrayHandle degreesArr = vtkm::cont::make_ArrayHandle(degrees); +// vtkm::cont::ArrayHandle compArr = vtkm::cont::make_ArrayHandle(comp); +// for (int i = 0; i < compArr.GetNumberOfValues(); i++) { +// std::cout << compArr.GetPortalConstControl().Get(i) << " "; +// } +// std::cout << std::endl; + +// std::vector connectivity = { 0, 2, 4, 1, 3, 5, 2, 6, 4, 5, 3, 7, 2, 9, 6, 4, 6, 8}; +// vtkm::cont::CellSetSingleType<> cellSet; +// cellSet.Fill(8, +// vtkm::CELL_SHAPE_TRIANGLE, +// 3, +// vtkm::cont::make_ArrayHandle(connectivity)); + + vtkm::Id3 dims(4, 4, 4); + vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims); + + vtkm::filter::MarchingCubes filter; + filter.SetGenerateNormals(true); + filter.SetMergeDuplicatePoints(true); + filter.SetIsoValue(0, 0.1); + vtkm::filter::Result result = filter.Execute(dataSet, dataSet.GetField("nodevar")); + vtkm::cont::DataSet& outputData = result.GetDataSet(); + + auto cellSet = outputData.GetCellSet().Cast>(); + + + vtkm::cont::ArrayHandle numIndicesArray; + vtkm::cont::ArrayHandle indexOffsetArray; + vtkm::cont::ArrayHandle connectivityArray; + + CellSetDualGraph().Run(cellSet, + numIndicesArray, + indexOffsetArray, + connectivityArray); + + vtkm::cont::ArrayHandle componentArray; + GraphConnectivity().Run(numIndicesArray, + indexOffsetArray, + connectivityArray, + componentArray); + + for (int i = 0; i < componentArray.GetNumberOfValues(); i++) + { + std::cout << i << " " + << componentArray.GetPortalConstControl().Get(i) << std::endl; + } + std::cout << std::endl; + } + + void operator()() const + { + this->TestGrafting(); + } +}; + +int UnitTestGraphConnectivity(int, char *[]) +{ + return vtkm::cont::testing::Testing::Run(TestGraphConnectivity()); +} \ No newline at end of file diff --git a/vtkm/worklet/testing/UnitTestInnerJoin.cxx b/vtkm/worklet/testing/UnitTestInnerJoin.cxx new file mode 100644 index 000000000..38fe2814a --- /dev/null +++ b/vtkm/worklet/testing/UnitTestInnerJoin.cxx @@ -0,0 +1,53 @@ +// +// Created by ollie on 12/19/17. +// + +#include +#include +#include +#include + +#include + +template +class TestInnerJoin +{ +public: + void TestTwoArrays() const + { + using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; + + std::vector A = { 8, 3, 6, 8, 9, 5, 12, 10, 14 }; + std::vector B = { 7, 11, 9, 8, 5, 1, 0, 5 }; + + vtkm::cont::ArrayHandle A_arr = vtkm::cont::make_ArrayHandle(A); + vtkm::cont::ArrayHandle B_arr = vtkm::cont::make_ArrayHandle(B); + vtkm::cont::ArrayHandle idxA; + vtkm::cont::ArrayHandle idxB; + + Algorithm::Copy(vtkm::cont::ArrayHandleCounting(0, 1, A_arr.GetNumberOfValues()), + idxA); + Algorithm::Copy(vtkm::cont::ArrayHandleCounting(0, 1, B_arr.GetNumberOfValues()), + idxB); + + vtkm::cont::ArrayHandle joinedIndex; + vtkm::cont::ArrayHandle outA; + vtkm::cont::ArrayHandle outB; + + InnerJoin().Run(A_arr, idxA, B_arr, idxB, joinedIndex, outA, outB); + + for (int i = 0; i < joinedIndex.GetNumberOfValues(); i++) + { + std::cout << "key: " << joinedIndex.GetPortalConstControl().Get(i) + << ", value1: " << outA.GetPortalConstControl().Get(i) + << ", value2: " << outB.GetPortalConstControl().Get(i) << std::endl; + } + } + + void operator()() const { this->TestTwoArrays(); } +}; + +int UnitTestInnerJoin(int, char* []) +{ + return vtkm::cont::testing::Testing::Run(TestInnerJoin()); +} \ No newline at end of file From 4c2ef4f89b240a97e5f93de3be4d302e3d46c411 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Tue, 2 Jan 2018 16:44:35 -0700 Subject: [PATCH 02/70] factor out CellSetConnectivity worklet, cleanup --- examples/CMakeLists.txt | 1 - examples/connected_component_labeling/CCL.cpp | 153 ------------- .../CMakeLists.txt | 7 - .../connectivities/CellSetConnectivity.h | 46 ++++ .../worklet/connectivities/CellSetDualGraph.h | 45 +--- .../connectivities/GraphConnectivity.h | 2 +- vtkm/worklet/connectivities/InnerJoin.h | 30 +-- vtkm/worklet/testing/CMakeLists.txt | 4 +- ...ph.cxx => UnitTestCellSetConnectivity.cpp} | 103 ++------- .../testing/UnitTestCellSetDualGraph.cxx | 87 ++++++++ .../testing/UnitTestGraphConnectivity.cpp | 209 ------------------ vtkm/worklet/testing/UnitTestInnerJoin.cxx | 39 +++- 12 files changed, 209 insertions(+), 517 deletions(-) delete mode 100644 examples/connected_component_labeling/CCL.cpp delete mode 100644 examples/connected_component_labeling/CMakeLists.txt create mode 100644 vtkm/worklet/connectivities/CellSetConnectivity.h rename vtkm/worklet/testing/{UnitTestDualGraph.cxx => UnitTestCellSetConnectivity.cpp} (61%) create mode 100644 vtkm/worklet/testing/UnitTestCellSetDualGraph.cxx delete mode 100644 vtkm/worklet/testing/UnitTestGraphConnectivity.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d871ee791..d18cd770a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -25,7 +25,6 @@ set(CMAKE_PREFIX_PATH ${VTKm_BINARY_DIR}/${VTKm_INSTALL_CONFIG_DIR}) add_subdirectory(clipping) add_subdirectory(contour_tree) -add_subdirectory(connected_component_labeling) add_subdirectory(cosmotools) add_subdirectory(demo) add_subdirectory(dynamic_dispatcher) diff --git a/examples/connected_component_labeling/CCL.cpp b/examples/connected_component_labeling/CCL.cpp deleted file mode 100644 index 367713acb..000000000 --- a/examples/connected_component_labeling/CCL.cpp +++ /dev/null @@ -1,153 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -// -// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). -// Copyright 2014 UT-Battelle, LLC. -// Copyright 2014 Los Alamos National Security. -// -// Under the terms of Contract DE-NA0003525 with NTESS, -// the U.S. Government retains certain rights in this software. -// -// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National -// Laboratory (LANL), the U.S. Government retains certain rights in -// this software. -//============================================================================ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -//#include -#include -//#include -#include - -void populate(std::vector& pixels, - std::vector& components, - vtkm::UInt32 width, - vtkm::UInt32 height) -{ - for (auto& pixel : pixels) { - pixel = 0.0f; - } - - for (int i = 6; i <= 8; i++) { - pixels[i] = 1.0f; - } - - for (int i = 16; i <= 18; i++) { - pixels[i] = 1.0f; - } - - for (int i = 0; i < width*height; ++i) { - components[i] = i; - } -} - -struct UpdateComponent : public vtkm::worklet::WorkletPointNeighborhood3x3x3 -{ - typedef void ControlSignature(FieldInNeighborhood pixel, - CellSetIn, - FieldInNeighborhood prevComponent, - FieldOut component); - - typedef void ExecutionSignature(_1, _3, _4); - - //verify input domain can be something other than first parameter - typedef _2 InputDomain; - - template - VTKM_EXEC void operator()(const vtkm::exec::arg::Neighborhood<1, FieldIn>& pixel, - const vtkm::exec::arg::Neighborhood<1, FieldIn1>& prevComponent, - FieldOut& component) const - //FieldIn1& component) const - { - //vtkm::UInt8 color = - std::cout << "pixel: " << pixel.Get(0, 0, 0) - << ", component: " << prevComponent.Get(0, 0, 0) - << std::endl; - - vtkm::Float32 color = pixel.Get(0, 0, 0); - if (color == pixel.Get(-1, 0, 0)) { - component = prevComponent.Get(-1, 0, 0); - } else if (color == pixel.Get(0, -1, 0)) { - component = prevComponent.Get(0, -1, 0); - } else { - component = prevComponent.Get(0, 0, 0); - } - } -}; - -struct FindRoot : public vtkm::worklet::WorkletMapField -{ - typedef void ControlSignature(FieldIn, - WholeArrayInOut component); - typedef void ExecutionSignature(_1, _2); - typedef _1 Inputdomain; - - template - VTKM_EXEC void operator()(const FieldIn& id, FieldOut& component) const { - //while (id != component.Get(id)) { -// if (id != component.Get(id)) { -// std::cout << "id: " << id << ", component: " << component.Get(id) << std::endl; -// component.Set(id, this->operator()(component.Get(id), component)); -// } - vtkm::Id parent = component.Get(id); - while (parent != component.Get(parent)) { - parent = component.Get(parent); - component.Set(id, parent); - - std::cout << "id: " << id << ", component: " << component.Get(id) << std::endl; - } - }; -}; - -int main(int argc, char *argv[]) -{ - vtkm::cont::DataSetBuilderUniform builder; - vtkm::cont::DataSet data = builder.Create(vtkm::Id2(5, 5)); - std::vector pixels(5*5); - std::vector components(5*5); - populate(pixels, components, 5, 5); - vtkm::cont::Field pixelField("pixels", vtkm::cont::Field::ASSOC_POINTS, pixels); - data.AddField(pixelField); - - vtkm::cont::Field componentField("components", vtkm::cont::Field::ASSOC_POINTS, components); - data.AddField(componentField); - - vtkm::worklet::DispatcherPointNeighborhood dispatcher; - - vtkm::cont::ArrayHandle output; - dispatcher.Invoke(data.GetField("pixels"), - data.GetCellSet(), - data.GetField("components"), - output); - - for (int i = 0; i < output.GetNumberOfValues(); i++) { - std::cout << output.GetPortalConstControl().Get(i) << " "; - } - std::cout << std::endl; - - vtkm::worklet::DispatcherMapField findRootDispatcher; - findRootDispatcher.Invoke(data.GetField("components"), output); - for (int i = 0; i < output.GetNumberOfValues(); i++) { - std::cout << output.GetPortalConstControl().Get(i) << " "; - } - std::cout << std::endl; -} \ No newline at end of file diff --git a/examples/connected_component_labeling/CMakeLists.txt b/examples/connected_component_labeling/CMakeLists.txt deleted file mode 100644 index 940653b0f..000000000 --- a/examples/connected_component_labeling/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -find_package(VTKm REQUIRED QUIET - OPTIONAL_COMPONENTS Serial #CUDA TBB OpenGL GLUT - ) - -add_executable(CCL CCL.cpp) -target_link_libraries(CCL PRIVATE ${VTKm_LIBRARIES}) -target_compile_options(CCL PRIVATE ${VTKm_COMPILE_OPTIONS}) diff --git a/vtkm/worklet/connectivities/CellSetConnectivity.h b/vtkm/worklet/connectivities/CellSetConnectivity.h new file mode 100644 index 000000000..3d5a8fe8d --- /dev/null +++ b/vtkm/worklet/connectivities/CellSetConnectivity.h @@ -0,0 +1,46 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). +// Copyright 2014 UT-Battelle, LLC. +// Copyright 2014 Los Alamos National Security. +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National +// Laboratory (LANL), the U.S. Government retains certain rights in +// this software. +//============================================================================ + +#ifndef vtk_m_worklet_connectivity_CellSetConnectivity_h +#define vtk_m_worklet_connectivity_CellSetConnectivity_h + +#include +#include + +template +class CellSetConnectivity +{ +public: + template