PLaSK library

Loading...
Searching...
No Matches
base.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__FILTER__BASE_H
15#define PLASK__FILTER__BASE_H
16
17#include <vector>
18#include <memory>
19
20#include "../solver.hpp"
21#include "../provider/providerfor.hpp"
22
23 namespace plask {
24
26 template <typename PropertyT, PropertyType propertyType, typename OutputSpaceType, typename VariadicTemplateTypesHolder>
27 struct DataSourceImpl {
28 static_assert(propertyType != SINGLE_VALUE_PROPERTY, "space change filter data sources can't be use with single value properties (it can be use only with fields properties)");
29};
30
31//This class is similar to field provider, but in each point it returns optional value
32 template <typename PropertyT, typename OutputSpaceT, typename... ExtraArgs>
33 class DataSourceImpl<PropertyT, FIELD_PROPERTY, OutputSpaceT, VariadicTemplateTypesHolder<ExtraArgs...>>
34//: public FieldProvider<plask::optional<typename PropertyAt<PropertyT, OutputSpaceType>::ValueType>, OutputSpaceType, ExtraArgs...> //inharistance only for change signal, not neccessery
35{
36
37 //shared_ptr<OutputSpaceType> destinationSpace; //should be stored here? maybe only connection...
38
39 public:
40
41 typedef OutputSpaceT OutputSpaceType;
42
46 boost::signals2::signal<void()> changed;
47
48 /*shared_ptr<OutputSpaceType> getDestinationSpace() const { return destinationSpace; }
49
50 virtual void setDestinationSpace(shared_ptr<OutputSpaceType>) { this->destinationSpace = destinationSpace; }*/
51
52 /*
53 * Check if this source can provide value for given point.
54 * @param p point, in outer space coordinates
55 * @return @c true only if this can provide data in given point @p p
56 */
57 //virtual bool canProvide(const Vec<OutputSpaceType::DIM, double>& p) const = 0;
58
60 typedef typename PropertyAt<PropertyT, OutputSpaceType>::ValueType ValueType;
61
62 /*
63 * Check if this source can provide value for given point and eventually return this value.
64 * @param p point (in outer space coordinates)
65 * @param extra_args
66 * @param method interpolation method to use
67 * @return value in point @p, set only if this can provide data in given point @p p
68 */
69 // virtual plask::optional<ValueType> get(const Vec<OutputSpaceType::DIM, double>& p, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
70
71 // virtual ValueT get(const Vec<OutputSpaceType::DIM, double>& p, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
72
73 //virtual LazyData<plask::optional<ValueType>> operator()(const MeshD<OutputSpaceType::DIM>& dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
74
75 virtual ~DataSourceImpl() {}
76
77 virtual std::function<plask::optional<ValueType>(std::size_t index)> operator()(const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
78
79 inline std::function<plask::optional<ValueType>(std::size_t index)> operator()(const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, std::tuple<ExtraArgs...> extra_args, InterpolationMethod method) const {
80 typedef std::tuple<ExtraArgs...> Tuple;
81 return apply_tuple(dst_mesh, method, std::forward<Tuple>(extra_args), make_seq_indices<0, sizeof...(ExtraArgs)>{});
82 }
83
84 private:
85 template <typename T, template <std::size_t...> class I, std::size_t... Indices>
86 inline std::function<plask::optional<ValueType>(std::size_t index)> apply_tuple(const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, InterpolationMethod method, T&& t, I<Indices...>) const {
87 return this->operator()(dst_mesh, std::get<Indices>(std::forward<T>(t))..., method);
88 }
89
90};
91
92//This class is similar to field provider, but in each point it returns optional value
93 template <typename PropertyT, typename OutputSpaceT, typename... ExtraArgs>
94 class DataSourceImpl<PropertyT, MULTI_FIELD_PROPERTY, OutputSpaceT, VariadicTemplateTypesHolder<ExtraArgs...>>
95//: public FieldProvider<plask::optional<typename PropertyAt<PropertyT, OutputSpaceType>::ValueType>, OutputSpaceType, ExtraArgs...> //inharistance only for change signal, not neccessery
96{
97
98 //shared_ptr<OutputSpaceType> destinationSpace; //should be stored here? maybe only connection...
99
100 public:
101
102 typedef OutputSpaceT OutputSpaceType;
103 typedef typename PropertyT::EnumType EnumType;
104
108 boost::signals2::signal<void()> changed;
109
110 /*shared_ptr<OutputSpaceType> getDestinationSpace() const { return destinationSpace; }
111
112 virtual void setDestinationSpace(shared_ptr<OutputSpaceType>) { this->destinationSpace = destinationSpace; }*/
113
114 /*
115 * Check if this source can provide value for given point.
116 * @param p point, in outer space coordinates
117 * @return @c true only if this can provide data in given point @p p
118 */
119 //virtual bool canProvide(const Vec<OutputSpaceType::DIM, double>& p) const = 0;
120
122 typedef typename PropertyAt<PropertyT, OutputSpaceType>::ValueType ValueType;
123
124 /*
125 * Check if this source can provide value for given point and eventually return this value.
126 * @param p point (in outer space coordinates)
127 * @param extra_args
128 * @param method interpolation method to use
129 * @return value in point @p, set only if this can provide data in given point @p p
130 */
131 // virtual plask::optional<ValueType> get(const Vec<OutputSpaceType::DIM, double>& p, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
132
133 // virtual ValueT get(const Vec<OutputSpaceType::DIM, double>& p, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
134
135 //virtual LazyData<plask::optional<ValueType>> operator()(const MeshD<OutputSpaceType::DIM>& dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
136
137 virtual ~DataSourceImpl() {}
138
139 virtual std::function<plask::optional<ValueType>(std::size_t index)> operator()(EnumType num, const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
140
141 virtual size_t size() const = 0;
142
143 inline std::function<plask::optional<ValueType>(std::size_t index)> operator()(EnumType num, const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, std::tuple<ExtraArgs...> extra_args, InterpolationMethod method) const {
144 typedef std::tuple<ExtraArgs...> Tuple;
145 return apply_tuple(num, dst_mesh, method, std::forward<Tuple>(extra_args), make_seq_indices<0, sizeof...(ExtraArgs)>{});
146 }
147
148 private:
149 template <typename T, template <std::size_t...> class I, std::size_t... Indices>
150 inline std::function<plask::optional<ValueType>(std::size_t index)> apply_tuple(const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, InterpolationMethod method, T&& t, I<Indices...>) const {
151 return this->operator()(dst_mesh, std::get<Indices>(std::forward<T>(t))..., method);
152 }
153
154 template <typename T, template <std::size_t...> class I, std::size_t... Indices>
155 inline std::function<plask::optional<ValueType>(std::size_t index)> apply_tuple(EnumType num, const shared_ptr<const MeshD<OutputSpaceType::DIM>>& dst_mesh, InterpolationMethod method, T&& t, I<Indices...>) const {
156 return this->operator()(num, dst_mesh, std::get<Indices>(std::forward<T>(t))..., method);
157 }
158
159};
160
161 template <typename PropertyT, typename OutputSpaceType>
162 using DataSource = DataSourceImpl<PropertyT, PropertyT::propertyType, OutputSpaceType, typename PropertyT::ExtraParams>;
163
164// Hold reference to data source and destination mesh, base for LazyDataImpl returned by most DataSources
165/*template <typename DataSourceType>
166 struct DataSourceDataImpl: public LazyDataImpl<plask::optional<typename DataSourceType::ValueType>> {
167
168 const DataSourceType& data_src;
169 const MeshD<DataSourceType::DIM>& dst_mesh;
170
171 DataSourceDataImpl(const DataSourceType& data_src, const MeshD<DataSourceType::DIM>& dst_mesh): data_src(data_src), dst_mesh(dst_mesh) {}
172
173 std::size_t size() const override { return dst_mesh.size(); }
174
175};*/
176
177 template <typename PropertyT, typename OutputSpaceType, typename InputSpaceType = OutputSpaceType, typename OutputGeomObj = OutputSpaceType, typename InputGeomObj = InputSpaceType>
178 struct DataSourceWithReceiver: public DataSource<PropertyT, OutputSpaceType> {
179
180 protected:
181 //in, out obj can't be hold by shared_ptr, due to memory leak (circular reference)
182 const InputGeomObj* inputObj;
183 const OutputGeomObj* outputObj;
184 plask::optional<PathHints> path;
185 boost::signals2::connection geomConnectionIn;
186 boost::signals2::connection geomConnectionOut;
187
188 public:
189 ReceiverFor<PropertyT, InputSpaceType> in;
190
191 DataSourceWithReceiver() {
192 in.providerValueChanged.connect(
193 [&] (ReceiverBase&, ReceiverBase::ChangeReason reason) {
194 if (reason != ReceiverBase::ChangeReason::REASON_DELETE) this->changed();
195 }
196 );
197 }
198
199 ~DataSourceWithReceiver() {
200 disconnect();
201 }
202
203 void disconnect() {
204 geomConnectionIn.disconnect();
205 geomConnectionOut.disconnect();
206 }
207
212 virtual void calcConnectionParameters() = 0;
213
214 void setPath(const PathHints* path) {
215 if (path)
216 this->path = *path;
217 else
218 this->path = plask::optional<PathHints>();
219 }
220
221 const PathHints* getPath() const {
222 return path ? &*path : nullptr;
223 }
224
225 void inOrOutWasChanged(GeometryObject::Event& e) {
226 if (e.hasFlag(GeometryObject::Event::EVENT_DELETE)) disconnect(); else
227 if (e.hasFlag(GeometryObject::Event::EVENT_RESIZE)) calcConnectionParameters();
228 }
229
230 void connect(InputGeomObj& inputObj, OutputGeomObj& outputObj, const PathHints* path = nullptr) {
231 disconnect();
232 this->setPath(path);
233 this->inputObj = &inputObj;
234 this->outputObj = &outputObj;
235 geomConnectionOut = outputObj.changedConnectMethod(this, &DataSourceWithReceiver::inOrOutWasChanged);
236 geomConnectionIn = inputObj.changedConnectMethod(this, &DataSourceWithReceiver::inOrOutWasChanged);
237 calcConnectionParameters();
238 }
239};
240
241 template <typename PropertyT, typename OutputSpaceType, typename InputSpaceType = OutputSpaceType, typename OutputGeomObj = OutputSpaceType, typename InputGeomObj = InputSpaceType>
242 struct InnerDataSource: public DataSourceWithReceiver<PropertyT, OutputSpaceType, InputSpaceType, OutputGeomObj, InputGeomObj> {
243
244 typedef typename Primitive<OutputSpaceType::DIM>::Box OutBox;
245 typedef Vec<OutputSpaceType::DIM, double> OutVec;
246
247 struct Region {
248
250 OutBox inGeomBB;
251
253 OutVec inTranslation;
254
255 Region(const OutBox& inGeomBB, const OutVec& inTranslation)
256 : inGeomBB(inGeomBB), inTranslation(inTranslation) {}
257
258 };
259
260 std::vector<Region> regions;
261
262 const Region* findRegion(const OutVec& p) const {
263 for (const Region& r: regions)
264 if (r.inGeomBB.contains(p)) return &r;
265 return nullptr;
266 }
267
268 std::size_t findRegionIndex(const OutVec& p) const {
269 for (std::size_t i = 0; i < regions.size(); ++i)
270 if (regions[i].inGeomBB.contains(p)) return i;
271 return regions.size();
272 }
273
277 template <typename Predicate>
278 const Region* findRegion(const OutVec& p, Predicate pred) const {
279 for (const Region& r: regions)
280 if (r.inGeomBB.contains(p) && pred(r))
281 return &r;
282 return nullptr;
283 }
284
285 template <typename Predicate>
286 std::size_t findRegionIndex(const OutVec& p, Predicate pred) const {
287 for (std::size_t i = 0; i < regions.size(); ++i)
288 if (regions[i].inGeomBB.contains(p) && pred(regions[i])) return i;
289 return regions.size();
290 }
291
292 void calcConnectionParameters() override {
293 regions.clear();
294 std::vector<OutVec> pos = this->outputObj->getObjectPositions(*this->inputObj, this->getPath());
295 for (auto& p: pos) {
296 if (isnan(p))
297 throw plask::Exception("filter error: the place of some source geometry inside a destination geometry can't be described by translation.\nThis can be caused by flip or mirror on the path from the source to the destination.");
298 }
299 std::vector<OutBox> bb = this->outputObj->getObjectBoundingBoxes(*this->inputObj, this->getPath());
300 for (std::size_t i = 0; i < pos.size(); ++i)
301 regions.emplace_back(bb[i], pos[i]);
302 }
303
304};
305
306/*template <typename DataSourceType, typename... ExtraArgs>
307 struct InnerLazySourceImpl { //template for base class
308
309 std::vector<LazyData<typename DataSourceType::ValueType>> dataForRegion;
310
311 const DataSourceType& source;
312
313 const shared_ptr<const MeshD<DataSourceType::OutputSpaceType::DIM>> dst_mesh;
314
315 std::tuple<ExtraArgs...> extra_args;
316
317 InterpolationMethod method;
318
319 InnerLazySourceImpl(const DataSourceType& source, const shared_ptr<const MeshD<DataSourceType::OutputSpaceType::DIM>>& dst_mesh,
320 ExtraArgs... extra_args, InterpolationMethod method)
321 : dataForRegion(source.regions.size()), source(source), dst_mesh(dst_mesh), extra_args(extra_args...), method(method)
322 {}
323};*/
324
326 template <typename PropertyT, typename OutputSpaceType, typename InputSpaceType = OutputSpaceType, typename OutputGeomObj = OutputSpaceType, typename InputGeomObj = InputSpaceType>
327 struct OuterDataSource: public DataSourceWithReceiver<PropertyT, OutputSpaceType, InputSpaceType, OutputGeomObj, InputGeomObj> {
328
329 Vec<InputGeomObj::DIM, double> inTranslation;
330
331 void calcConnectionParameters() override {
332 std::vector<Vec<InputGeomObj::DIM, double>> pos = this->inputObj->getObjectPositions(*this->outputObj, this->getPath());
333 if (pos.size() != 1) throw Exception("inner output geometry object has not unambiguous position in outer input geometry object.");
334 inTranslation = pos[0];
335 }
336
337};
338
340 template <typename PropertyT, PropertyType propertyType, typename OutputSpaceType, typename VariadicTemplateTypesHolder>
341 struct ConstDataSourceImpl {
342 static_assert(propertyType == FIELD_PROPERTY || propertyType == MULTI_FIELD_PROPERTY,
343 "filter data sources can't be used with value properties (it can be used only with field properties)");
344};
345
346 template <typename PropertyT, typename OutputSpaceType, typename... ExtraArgs>
347 struct ConstDataSourceImpl<PropertyT, FIELD_PROPERTY, OutputSpaceType, VariadicTemplateTypesHolder<ExtraArgs...>>
348 : public DataSource<PropertyT, OutputSpaceType> {
349
350 public:
351
353 typedef typename PropertyAt<PropertyT, OutputSpaceType>::ValueType ValueType;
354
355 ValueType value;
356
357 ConstDataSourceImpl(const ValueType& value): value(value) {}
358
359 std::function<plask::optional<ValueType>(std::size_t index)> operator()(const shared_ptr<const MeshD<OutputSpaceType::DIM>>&, ExtraArgs..., InterpolationMethod) const override {
360 return [=](std::size_t) { return value; };
361 }
362
363};
364
365 template <typename PropertyT, typename OutputSpaceType, typename... ExtraArgs>
366 struct ConstDataSourceImpl<PropertyT, MULTI_FIELD_PROPERTY, OutputSpaceType, VariadicTemplateTypesHolder<ExtraArgs...>>
367 : public DataSource<PropertyT, OutputSpaceType> {
368
369 public:
370
372 typedef typename PropertyAt<PropertyT, OutputSpaceType>::ValueType ValueType;
373
374 ValueType value;
375
376 ConstDataSourceImpl(const ValueType& value): value(value) {}
377
378 std::function<plask::optional<ValueType>(std::size_t index)> operator()(typename PropertyT::EnumType, const shared_ptr<const MeshD<OutputSpaceType::DIM>>&, ExtraArgs..., InterpolationMethod) const override {
379 return [=](std::size_t) { return value; };
380 }
381
382 size_t size() const override { return 1; }
383};
384
385 template <typename PropertyT, typename OutputSpaceType>
386 using ConstDataSource = ConstDataSourceImpl<PropertyT, PropertyT::propertyType, OutputSpaceType, typename PropertyT::ExtraParams>;
387
388} // plask
389
390#endif // PLASK__FILTER__BASE_H