//============================================================================ // 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. //============================================================================ #include #include #include #include #include namespace vtkm { namespace rendering { namespace raytracing { namespace detail { class CountPoints : public vtkm::worklet::WorkletVisitCellsWithPoints { public: VTKM_CONT CountPoints() {} typedef void ControlSignature(CellSetIn cellset, FieldOut); typedef void ExecutionSignature(CellShape, _2); VTKM_EXEC void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& points) const { if (shapeType.Id == vtkm::CELL_SHAPE_VERTEX) points = 1; else points = 0; } VTKM_EXEC void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& points) const { points = 0; } VTKM_EXEC void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shapeType), vtkm::Id& points) const { points = 0; } VTKM_EXEC void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& points) const { points = 0; } }; // ClassCountPoints class Pointify : public vtkm::worklet::WorkletVisitCellsWithPoints { public: VTKM_CONT Pointify() {} typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut); typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3); template VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset), vtkm::CellShapeTagQuad vtkmNotUsed(shapeType), const VecType& vtkmNotUsed(cellIndices), const vtkm::Id& vtkmNotUsed(cellId), OutputPortal& vtkmNotUsed(outputIndices)) const { } template VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset), vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), const VecType& vtkmNotUsed(cellIndices), const vtkm::Id& vtkmNotUsed(cellId), OutputPortal& vtkmNotUsed(outputIndices)) const { } template VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset), vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), const VecType& vtkmNotUsed(cellIndices), const vtkm::Id& vtkmNotUsed(cellId), OutputPortal& vtkmNotUsed(outputIndices)) const { } template VTKM_EXEC void operator()(const vtkm::Id& pointOffset, vtkm::CellShapeTagGeneric shapeType, const VecType& vtkmNotUsed(cellIndices), const vtkm::Id& cellId, OutputPortal& outputIndices) const { if (shapeType.Id == vtkm::CELL_SHAPE_VERTEX) { outputIndices.Set(pointOffset, cellId); } } }; //class pointify class Iterator : public vtkm::worklet::WorkletMapField { public: VTKM_CONT Iterator() {} typedef void ControlSignature(FieldOut); typedef void ExecutionSignature(_1, WorkIndex); VTKM_EXEC void operator()(vtkm::Id& index, const vtkm::Id& idx) const { index = idx; } }; //class Iterator class FieldRadius : public vtkm::worklet::WorkletMapField { protected: vtkm::Float32 MinRadius; vtkm::Float32 RadiusDelta; vtkm::Float32 MinValue; vtkm::Float32 InverseDelta; public: VTKM_CONT FieldRadius(const vtkm::Float32 minRadius, const vtkm::Float32 maxRadius, const vtkm::Range scalarRange) : MinRadius(minRadius) , RadiusDelta(maxRadius - minRadius) , MinValue(static_cast(scalarRange.Min)) { vtkm::Float32 delta = static_cast(scalarRange.Max - scalarRange.Min); if (delta != 0.f) InverseDelta = 1.f / (delta); else InverseDelta = 0.f; // just map scalar to 0; } typedef void ControlSignature(FieldIn, FieldOut, WholeArrayIn); typedef void ExecutionSignature(_1, _2, _3); template VTKM_EXEC void operator()(const vtkm::Id& pointId, vtkm::Float32& radius, const ScalarPortalType& scalars) const { vtkm::Float32 scalar = static_cast(scalars.Get(pointId)); vtkm::Float32 t = (scalar - MinValue) * InverseDelta; radius = MinRadius + t * RadiusDelta; } }; //class FieldRadius } //namespace detail void SphereExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords, const vtkm::Float32 radius) { this->SetPointIdsFromCoords(coords); this->SetUniformRadius(radius); } void SphereExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords, const vtkm::cont::Field& field, const vtkm::Float32 minRadius, const vtkm::Float32 maxRadius) { this->SetPointIdsFromCoords(coords); this->SetVaryingRadius(minRadius, maxRadius, field); } void SphereExtractor::ExtractCells(const vtkm::cont::UnknownCellSet& cells, const vtkm::Float32 radius) { this->SetPointIdsFromCells(cells); this->SetUniformRadius(radius); } void SphereExtractor::ExtractCells(const vtkm::cont::UnknownCellSet& cells, const vtkm::cont::Field& field, const vtkm::Float32 minRadius, const vtkm::Float32 maxRadius) { this->SetPointIdsFromCells(cells); this->SetVaryingRadius(minRadius, maxRadius, field); } void SphereExtractor::SetUniformRadius(const vtkm::Float32 radius) { const vtkm::Id size = this->PointIds.GetNumberOfValues(); Radii.Allocate(size); vtkm::cont::ArrayHandleConstant radiusHandle(radius, size); vtkm::cont::Algorithm::Copy(radiusHandle, Radii); } void SphereExtractor::SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords) { vtkm::Id size = coords.GetNumberOfPoints(); this->PointIds.Allocate(size); vtkm::worklet::DispatcherMapField(detail::Iterator()).Invoke(this->PointIds); } void SphereExtractor::SetPointIdsFromCells(const vtkm::cont::UnknownCellSet& cells) { using SingleType = vtkm::cont::CellSetSingleType<>; vtkm::Id numCells = cells.GetNumberOfCells(); if (numCells == 0) { return; } // // look for points in the cell set // if (cells.CanConvert>()) { auto cellsExplicit = cells.AsCellSet>(); vtkm::cont::ArrayHandle points; vtkm::worklet::DispatcherMapTopology(detail::CountPoints()) .Invoke(cellsExplicit, points); vtkm::Id totalPoints = 0; totalPoints = vtkm::cont::Algorithm::Reduce(points, vtkm::Id(0)); vtkm::cont::ArrayHandle cellOffsets; vtkm::cont::Algorithm::ScanExclusive(points, cellOffsets); PointIds.Allocate(totalPoints); vtkm::worklet::DispatcherMapTopology(detail::Pointify()) .Invoke(cellsExplicit, cellOffsets, this->PointIds); } else if (cells.CanConvert()) { SingleType pointCells = cells.AsCellSet(); vtkm::UInt8 shape_id = pointCells.GetCellShape(0); if (shape_id == vtkm::CELL_SHAPE_VERTEX) { this->PointIds.Allocate(numCells); vtkm::worklet::DispatcherMapField(detail::Iterator()) .Invoke(this->PointIds); } } } void SphereExtractor::SetVaryingRadius(const vtkm::Float32 minRadius, const vtkm::Float32 maxRadius, const vtkm::cont::Field& field) { vtkm::cont::ArrayHandle rangeArray = field.GetRange(); if (rangeArray.GetNumberOfValues() != 1) { throw vtkm::cont::ErrorBadValue("Sphere Extractor: scalar field must have one component"); } vtkm::Range range = rangeArray.ReadPortal().Get(0); Radii.Allocate(this->PointIds.GetNumberOfValues()); vtkm::worklet::DispatcherMapField( detail::FieldRadius(minRadius, maxRadius, range)) .Invoke(this->PointIds, this->Radii, vtkm::rendering::raytracing::GetScalarFieldArray(field)); } vtkm::cont::ArrayHandle SphereExtractor::GetPointIds() { return this->PointIds; } vtkm::cont::ArrayHandle SphereExtractor::GetRadii() { return this->Radii; } vtkm::Id SphereExtractor::GetNumberOfSpheres() const { return this->PointIds.GetNumberOfValues(); } } } } //namespace vtkm::rendering::raytracing