ViennaLS
Loading...
Searching...
No Matches
lsExpand.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <hrleSparseStarIterator.hpp>
6#include <hrleVectorType.hpp>
7#include <lsDomain.hpp>
8
9namespace viennals {
10
11using namespace viennacore;
12
16template <class T, int D> class Expand {
17 typedef typename Domain<T, D>::GridType GridType;
18 SmartPointer<Domain<T, D>> levelSet = nullptr;
19 int width = 0;
20 bool updatePointData = true;
21
22public:
23 Expand() {}
24
25 Expand(SmartPointer<Domain<T, D>> passedlsDomain)
26 : levelSet(passedlsDomain) {}
27
28 Expand(SmartPointer<Domain<T, D>> passedlsDomain, int passedWidth)
29 : levelSet(passedlsDomain), width(passedWidth) {}
30
31 void setLevelSet(SmartPointer<Domain<T, D>> passedlsDomain) {
32 levelSet = passedlsDomain;
33 }
34
37 void setWidth(int passedWidth) { width = passedWidth; }
38
41 void setUpdatePointData(bool update) { updatePointData = update; }
42
44 void apply() {
45 if (levelSet == nullptr) {
46 Logger::getInstance()
47 .addWarning("No level set passed to Expand. Not expanding.")
48 .print();
49 return;
50 }
51
52 if (width <= levelSet->getLevelSetWidth())
53 return;
54
55 if (levelSet->getNumberOfPoints() == 0)
56 return;
57
58 const T totalLimit = width * 0.5;
59 const int startWidth = levelSet->getLevelSetWidth();
60 const int numberOfRequiredCycles = width - startWidth;
61
62 for (int currentCycle = 0; currentCycle < numberOfRequiredCycles;
63 ++currentCycle) {
64
65 const int allocationFactor =
66 1 + 1.0 / static_cast<double>(startWidth + currentCycle);
67 const T limit = (startWidth + currentCycle + 1) * T(0.5);
68
69 auto &grid = levelSet->getGrid();
70 auto newlsDomain = SmartPointer<Domain<T, D>>::New(grid);
71 typename Domain<T, D>::DomainType &newDomain = newlsDomain->getDomain();
72 typename Domain<T, D>::DomainType &domain = levelSet->getDomain();
73
74 newDomain.initialize(domain.getNewSegmentation(),
75 domain.getAllocation() * allocationFactor);
76
77 const bool updateData = updatePointData;
78 // save how data should be transferred to new level set
79 // list of indices into the old pointData vector
80 std::vector<std::vector<unsigned>> newDataSourceIds;
81 if (updateData)
82 newDataSourceIds.resize(newDomain.getNumberOfSegments());
83
84#pragma omp parallel num_threads(newDomain.getNumberOfSegments())
85 {
86 int p = 0;
87#ifdef _OPENMP
88 p = omp_get_thread_num();
89#endif
90
91 auto &domainSegment = newDomain.getDomainSegment(p);
92
93 hrleVectorType<hrleIndexType, D> startVector =
94 (p == 0) ? grid.getMinGridPoint()
95 : newDomain.getSegmentation()[p - 1];
96
97 hrleVectorType<hrleIndexType, D> endVector =
98 (p != static_cast<int>(newDomain.getNumberOfSegments() - 1))
99 ? newDomain.getSegmentation()[p]
100 : grid.incrementIndices(grid.getMaxGridPoint());
101
102 for (hrleSparseStarIterator<typename Domain<T, D>::DomainType, 1>
103 neighborIt(domain, startVector);
104 neighborIt.getIndices() < endVector; neighborIt.next()) {
105
106 auto &centerIt = neighborIt.getCenter();
107 if (std::abs(centerIt.getValue()) <= totalLimit) {
108 domainSegment.insertNextDefinedPoint(neighborIt.getIndices(),
109 centerIt.getValue());
110 if (updateData)
111 newDataSourceIds[p].push_back(centerIt.getPointId());
112 } else {
113 if (centerIt.getValue() > -std::numeric_limits<T>::epsilon()) {
114 T distance = Domain<T, D>::POS_VALUE;
115 int neighbor = -1;
116 for (int i = 0; i < 2 * D; i++) {
117 T newValue = neighborIt.getNeighbor(i).getValue() + T(1);
118 if (distance > newValue) {
119 distance = newValue;
120 neighbor = i;
121 }
122 }
123 if (distance <= limit) {
124 domainSegment.insertNextDefinedPoint(neighborIt.getIndices(),
125 distance);
126 if (updateData)
127 newDataSourceIds[p].push_back(
128 neighborIt.getNeighbor(neighbor).getPointId());
129 } else {
130 // TODO: use insertNextUndefinedRunType
131 domainSegment.insertNextUndefinedPoint(neighborIt.getIndices(),
133 }
134 } else {
135 T distance = Domain<T, D>::NEG_VALUE;
136 int neighbor = -1;
137 for (int i = 0; i < 2 * D; i++) {
138 T newValue = neighborIt.getNeighbor(i).getValue() - T(1);
139 if (distance < newValue) {
140 distance = newValue;
141 neighbor = i;
142 }
143 }
144 if (distance >= -limit) {
145 domainSegment.insertNextDefinedPoint(neighborIt.getIndices(),
146 distance);
147 if (updateData)
148 newDataSourceIds[p].push_back(
149 neighborIt.getNeighbor(neighbor).getPointId());
150 } else {
151 // TODO: use insertNextUndefinedRunType
152 domainSegment.insertNextUndefinedPoint(neighborIt.getIndices(),
154 }
155 }
156 }
157 }
158 }
159
160 // now copy old data into new level set
161 if (updateData) {
162 newlsDomain->getPointData().translateFromMultiData(
163 levelSet->getPointData(), newDataSourceIds);
164 }
165
166 newDomain.finalize();
167 levelSet->deepCopy(newlsDomain);
168 }
169 levelSet->getDomain().segment();
170 levelSet->finalize(width);
171 }
172};
173
174// add all template specialisations for this class
176
177} // namespace viennals
Class containing all information about the level set, including the dimensions of the domain,...
Definition lsDomain.hpp:28
hrleGrid< D > GridType
Definition lsDomain.hpp:32
unsigned getNumberOfSegments() const
returns the number of segments, the levelset is split into. This is useful for algorithm parallelisat...
Definition lsDomain.hpp:150
void finalize(int newWidth)
this function sets a new levelset width and finalizes the levelset, so it is ready for use by other a...
Definition lsDomain.hpp:114
hrleDomain< T, D > DomainType
Definition lsDomain.hpp:33
Expands the leveleSet to the specified number of layers. The largest value in the levelset is thus wi...
Definition lsExpand.hpp:16
Expand(SmartPointer< Domain< T, D > > passedlsDomain, int passedWidth)
Definition lsExpand.hpp:28
Expand()
Definition lsExpand.hpp:23
void setUpdatePointData(bool update)
Set whether to update the point data stored in the LS during this algorithm. Defaults to true.
Definition lsExpand.hpp:41
void apply()
Apply the expansion to the specified width.
Definition lsExpand.hpp:44
Expand(SmartPointer< Domain< T, D > > passedlsDomain)
Definition lsExpand.hpp:25
void setWidth(int passedWidth)
Set how far the level set should be extended. Points with value width*0.5 will be added by this algor...
Definition lsExpand.hpp:37
void setLevelSet(SmartPointer< Domain< T, D > > passedlsDomain)
Definition lsExpand.hpp:31
#define PRECOMPILE_PRECISION_DIMENSION(className)
Definition lsPreCompileMacros.hpp:24
Definition lsAdvect.hpp:46
constexpr int D
Definition pyWrap.cpp:65
double T
Definition pyWrap.cpp:63