PLaSK library

Loading...
Searching...
No Matches
leaf.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_LEAF_H
15#define PLASK__GEOMETRY_LEAF_H
16
21#include "object.hpp"
22#include "reader.hpp"
23#include "../manager.hpp"
24#include "../material/db.hpp"
25
26 namespace plask {
27
28 class GeometryReader;
29
35 template <int dim> struct PLASK_API GeometryObjectLeaf : public GeometryObjectD<dim> {
36 typedef typename GeometryObjectD<dim>::DVec DVec;
37 typedef typename GeometryObjectD<dim>::Box Box;
38 using GeometryObjectD<dim>::getBoundingBox;
39 using GeometryObjectD<dim>::shared_from_this;
40
41 public:
42 struct PLASK_API MaterialProvider {
43 virtual shared_ptr<Material> getMaterial(const GeometryObjectLeaf<dim>& thisObj, const DVec& p) const = 0;
44
50 virtual shared_ptr<Material> singleMaterial() const = 0;
51
52 virtual MaterialProvider* clone() const = 0;
53
58 virtual shared_ptr<Material> getRepresentativeMaterial() const = 0;
59
60 virtual XMLWriter::Element& writeXML(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const = 0;
61
62 virtual bool isUniform(Primitive<3>::Direction direction) const = 0;
63
64 virtual ~MaterialProvider() {}
65 };
66
67 struct PLASK_API SolidMaterial : public MaterialProvider {
68 shared_ptr<Material> material;
69
70 SolidMaterial() = default;
71
72 SolidMaterial(shared_ptr<Material> material) : material(material) {}
73
74 virtual shared_ptr<Material> getMaterial(const GeometryObjectLeaf<dim>& PLASK_UNUSED(thisObj),
75 const DVec& PLASK_UNUSED(p)) const override {
76 return material;
77 }
78
79 shared_ptr<Material> singleMaterial() const override { return material; }
80
81 SolidMaterial* clone() const override { return new SolidMaterial(material); }
82
83 shared_ptr<Material> getRepresentativeMaterial() const override { return material; }
84
85 bool isUniform(Primitive<3>::Direction PLASK_UNUSED(direction)) const override { return true; }
86
87 XMLWriter::Element& writeXML(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const override;
88 };
89
90 struct PLASK_API GradientMaterial : public MaterialProvider {
91 shared_ptr<MaterialsDB::MixedCompositionFactory> materialFactory;
92
93 GradientMaterial(shared_ptr<MaterialsDB::MixedCompositionFactory> materialFactory)
94 : materialFactory(materialFactory) {}
95
96 shared_ptr<Material> getMaterial(const GeometryObjectLeaf<dim>& thisObj, const DVec& p) const override {
97 Box b = thisObj.getBoundingBox(); // TODO sth. faster. we only need vert() coordinates, we can also cache
98 // lower and height
99 return (*materialFactory)((p.vert() - b.lower.vert()) / b.height());
100 }
101
102 shared_ptr<Material> singleMaterial() const override { return shared_ptr<Material>(); }
103
104 GradientMaterial* clone() const override { return new GradientMaterial(materialFactory); }
105
106 shared_ptr<Material> getRepresentativeMaterial() const override { return (*materialFactory)(0.5); }
107
108 bool isUniform(Primitive<3>::Direction direction) const override {
109 return direction != Primitive<3>::DIRECTION_VERT;
110 }
111
112 XMLWriter::Element& writeXML(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const override;
113 };
114
115 struct PLASK_API DraftGradientMaterial : public GradientMaterial {
116
117 DraftGradientMaterial(shared_ptr<MaterialsDB::MixedCompositionFactory> materialFactory)
118 : GradientMaterial(materialFactory) {}
119
120 shared_ptr<Material> getMaterial(const GeometryObjectLeaf<dim>& thisObj, const DVec& p) const override {
121 return (*this->materialFactory)(0.5);
122 }
123
124 bool isUniform(Primitive<3>::Direction direction) const override { return true; }
125 };
126
127 protected:
128 std::unique_ptr<MaterialProvider> materialProvider;
129
130 public:
131 GeometryReader& readMaterial(GeometryReader& src);
132
133 // shared_ptr<Material> material; //TODO support for XML (checking if MixedCompositionFactory is solid), add
134 // singleMaterial
135
139 GeometryObjectLeaf<dim>() : materialProvider(new SolidMaterial()) {}
140
144 GeometryObjectLeaf<dim>(const GeometryObjectLeaf<dim>& src) : materialProvider(src.materialProvider->clone()) {}
145
150 GeometryObjectLeaf<dim>(shared_ptr<Material> material) : materialProvider(new SolidMaterial(material)) {}
151
157 GeometryObjectLeaf<dim>(shared_ptr<MaterialsDB::MixedCompositionFactory> materialTopBottom)
158 : materialProvider(new GradientMaterial(materialTopBottom)) {}
159
164 shared_ptr<Material> getRepresentativeMaterial() const { return materialProvider->getRepresentativeMaterial(); }
165
170 shared_ptr<Material> singleMaterial() const { return materialProvider->singleMaterial(); }
171
176 void setMaterial(shared_ptr<Material> new_material) {
177 materialProvider.reset(new SolidMaterial(new_material));
178 this->fireChanged();
179 }
180
185 void setMaterialFast(shared_ptr<Material> new_material) { materialProvider.reset(new SolidMaterial(new_material)); }
186
192 void setMaterialTopBottomCompositionFast(shared_ptr<MaterialsDB::MixedCompositionFactory> materialTopBottom) {
193 materialProvider.reset(new GradientMaterial(materialTopBottom));
194 }
195
201 void setMaterialTopBottomComposition(shared_ptr<MaterialsDB::MixedCompositionFactory> materialTopBottom) {
202 setMaterialTopBottomCompositionFast(materialTopBottom);
203 this->fireChanged();
204 }
205
211 void setMaterialDraftTopBottomCompositionFast(shared_ptr<MaterialsDB::MixedCompositionFactory> materialTopBottom) {
212 materialProvider.reset(new DraftGradientMaterial(materialTopBottom));
213 }
214
219 void setMaterialProviderFast(MaterialProvider* provider) { materialProvider.reset(provider); }
220
225 void setMaterialProvider(MaterialProvider* provider) {
226 setMaterialProviderFast(provider);
227 this->fireChanged();
228 }
229
233 const MaterialProvider* getMaterialProvider() const { return materialProvider.get(); }
234
235 GeometryObject::Type getType() const override;
236
237 shared_ptr<Material> getMaterial(const DVec& p) const override;
238
239 void getBoundingBoxesToVec(const GeometryObject::Predicate& predicate,
240 std::vector<Box>& dest,
241 const PathHints* path = 0) const override;
242
243 void getObjectsToVec(const GeometryObject::Predicate& predicate,
244 std::vector<shared_ptr<const GeometryObject>>& dest,
245 const PathHints* path = 0) const override;
246
247 void getPositionsToVec(const GeometryObject::Predicate& predicate,
248 std::vector<DVec>& dest,
249 const PathHints* = 0) const override;
250
251 bool hasInSubtree(const GeometryObject& el) const override;
252
253 GeometryObject::Subtree getPathsTo(const GeometryObject& el, const PathHints* path = 0) const override;
254
255 GeometryObject::Subtree getPathsAt(const DVec& point, bool = false) const override;
256
257 std::size_t getChildrenCount() const override { return 0; }
258
259 shared_ptr<GeometryObject> getChildNo(std::size_t child_no) const override;
260
261 shared_ptr<const GeometryObject> changedVersion(const GeometryObject::Changer& changer,
262 Vec<3, double>* translation = 0) const override;
263
264 shared_ptr<GeometryObject> deepCopy(
265 std::map<const GeometryObject*, shared_ptr<GeometryObject>>& copied) const override;
266
267 // void extractToVec(const GeometryObject::Predicate& predicate, std::vector< shared_ptr<const GeometryObjectD<dim>
268 // > >& dest, const PathHints* = 0) const {
269 // if (predicate(*this)) dest.push_back(static_pointer_cast< const GeometryObjectD<dim>
270 // >(this->shared_from_this()));
271 // }
272};
273
274 PLASK_API_EXTERN_TEMPLATE_STRUCT(GeometryObjectLeaf<2>)
275 PLASK_API_EXTERN_TEMPLATE_STRUCT(GeometryObjectLeaf<3>)
276
277
284 template <int dim> struct PLASK_API Block : public GeometryObjectLeaf<dim> {
286 typedef typename GeometryObjectLeaf<dim>::DVec DVec;
287
289 typedef typename GeometryObjectLeaf<dim>::Box Box;
290
291 static const char* NAME;
292
293 std::string getTypeName() const override;
294
298 DVec size;
299
304 void setSize(DVec&& new_size) {
305 for (int i = 0; i != dim; ++i)
306 if (new_size[i] < 0.) new_size[i] = 0.;
307 size = new_size;
308 this->fireChanged(GeometryObject::Event::EVENT_RESIZE);
309 }
310
315 template <typename... VecCtrArg> void setSize(VecCtrArg&&... vecCtrArg) {
316 this->setSize(DVec(std::forward<VecCtrArg>(vecCtrArg)...));
317 }
318
324 explicit Block(const DVec& size = Primitive<dim>::ZERO_VEC,
325 const shared_ptr<Material>& material = shared_ptr<Material>())
326 : GeometryObjectLeaf<dim>(material), size(size) {
327 for (int i = 0; i != dim; ++i)
328 if (size[i] < 0.) this->size[i] = 0.;
329 }
330
331 explicit Block(const DVec& size, shared_ptr<MaterialsDB::MixedCompositionFactory> materialTopBottom)
332 : GeometryObjectLeaf<dim>(materialTopBottom), size(size) {}
333
334 explicit Block(const Block& src) : GeometryObjectLeaf<dim>(src), size(src.size) {}
335
336 Box getBoundingBox() const override;
337
338 bool contains(const DVec& p) const override;
339
340 // bool intersects(const Box& area) const { return this->getBoundingBox().intersects(area); }
341
342 shared_ptr<GeometryObject> shallowCopy() const override { return make_shared<Block>(*this); }
343
344 void addPointsAlongToSet(std::set<double>& points,
345 Primitive<3>::Direction direction,
346 unsigned max_steps,
347 double min_step_size) const override;
348
349 void addLineSegmentsToSet(std::set<typename GeometryObjectD<dim>::LineSegment>& segments,
350 unsigned max_steps,
351 double min_step_size) const override;
352
353 void writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const override;
354};
355
356 template <> void Block<2>::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const;
357 template <> void Block<3>::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const;
358
359 template <>
360 void Block<2>::addLineSegmentsToSet(std::set<typename GeometryObjectD<2>::LineSegment>& segments,
361 unsigned max_steps,
362 double min_step_size) const;
363 template <>
364 void Block<3>::addLineSegmentsToSet(std::set<typename GeometryObjectD<3>::LineSegment>& segments,
365 unsigned max_steps,
366 double min_step_size) const;
367
368 PLASK_API_EXTERN_TEMPLATE_STRUCT(Block<2>)
369 PLASK_API_EXTERN_TEMPLATE_STRUCT(Block<3>)
370
371
379 PLASK_API shared_ptr<GeometryObject> changeToBlock(const SolidOrGradientMaterial& material,
380 const shared_ptr<const GeometryObject>& to_change,
381 Vec<3, double>& translation, bool draft = false);
382
383
384 namespace details {
385
386 // Read alternative attributes
387 inline static double readAlternativeAttrs(GeometryReader& reader, const std::string& attr1, const std::string& attr2) {
388 auto value1 = reader.source.getAttribute<double>(attr1);
389 auto value2 = reader.source.getAttribute<double>(attr2);
390 if (value1) {
391 if (value2) throw XMLConflictingAttributesException(reader.source, attr1, attr2);
392 if (*value1 < 0.) throw XMLBadAttrException(reader.source, attr1, boost::lexical_cast<std::string>(*value1));
393 return *value1;
394 } else {
395 if (!value2) {
396 if (reader.manager.draft)
397 return 0.0;
398 else
399 throw XMLNoAttrException(reader.source, format("{0}' or '{1}", attr1, attr2));
400 }
401 if (*value2 < 0.) throw XMLBadAttrException(reader.source, attr2, boost::lexical_cast<std::string>(*value2));
402 return *value2;
403 }
404 }
405
406 template <typename BlockType> inline static void setupBlock2D3D(GeometryReader& reader, BlockType& block) {
407 block.size.tran() = readAlternativeAttrs(reader, "d" + reader.getAxisTranName(), "width");
408 block.size.vert() = readAlternativeAttrs(reader, "d" + reader.getAxisVertName(), "height");
409 block.readMaterial(reader);
410 reader.source.requireTagEnd();
411 }
412}
413
414 typedef Block<2> Rectangle;
415 typedef Block<3> Cuboid;
416
417} // namespace plask
418
419#endif // PLASK__GEOMETRY_LEAF_H