Visual Computing Library
Loading...
Searching...
No Matches
static_grid.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_SPACE_COMPLEX_GRID_STATIC_GRID_H
24#define VCL_SPACE_COMPLEX_GRID_STATIC_GRID_H
25
26#include "abstract_grid.h"
27#include "iterators/static_grid_iterator.h"
28#include "regular_grid.h"
29
30#include <vclib/concepts/ranges/mesh/vertex_range.h>
31
32#include <set>
33#include <vector>
34
35namespace vcl {
36
37template<typename GridType, typename ValueType>
39 public AbstractGrid<
40 GridType,
41 ValueType,
42 StaticGrid<GridType, ValueType>>
43{
44 using AbsGrid =
46
47 using PairType = std::pair<uint, ValueType>;
49
50 friend AbsGrid;
51
52 PairComparator mComparator = PairComparator();
53
54 // each value is stored as a pair: [cell index of the grid - value]
55 // when the grid is built, this vector is sorted by the cell indices
56 std::vector<PairType> mValues;
57
58 // for each cell of the grid, we store the index (in the values vector ) of
59 // the first ValueType object contained in the cell, or values.size() if the
60 // cell is empty
61 std::vector<uint> mGrid;
62
63public:
64 using KeyType = AbsGrid::KeyType;
65 using IntersectsCellFunction = AbsGrid::IntersectsCellFunction;
66
69
70 StaticGrid() {}
71
72 StaticGrid(const GridType& g) : AbsGrid(g) {}
73
74 template<typename ObjIterator>
76 ObjIterator begin,
77 ObjIterator end,
78 const IntersectsCellFunction& intersects = nullptr) :
79 AbsGrid(begin, end, intersects)
80 {
81 AbsGrid::insert(begin, end);
82 build();
83 }
84
85 template<Range Rng>
86 StaticGrid(Rng&& r, const IntersectsCellFunction& intersects = nullptr) :
87 StaticGrid(std::ranges::begin(r), std::ranges::end(r), intersects)
88 {
89 }
90
91 void build()
92 {
93 uint totCellNumber = 1;
94 for (uint i = 0; i < GridType::DIM; ++i) {
95 totCellNumber *= GridType::cellNumber(i);
96 }
97
98 mGrid.resize(totCellNumber);
99
100 std::sort(mValues.begin(), mValues.end(), mComparator);
101
102 // values[vi].first points to the next non empty cell in the grid
103 uint vi = 0;
104
105 // for each cell
106 for (uint ci = 0; ci < mGrid.size(); ++ci) {
107 // values[vi] is in the cell ci
108 if (vi < mValues.size() && mValues[vi].first == ci)
109 mGrid[ci] = vi;
110 else { // there are no values in this grid cell
111 mGrid[ci] = mValues.size(); // set the sentinel value
112 }
113
114 // move vi to the next non-empty cell
115 // skip all the values that are in the current cell ci
116 // won't increment vi if the values[vi].first is not equal to ci
117 while (vi < mValues.size() && mValues[vi].first == ci) {
118 vi++;
119 }
120 }
121 }
122
123 bool empty() const { return mValues.empty(); }
124
125 bool cellEmpty(const KeyType& k) const
126 {
127 uint ind = GridType::indexOfCell(k);
128 return mGrid[ind] == mValues.size();
129 }
130
131 std::set<KeyType> nonEmptyCells() const
132 {
133 std::set<KeyType> keys;
134 uint actualInd = mValues.size();
135 for (uint i = 0; i < mValues.size(); ++i) {
136 if (mValues[i].first != actualInd) {
137 actualInd = mValues[i].first;
138 keys.insert(GridType::cellOfIndex(actualInd));
139 }
140 }
141 return keys;
142 }
143
144 std::size_t countInCell(const KeyType& k) const
145 {
146 uint ind = GridType::indexOfCell(k);
147 uint i = mGrid[ind];
148 uint cnt = 0;
149
150 while (i < mValues.size() && mValues[i].first == ind) {
151 i++;
152 cnt++;
153 }
154 return cnt;
155 }
156
157 std::pair<Iterator, Iterator> valuesInCell(const KeyType& k)
158 {
159 uint ind = GridType::indexOfCell(k);
160 uint i = mGrid[ind];
161 if (i < mValues.size()) {
162 std::pair<Iterator, Iterator> p;
163 p.first = Iterator(mValues.begin() + i, (const GridType&) *this);
164 while (i < mValues.size() && mValues[i].first == ind) {
165 i++;
166 }
167 auto it = i < mValues.size() ? mValues.begin() + i : mValues.end();
168 p.second = Iterator(it, (const GridType&) *this);
169 return p;
170 }
171 else {
172 return std::make_pair(end(), end());
173 }
174 }
175
176 std::pair<ConstIterator, ConstIterator> valuesInCell(const KeyType& k) const
177 {
178 uint ind = GridType::indexOfCell(k);
179 uint i = mGrid[ind];
180 if (i < mValues.size()) {
181 std::pair<ConstIterator, ConstIterator> p;
182 p.first =
183 ConstIterator(mValues.begin() + i, (const GridType&) *this);
184 while (i < mValues.size() && mValues[i].first == ind) {
185 i++;
186 }
187 auto it = i < mValues.size() ? mValues.begin() + i : mValues.end();
188 p.second = ConstIterator(it, (const GridType&) *this);
189 return p;
190 }
191 else {
192 return std::make_pair(end(), end());
193 }
194 }
195
196 Iterator begin()
197 {
198 return Iterator(mValues.begin(), (const GridType&) *this);
199 }
200
201 ConstIterator begin() const
202 {
203 return ConstIterator(mValues.begin(), (const GridType&) *this);
204 }
205
206 Iterator end() { return Iterator(mValues.end(), (const GridType&) *this); }
207
208 ConstIterator end() const
209 {
210 return ConstIterator(mValues.end(), (const GridType&) *this);
211 }
212
213private:
214 // not available member functions
215 using AbsGrid::erase;
216 using AbsGrid::eraseAllInCell;
217 using AbsGrid::eraseInSphere;
218
219 bool insertInCell(const KeyType& cell, const ValueType& v)
220 {
221 uint cellIndex = GridType::indexOfCell(cell);
222 mValues.emplace_back(cellIndex, v);
223 return true;
224 }
225
226 // not allowing to erase
227 bool eraseInCell(const KeyType&, const ValueType&) { return false; };
228};
229
230/* Specialization Aliases */
231
232template<typename ValueType, typename ScalarType = double>
234
235template<typename ValueType, typename ScalarType = double>
237
238/* Deduction guides */
239
240template<PointIteratorConcept It>
242 -> StaticGrid<
244 typename It::value_type::ScalarType>;
245
246template<PointIteratorConcept It, typename F>
247StaticGrid(It, It, F)
248 -> StaticGrid<
250 typename It::value_type::ScalarType>;
251
252template<VertexPointerRangeConcept Rng>
255 // scalar type used for the grid, the same of the
256 // CoordType of the Vertex
257 typename RemovePtr<typename std::ranges::iterator_t<
258 Rng>::value_type>::CoordType::ScalarType,
259 3>, // the dimension of the Grid
260 // the ValueType of the StaticGrid, which is the iterated
261 // type in the given range (pointer to vertex)
262 typename std::ranges::iterator_t<Rng>::value_type>;
263
264} // namespace vcl
265
266#endif // VCL_SPACE_COMPLEX_GRID_STATIC_GRID_H
The AbstractGrid class describes a generic Spatial Data Structure organized on a regular grid,...
Definition abstract_grid.h:108
bool insert(const ValueType &v)
Inserts the given element in the AbstractGrid.
Definition abstract_grid.h:183
std::function< bool(const typename GridType::BBoxType &, const RemoveCVRefAndPointer< ValueType > &)> IntersectsCellFunction
The IntersectsCellFunction type is a std::function that takes as input a bounding box and a value,...
Definition abstract_grid.h:119
Definition regular_grid.h:35
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
Definition static_grid.h:43
std::remove_pointer_t< T > RemovePtr
Utility alias to get a type without the pointer. e.g. If T is int*, the resulting type is int.
Definition pointers.h:42