1
+ #pragma once
2
+
3
+ #include < lsDomain.hpp>
4
+ #include < vcVectorUtil.hpp>
5
+
6
+ namespace viennals {
7
+ using namespace viennacore ;
8
+
9
+ template <class NumericType , int D> class CalculateVisibilities {
10
+ SmartPointer<Domain<NumericType, D>> levelSet;
11
+ Vec3D<NumericType> direction;
12
+ const NumericType epsilon = static_cast <NumericType>(1e-6 );
13
+ const std::string visibilitiesLabel;
14
+
15
+ public:
16
+ CalculateVisibilities (
17
+ const SmartPointer<Domain<NumericType, D>> &passedLevelSet,
18
+ const Vec3D<NumericType> passedDirection,
19
+ const std::string label = " Visibilities" )
20
+ : levelSet(passedLevelSet), direction(passedDirection),
21
+ visibilitiesLabel (std::move(label)) {}
22
+
23
+ void apply () {
24
+
25
+ auto &domain = levelSet->getDomain ();
26
+ auto &grid = levelSet->getGrid ();
27
+
28
+ // *** Determine extents of domain ***
29
+ Vec3D<NumericType> minDefinedPoint;
30
+ Vec3D<NumericType> maxDefinedPoint;
31
+ // Initialize with extreme values
32
+ for (int i = 0 ; i < D; ++i) {
33
+ minDefinedPoint[i] = std::numeric_limits<NumericType>::max ();
34
+ maxDefinedPoint[i] = std::numeric_limits<NumericType>::lowest ();
35
+ }
36
+ // Iterate through all defined points in the domain
37
+ for (hrleSparseIterator<typename Domain<NumericType, D>::DomainType> it (
38
+ 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
+ NumericType 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
+ static_cast <NumericType>(domain.getGrid ().getGridDelta ());
57
+
58
+ auto numDefinedPoints = domain.getNumberOfPoints ();
59
+ std::vector<NumericType> visibilities (numDefinedPoints);
60
+
61
+ #pragma omp parallel num_threads(levelSet->getNumberOfSegments())
62
+ {
63
+ int p = 0 ;
64
+ #ifdef _OPENMP
65
+ p = omp_get_thread_num ();
66
+ #endif
67
+
68
+ hrleVectorType<hrleIndexType, D> startVector =
69
+ (p == 0 ) ? grid.getMinGridPoint () : domain.getSegmentation ()[p - 1 ];
70
+
71
+ hrleVectorType<hrleIndexType, D> endVector =
72
+ (p != static_cast <int >(domain.getNumberOfSegments () - 1 ))
73
+ ? domain.getSegmentation ()[p]
74
+ : grid.incrementIndices (grid.getMaxGridPoint ());
75
+
76
+ // Calculate the starting index for the visibility vector
77
+ hrleSizeType id = 0 ;
78
+ for (int i = 0 ; i < p; ++i) {
79
+ id += domain.getDomainSegment (i).getNumberOfPoints ();
80
+ }
81
+
82
+ for (hrleSparseIterator<typename Domain<NumericType, D>::DomainType> it (
83
+ domain, startVector);
84
+ it.getStartIndices () < endVector; ++it) {
85
+
86
+ if (!it.isDefined ())
87
+ continue ;
88
+
89
+ // Starting position of the point
90
+ Vec3D<NumericType> currentPos;
91
+ for (int i = 0 ; i < D; ++i) {
92
+ currentPos[i] = it.getStartIndices (i);
93
+ }
94
+
95
+ // Start tracing the ray
96
+ NumericType minLevelSetValue =
97
+ it.getValue (); // Starting level set value
98
+ Vec3D<NumericType> rayPos = currentPos;
99
+ bool visibility = true ;
100
+
101
+ while (1 ) {
102
+ // Update the ray position
103
+ for (int i = 0 ; i < D; ++i) {
104
+ rayPos[i] += dir[i];
105
+ }
106
+
107
+ // Determine the nearest grid cell (round to nearest index)
108
+ Vec3D<hrleIndexType> nearestCell;
109
+ for (int i = 0 ; i < D; ++i) {
110
+ nearestCell[i] = static_cast <hrleIndexType>(rayPos[i]);
111
+ }
112
+
113
+ // // Before adding a cell, check if it's already visited
114
+ // if (std::find(visitedCells.begin(), visitedCells.end(),
115
+ // nearestCell)
116
+ // == visitedCells.end()) {
117
+ // visitedCells.push_back(nearestCell);
118
+ // }
119
+
120
+ // Check if the nearest cell is within bounds
121
+ bool outOfBounds = false ;
122
+ for (int i = 0 ; i < D; ++i) {
123
+ if (nearestCell[i] < minDefinedPoint[i] ||
124
+ nearestCell[i] > maxDefinedPoint[i]) {
125
+ outOfBounds = true ;
126
+ break ;
127
+ }
128
+ }
129
+
130
+ if (outOfBounds) {
131
+ break ; // Ray is outside the grid
132
+ }
133
+
134
+ // Access the level set value at the nearest cell
135
+ NumericType neighborValue = std::numeric_limits<NumericType>::max ();
136
+ hrleSparseIterator<typename Domain<NumericType, D>::DomainType>
137
+ neighborIt (domain);
138
+ neighborIt.goToIndices (nearestCell);
139
+ neighborValue = neighborIt.getValue ();
140
+
141
+ // Update the minimum value encountered
142
+ if (neighborValue < minLevelSetValue) {
143
+ visibility = false ;
144
+ break ;
145
+ }
146
+ }
147
+
148
+ // Update visibility for this point
149
+ visibilities[id++] = visibility ? 1.0 : 0.0 ;
150
+ }
151
+ }
152
+
153
+ auto &pointData = levelSet->getPointData ();
154
+ // delete if already exists
155
+ if (int i = pointData.getScalarDataIndex (visibilitiesLabel); i != -1 ) {
156
+ pointData.eraseScalarData (i);
157
+ }
158
+ pointData.insertNextScalarData (visibilities, visibilitiesLabel);
159
+ }
160
+ };
161
+
162
+ } // namespace viennals
0 commit comments