PLaSK library

Loading...
Searching...
No Matches
transform.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__GEOMETRY_TRANSFORM_H
15#define PLASK__GEOMETRY_TRANSFORM_H
16
17#define BOOST_BIND_GLOBAL_PLACEHOLDERS
18#include <boost/bind.hpp>
19#include "object.hpp"
20//#include <functional>
21
22 namespace plask {
23
32 template <int dim, typename Child_Type = GeometryObjectD<dim>>
33 struct GeometryObjectTransform : public GeometryObjectD<dim> {
34 typedef typename GeometryObjectD<dim>::DVec DVec;
35 typedef typename GeometryObjectD<dim>::Box Box;
36 typedef Child_Type ChildType;
37
38 explicit GeometryObjectTransform(shared_ptr<ChildType> child = nullptr) : _child(child) { connectOnChildChanged(); }
39
40 explicit GeometryObjectTransform(ChildType& child)
41 : _child(static_pointer_cast<ChildType>(child.shared_from_this())) {
42 connectOnChildChanged();
43 }
44
45 virtual ~GeometryObjectTransform() { disconnectOnChildChanged(); }
46
47 GeometryObject::Type getType() const override { return GeometryObject::TYPE_TRANSFORM; }
48
49 /*virtual void getLeafsToVec(std::vector< shared_ptr<const GeometryObject> >& dest) const {
50 getChild()->getLeafsToVec(dest);
51 }*/
52
53 void getObjectsToVec(const GeometryObject::Predicate& predicate,
54 std::vector<shared_ptr<const GeometryObject>>& dest,
55 const PathHints* path = 0) const override {
56 if (predicate(*this)) {
57 dest.push_back(this->shared_from_this());
58 } else {
59 if (hasChild()) _child->getObjectsToVec(predicate, dest, path);
60 }
61 }
62
64 virtual void onChildChanged(const GeometryObject::Event& evt) {
65 this->fireChanged(evt.originalSource(), evt.flagsForParent());
66 }
67
69 void connectOnChildChanged() {
70 if (hasChild())
71 _child->changed.connect(boost::bind(&GeometryObjectTransform<dim, Child_Type>::onChildChanged, this, _1));
72 }
73
75 void disconnectOnChildChanged() {
76 if (hasChild())
77 _child->changed.disconnect(
78 boost::bind(&GeometryObjectTransform<dim, Child_Type>::onChildChanged, this, _1));
79 }
80
85 inline shared_ptr<ChildType> getChild() const { return _child; }
86
93 void setChildUnsafe(const shared_ptr<ChildType>& child) {
94 if (child == _child) return;
95 disconnectOnChildChanged();
96 _child = child;
97 connectOnChildChanged();
98 }
99
106 void setChild(const shared_ptr<ChildType>& child) {
107 // if (!child) throw NoChildException();
108 if (child == _child) return;
109 if (child) this->ensureCanHaveAsChild(*child);
110 setChildUnsafe(child);
111 this->fireChildrenChanged();
112 }
113
117 bool hasChild() const { return _child != nullptr; }
118
122 void validate() const override {
123 if (!hasChild()) throw NoChildException();
124 }
125
126 bool hasInSubtree(const GeometryObject& el) const override {
127 return &el == this || (hasChild() && _child->hasInSubtree(el));
128 }
129
130 GeometryObject::Subtree getPathsTo(const GeometryObject& el, const PathHints* path = 0) const override {
131 if (this == &el) return GeometryObject::Subtree(this->shared_from_this());
132 if (!hasChild()) GeometryObject::Subtree();
133 GeometryObject::Subtree e = _child->getPathsTo(el, path);
134 if (e.empty()) return GeometryObject::Subtree();
135 GeometryObject::Subtree result(this->shared_from_this());
136 result.children.push_back(std::move(e));
137 return result;
138 }
139
140 std::size_t getChildrenCount() const override { return hasChild() ? 1 : 0; }
141
142 shared_ptr<GeometryObject> getChildNo(std::size_t child_no) const override {
143 if (!hasChild() || child_no > 0) throw OutOfBoundsException("geometryObjectTransform::getChildNo", "child_no");
144 return _child;
145 }
146
152 shared_ptr<GeometryObjectTransform<dim, Child_Type>> shallowCopyWithChild(
153 const shared_ptr<ChildType>& child) const {
154 shared_ptr<GeometryObjectTransform<dim, Child_Type>> result =
155 static_pointer_cast<GeometryObjectTransform<dim, Child_Type>>(this->shallowCopy());
156 result->setChild(child);
157 result->roles = this->roles;
158 return result;
159 }
160
161 shared_ptr<GeometryObject> deepCopy(
162 std::map<const GeometryObject*, shared_ptr<GeometryObject>>& copied) const override {
163 auto found = copied.find(this);
164 if (found != copied.end()) return found->second;
165 shared_ptr<GeometryObjectTransform<dim, Child_Type>> result =
166 static_pointer_cast<GeometryObjectTransform<dim, Child_Type>>(this->shallowCopy());
167 copied[this] = result;
168 if (hasChild()) result->setChild(dynamic_pointer_cast<ChildType>(_child->deepCopy(copied)));
169 return result;
170 }
171
172 shared_ptr<const GeometryObject> changedVersion(const GeometryObject::Changer& changer,
173 Vec<3, double>* translation = 0) const override {
174 shared_ptr<GeometryObject> result(const_pointer_cast<GeometryObject>(this->shared_from_this()));
175 if (changer.apply(result, translation) || !hasChild()) return result;
176 shared_ptr<const GeometryObject> new_child = _child->changedVersion(changer, translation);
177 if (!new_child) return shared_ptr<const GeometryObject>(); // child was deleted, so we also should be
178 return new_child == _child ? result
179 : shallowCopyWithChild(const_pointer_cast<ChildType>(
180 dynamic_pointer_cast<const ChildType>(new_child)));
181 }
182
183 void removeAtUnsafe(std::size_t) override { _child.reset(); }
184
190 virtual Box fromChildCoords(const typename ChildType::Box& child_bbox) const = 0;
191
192 Box getBoundingBox() const override {
193 return this->hasChild() ? this->fromChildCoords(this->_child->getBoundingBox())
194 : Box(Primitive<dim>::ZERO_VEC, Primitive<dim>::ZERO_VEC);
195 }
196
197 void getBoundingBoxesToVec(const GeometryObject::Predicate& predicate,
198 std::vector<Box>& dest,
199 const PathHints* path) const override {
200 if (predicate(*this)) {
201 dest.push_back(this->getBoundingBox());
202 return;
203 }
204 if (!hasChild()) return;
205 auto child_boxes = this->_child->getBoundingBoxes(predicate, path);
206 dest.reserve(dest.size() + child_boxes.size());
207 for (auto& r : child_boxes) dest.push_back(this->fromChildCoords(r));
208 }
209
215 inline bool childHasType(GeometryObject::Type type) const { return hasChild() && (_child->getType() == type); }
216
217 protected:
218 shared_ptr<ChildType> _child;
219
224 template <typename ThisType>
225 inline static void _getNotChangedPositionsToVec(ThisType _this,
226 const GeometryObject::Predicate& predicate,
227 std::vector<DVec>& dest,
228 const PathHints* path) {
229 if (predicate(*_this)) {
230 dest.push_back(Primitive<dim>::ZERO_VEC);
231 return;
232 }
233 if (_this->hasChild()) _this->_child->getPositionsToVec(predicate, dest, path);
234 }
235};
236
244 template <int this_dim, int child_dim = 5 - this_dim, typename ChildType = GeometryObjectD<child_dim>>
245 struct GeometryObjectTransformSpace : public GeometryObjectTransform<this_dim, ChildType> {
246 typedef typename ChildType::Box ChildBox;
247 typedef typename ChildType::DVec ChildVec;
248 typedef typename GeometryObjectTransform<this_dim, ChildType>::DVec DVec;
249 using GeometryObjectTransform<this_dim, ChildType>::getChild;
250
251 explicit GeometryObjectTransformSpace(shared_ptr<ChildType> child = shared_ptr<ChildType>())
252 : GeometryObjectTransform<this_dim, ChildType>(child) {}
253
255 GeometryObject::Type getType() const override { return GeometryObject::TYPE_SPACE_CHANGER; }
256
257 /*virtual std::vector< std::tuple<shared_ptr<const GeometryObject>, DVec> > getLeafsWithTranslations() const {
258 std::vector< shared_ptr<const GeometryObject> > v = getChild()->getLeafs();
259 std::vector< std::tuple<shared_ptr<const GeometryObject>, DVec> > result(v.size());
260 std::transform(v.begin(), v.end(), result.begin(), [](shared_ptr<const GeometryObject> e) {
261 return std::make_pair(e, Primitive<this_dim>::NAN_VEC);
262 });
263 return result;
264 }*/
265};
266
271 template <int dim> struct PLASK_API Translation : public GeometryObjectTransform<dim> {
272 typedef GeometryObjectTransform<dim> BaseClass;
273
274 static const char* NAME;
275
276 std::string getTypeName() const override;
277
278 typedef typename BaseClass::ChildType ChildType;
279
281 typedef typename BaseClass::DVec DVec;
282
284 typedef typename BaseClass::Box Box;
285
286 using BaseClass::getChild;
287
291 DVec translation;
292
293 // Translation(const Translation<dim>& translation) = default;
294
299 explicit Translation(shared_ptr<GeometryObjectD<dim>> child = shared_ptr<GeometryObjectD<dim>>(),
300 const DVec& translation = Primitive<dim>::ZERO_VEC)
301 : BaseClass(child), translation(translation) {}
302
303 explicit Translation(GeometryObjectD<dim>& child, const DVec& translation = Primitive<dim>::ZERO_VEC)
304 : BaseClass(child), translation(translation) {}
305
315 static shared_ptr<Translation<dim>> compress(
316 shared_ptr<GeometryObjectD<dim>> child_or_translation = shared_ptr<GeometryObjectD<dim>>(),
317 const DVec& translation = Primitive<dim>::ZERO_VEC);
318
319 shared_ptr<Material> getMaterial(const DVec& p) const override;
320
321 bool contains(const DVec& p) const override;
322
323 // TODO to use (impl. is good) or remove
324 /*virtual bool intersects(const Box& area) const {
325 return getChild()->intersects(area.translated(-translation));
326 }*/
327
328 using GeometryObjectTransform<dim>::getPathsTo;
329
330 GeometryObject::Subtree getPathsAt(const DVec& point, bool all = false) const override;
331
332 /*virtual void getLeafsInfoToVec(std::vector< std::tuple<shared_ptr<const GeometryObject>, Box, DVec> >& dest, const
333 PathHints* path = 0) const { const std::size_t old_size = dest.size(); getChild()->getLeafsInfoToVec(dest, path);
334 for (auto i = dest.begin() + old_size; i != dest.end(); ++i) {
335 std::get<1>(*i).translate(translation);
336 std::get<2>(*i) += translation;
337 }
338 }*/
339
340 Box fromChildCoords(const typename ChildType::Box& child_bbox) const override;
341
342 /*virtual std::vector< std::tuple<shared_ptr<const GeometryObject>, DVec> > getLeafsWithTranslations() const {
343 std::vector< std::tuple<shared_ptr<const GeometryObject>, DVec> > result =
344 getChild()->getLeafsWithTranslations(); for (std::tuple<shared_ptr<const GeometryObject>, DVec>& r: result)
345 std::get<1>(r) += translation; return result;
346 }*/
347
348 virtual void getPositionsToVec(const GeometryObject::Predicate& predicate,
349 std::vector<DVec>& dest,
350 const PathHints* path = 0) const override;
351
356 shared_ptr<Translation<dim>> copyShallow() const {
357 return shared_ptr<Translation<dim>>(new Translation<dim>(getChild(), translation));
358 }
359
360 shared_ptr<GeometryObject> shallowCopy() const override;
361
362 virtual shared_ptr<const GeometryObject> changedVersion(const GeometryObject::Changer& changer,
363 Vec<3, double>* translation = 0) const override;
364
369 shared_ptr<Translation<dim>> copyShallow(const DVec& new_translation) const {
370 return shared_ptr<Translation<dim>>(new Translation<dim>(getChild(), new_translation));
371 }
372
373 void writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const override;
374
375 // void extractToVec(const GeometryObject::Predicate &predicate, std::vector< shared_ptr<const GeometryObjectD<dim>
376 // > >& dest, const PathHints *path) const;
377
378 void addPointsAlongToSet(std::set<double>& points,
379 Primitive<3>::Direction direction,
380 unsigned max_steps,
381 double min_step_size) const override;
382
383 void addLineSegmentsToSet(std::set<typename GeometryObjectD<dim>::LineSegment>& segments,
384 unsigned max_steps,
385 double min_step_size) const override;
386};
387
388 template <> void Translation<2>::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const;
389 template <> void Translation<3>::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const;
390
391 PLASK_API_EXTERN_TEMPLATE_STRUCT(Translation<2>)
392 PLASK_API_EXTERN_TEMPLATE_STRUCT(Translation<3>)
393
394} // namespace plask
395
396#endif // PLASK__GEOMETRY_TRANSFORM_H