ViennaLS
Loading...
Searching...
No Matches
lsCalculateVisibilities.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <hrleSparseIterator.hpp>
4#include <lsDomain.hpp>
5#include <vcVectorType.hpp>
6
7namespace viennals {
8using namespace viennacore;
9
10template <class T, int D> class CalculateVisibilities {
11 using hrleDomainType = typename Domain<T, D>::DomainType;
12
13 SmartPointer<Domain<T, D>> levelSet;
14 Vec3D<T> direction;
15 const T epsilon = static_cast<T>(1e-6);
16 const std::string visibilitiesLabel;
17
18public:
19 CalculateVisibilities(const SmartPointer<Domain<T, D>> &passedLevelSet,
20 const Vec3D<T> &passedDirection,
21 std::string label = "Visibilities")
22 : levelSet(passedLevelSet), direction(passedDirection),
23 visibilitiesLabel(std::move(label)) {}
24
25 void apply() {
26 auto &domain = levelSet->getDomain();
27 auto &grid = levelSet->getGrid();
28
29 // *** Determine extents of domain ***
30 Vec3D<T> minDefinedPoint;
31 Vec3D<T> maxDefinedPoint;
32 // Initialize with extreme values
33 for (int i = 0; i < D; ++i) {
34 minDefinedPoint[i] = std::numeric_limits<T>::max();
35 maxDefinedPoint[i] = std::numeric_limits<T>::lowest();
36 }
37 // Iterate through all defined points in the domain
38 for (viennahrle::SparseIterator<hrleDomainType> it(domain);
39 !it.isFinished(); it.next()) {
40 if (!it.isDefined())
41 continue; // Skip undefined points
42
43 // Get the coordinate of the current point
44 auto point = it.getStartIndices();
45 for (int i = 0; i < D; ++i) {
46 // Compare to update min and max defined points
47 T coord = point[i]; // * grid.getGridDelta();
48 minDefinedPoint[i] = std::min(minDefinedPoint[i], coord);
49 maxDefinedPoint[i] = std::max(maxDefinedPoint[i], coord);
50 }
51 }
52 //****************************
53
54 // Invert the vector
55 auto dir = Normalize(Inv(direction));
56 std::vector<T> visibilities(domain.getNumberOfPoints(), static_cast<T>(-1));
57
58#pragma omp parallel num_threads(levelSet->getNumberOfSegments())
59 {
60 int p = 0;
61#ifdef _OPENMP
62 p = omp_get_thread_num();
63#endif
64
65 const viennahrle::Index<D> startVector =
66 (p == 0) ? grid.getMinGridPoint() : domain.getSegmentation()[p - 1];
67
68 const viennahrle::Index<D> endVector =
69 (p != static_cast<int>(domain.getNumberOfSegments() - 1))
70 ? domain.getSegmentation()[p]
71 : grid.incrementIndices(grid.getMaxGridPoint());
72
73 for (viennahrle::SparseIterator<hrleDomainType> it(domain, startVector);
74 it.getStartIndices() < endVector; ++it) {
75
76 if (!it.isDefined())
77 continue;
78
79 // Starting position of the point
80 Vec3D<T> currentPos;
81 for (int i = 0; i < D; ++i) {
82 currentPos[i] = it.getStartIndices(i);
83 }
84
85 // Start tracing the ray
86 T minLevelSetValue = it.getValue(); // Starting level set value
87 Vec3D<T> rayPos = currentPos;
88
89 // Step once to skip immediate neighbor
90 for (int i = 0; i < D; ++i)
91 rayPos[i] += dir[i];
92
93 bool visibility = true;
94
95 while (true) {
96 // Update the ray position
97 for (int i = 0; i < D; ++i)
98 rayPos[i] += dir[i];
99
100 // Determine the nearest grid cell (round to nearest index)
101 viennahrle::Index<D> nearestCell;
102 for (int i = 0; i < D; ++i)
103 nearestCell[i] = static_cast<viennahrle::IndexType>(rayPos[i]);
104
105 // Check if the nearest cell is within bounds
106 bool outOfBounds = false;
107 for (int i = 0; i < D; ++i) {
108 if (nearestCell[i] < minDefinedPoint[i] ||
109 nearestCell[i] > maxDefinedPoint[i]) {
110 outOfBounds = true;
111 break;
112 }
113 }
114
115 if (outOfBounds)
116 break; // Ray is outside the grid
117
118 // Access the level set value at the nearest cell
119 T value =
120 viennahrle::SparseIterator<hrleDomainType>(domain, nearestCell)
121 .getValue();
122
123 // Update the minimum value encountered
124 if (value < minLevelSetValue) {
125 visibility = false;
126 break;
127 }
128 }
129
130 // Update visibility for this point
131 visibilities[it.getPointId()] = visibility ? 1.0 : 0.0;
132 }
133 }
134
135 int unassignedCount = 0;
136 for (size_t i = 0; i < visibilities.size(); ++i) {
137 if (visibilities[i] < 0) {
138 std::cerr << "Unassigned visibility at point ID: " << i << std::endl;
139 ++unassignedCount;
140 }
141 }
142 if (unassignedCount > 0) {
143 std::cerr << "[Error] Total unassigned points: " << unassignedCount
144 << std::endl;
145 }
146
147 auto &pointData = levelSet->getPointData();
148 // delete if already exists
149 if (int i = pointData.getScalarDataIndex(visibilitiesLabel); i != -1) {
150 pointData.eraseScalarData(i);
151 }
152 pointData.insertNextScalarData(visibilities, visibilitiesLabel);
153 }
154};
155
156} // namespace viennals
CalculateVisibilities(const SmartPointer< Domain< T, D > > &passedLevelSet, const Vec3D< T > &passedDirection, std::string label="Visibilities")
Definition lsCalculateVisibilities.hpp:19
void apply()
Definition lsCalculateVisibilities.hpp:25
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:27
viennahrle::Domain< T, D > DomainType
Definition lsDomain.hpp:32
Definition lsAdvect.hpp:36
constexpr int D
Definition pyWrap.cpp:71
double T
Definition pyWrap.cpp:69