PLaSK library

Loading...
Searching...
No Matches
object.cpp
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#include <boost/algorithm/string/join.hpp>
15
16#include "object.hpp"
17#include "leaf.hpp"
18#include "transform.hpp"
19#include "space.hpp"
20#include "path.hpp"
21#include "reader.hpp"
22
23 namespace plask {
24
25 GeometryObject::CompositeChanger::CompositeChanger(const Changer* changer) {
26 changers.push_back(changer);
27}
28
29 GeometryObject::CompositeChanger& GeometryObject::CompositeChanger::operator()(const Changer* changer) {
30 changers.push_back(changer);
31 return *this;
32}
33
34 GeometryObject::CompositeChanger::~CompositeChanger() {
35 for (auto c: changers) delete c;
36}
37
38 bool GeometryObject::CompositeChanger::apply(shared_ptr<GeometryObject> &to_change, Vec<3, double>* translation) const {
39 for (auto c: changers) if (c->apply(to_change, translation)) return true;
40 return false;
41}
42
43 bool GeometryObject::ReplaceChanger::apply(shared_ptr<GeometryObject> &to_change, Vec<3, double>* translation) const {
44 if (to_change != from) return false;
45 to_change = to;
46 if (translation) *translation = this->translation;
47 return true;
48}
49
50 GeometryObject::ToBlockChanger::ToBlockChanger(shared_ptr<const GeometryObject> toChange,
51 const SolidOrGradientMaterial& material,
52 bool draft) {
53 from = toChange;
54 to = changeToBlock(material, from, translation, draft);
55}
56
57 bool GeometryObject::DeleteChanger::apply(shared_ptr<GeometryObject>& to_change, Vec<3, double>* /*translation*/) const {
58 if (to_change != toDel) return false;
59 to_change = shared_ptr<GeometryObject>();
60 return true;
61}
62
63 void GeometryObject::WriteXMLCallback::prerareToAutonaming(const GeometryObject &subtree_root) {
64 subtree_root.forEachRealObjectInSubtree([&](const GeometryObject& e) { return ++this->counts[&e] == 1; });
65}
66
67std::string GeometryObject::WriteXMLCallback::getName(const GeometryObject&, AxisNames&) const {
68 return std::string();
69}
70
71std::vector<std::string> GeometryObject::WriteXMLCallback::getPathNames(const GeometryObject&, const GeometryObject&, std::size_t) const {
72 return std::vector<std::string>();
73}
74
75 XMLWriter::Element GeometryObject::WriteXMLCallback::makeTag(XMLElement &parent_tag, const GeometryObject &object, AxisNames &axesNames) {
76 auto saved_name = names_of_saved.find(&object);
77 if (saved_name != names_of_saved.end()) {
78 XMLWriter::Element ref(parent_tag, "again");
79 ref.attr("ref", saved_name->second);
80 return ref;
81 }
82 XMLWriter::Element tag(parent_tag, object.getTypeName());
83 AxisNames newAxesNames = axesNames;
84 std::string name = getName(object, newAxesNames);
85 if (name.empty()) { // check if auto-name should be constructed
86 auto c = counts.find(&object);
87 if (c != counts.end() && c->second > 1) { //only for non-unique objects
88 name += "#";
89 name += boost::lexical_cast<std::string>(nextAutoName);
90 ++nextAutoName;
91 }
92 }
93 if (!name.empty()) {
94 tag.attr("name", name);
95 names_of_saved[&object] = name;
96 }
97 if (!object.roles.empty()) {
98 tag.attr("role", boost::join(object.roles, ","));
99 }
100 if (axesNames != newAxesNames) {
101 axesNames = std::move(newAxesNames);
102 tag.attr("axes", axesNames.str());
103 }
104 return tag;
105}
106
107 XMLElement GeometryObject::WriteXMLCallback::makeChildTag(XMLElement& container_tag, const GeometryObject& /*container*/, std::size_t /*index_of_child_in_parent*/) const {
108 XMLElement tag(container_tag, "item");
109 //TODO get paths
110 return tag;
111}
112
113 GeometryObject::~GeometryObject() {
114 fireChanged(Event::EVENT_DELETE);
115}
116
117 void GeometryObject::writeXML(XMLWriter::Element& parent_xml_object, WriteXMLCallback& write_cb, AxisNames axes) const {
118 XMLWriter::Element tag = write_cb.makeTag(parent_xml_object, *this, axes);
119 if (WriteXMLCallback::isRef(tag)) return;
120 writeXMLAttr(tag, axes);
121 writeXMLChildren(tag, write_cb, axes);
122}
123
124 template<int DIMS>
125 shared_ptr< GeometryObjectD<DIMS> > GeometryObject::asD() {
126 if (getDimensionsCount() != DIMS || isGeometry()) return shared_ptr< GeometryObjectD<DIMS> >();
127 return static_pointer_cast< GeometryObjectD<DIMS> >(shared_from_this());
128}
129
130 template<int DIMS>
131 shared_ptr< const GeometryObjectD<DIMS> > GeometryObject::asD() const {
132 if (getDimensionsCount() != DIMS || isGeometry()) return shared_ptr< const GeometryObjectD<DIMS> >();
133 return static_pointer_cast< const GeometryObjectD<DIMS> >(shared_from_this());
134}
135
136 template shared_ptr< GeometryObjectD<2> > GeometryObject::asD<2>();
137 template shared_ptr< GeometryObjectD<3> > GeometryObject::asD<3>();
138 template shared_ptr< const GeometryObjectD<2> > GeometryObject::asD<2>() const;
139 template shared_ptr< const GeometryObjectD<3> > GeometryObject::asD<3>() const;
140
141 shared_ptr<Geometry> GeometryObject::asGeometry() {
142 return isGeometry() ? static_pointer_cast<Geometry>(shared_from_this()) : shared_ptr<Geometry>();
143}
144
145 shared_ptr<const Geometry> GeometryObject::asGeometry() const {
146 return isGeometry() ? static_pointer_cast<const Geometry>(shared_from_this()) : shared_ptr<const Geometry>();
147}
148
149 bool GeometryObject::hasInSubtree(const GeometryObject &el) const {
150 if (&el == this) return true;
151 std::size_t c = getRealChildrenCount();
152 for (std::size_t i = 0; i < c; ++i)
153 if (getRealChildNo(i)->hasInSubtree(el))
154 return true;
155 return false;
156}
157
158 bool GeometryObject::Subtree::hasBranches() const {
159 const std::vector<Subtree>* c = &children;
160 while (!c->empty()) {
161 if (c->size() > 1) return true;
162 c = &((*c)[0].children);
163 }
164 return false;
165}
166
167 Path GeometryObject::Subtree::toLinearPath() const {
168 std::vector< shared_ptr<const GeometryObject> > result;
169 if (empty()) return result;
170 const GeometryObject::Subtree* path_nodes = this;
171 while (true) {
172 if (path_nodes->children.size() > 1) throw NotUniqueObjectException("there is more than one path in the subtree.");
173 result.push_back(path_nodes->object);
174 if (path_nodes->children.empty()) break;
175 path_nodes = &(path_nodes->children[0]);
176 }
177 return result;
178}
179
180 Path GeometryObject::Subtree::getLastPath() const {
181 std::vector< shared_ptr<const GeometryObject> > result;
182 if (empty()) return result;
183 const GeometryObject::Subtree* path_nodes = this;
184 while (true) {
185 result.push_back(path_nodes->object);
186 if (path_nodes->children.empty()) break;
187 path_nodes = &(path_nodes->children.back());
188 }
189 return result;
190}
191
192 void GeometryObject::ensureCanHasAsParent(const GeometryObject& potential_parent) const {
193 if (hasInSubtree(potential_parent))
194 throw CyclicReferenceException();
195}
196
197 void GeometryObject::writeXMLAttr(XMLWriter::Element& /*dest_xml_object*/, const AxisNames& /*axes*/) const {
198 // do nothing
199}
200
201 void GeometryObject::writeXMLChildren(XMLWriter::Element &dest_xml_object, GeometryObject::WriteXMLCallback &write_cb, const AxisNames &axes) const {
202 const std::size_t child_count = getRealChildrenCount();
203 for (std::size_t i = 0; i < child_count; ++i)
204 getRealChildNo(i)->writeXML(dest_xml_object, write_cb, axes);
205}
206
207std::size_t GeometryObject::getRealChildrenCount() const {
208 return getChildrenCount();
209}
210
211 shared_ptr<GeometryObject> GeometryObject::getRealChildNo(std::size_t child_no) const {
212 return getChildNo(child_no);
213}
214
215 void GeometryObject::removeAtUnsafe(std::size_t) {
216 throw NotImplemented("removeAtUnsafe(std::size_t)");
217}
218
219 void GeometryObject::forEachRealObjectInSubtree(std::function<bool (const GeometryObject &)> callback) const {
220 if (!callback(*this)) return;
221 std::size_t size = getRealChildrenCount();
222 for (std::size_t i = 0; i < size; ++i) getRealChildNo(i)->forEachRealObjectInSubtree(callback);
223}
224
225// --- GeometryObjectD ---
226
227 template <int dims>
228 shared_ptr<const GeometryObject> GeometryObjectD<dims>::getMatchingAt(const DVec& point, const Predicate& predicate, const plask::PathHints* path) const {
229 Subtree subtree = getPathsAt(point, false);
230 // Walk the subtree
231 const GeometryObject::Subtree* nodes = &subtree;
232 while (!nodes->empty()) {
233 if (predicate(*(nodes->object))) return nodes->object;
234 if (nodes->children.empty()) return shared_ptr<const GeometryObject>();
235 assert(nodes->children.size() == 1);
236 if (path && nodes->object->isContainer()) {
237 if (!path->includes(nodes->object, nodes->children.front().object))
238 return shared_ptr<const GeometryObject>();
239 }
240 nodes = &(nodes->children.front());
241 }
242 return shared_ptr<const GeometryObject>();
243}
244
245 template <int dims>
246std::set<std::string> GeometryObjectD<dims>::getRolesAt(const DVec& point, const plask::PathHints* path) const {
247 std::set<std::string> result;
248 getMatchingAt(point, [&](const GeometryObject& o)->bool { result.insert(o.roles.begin(), o.roles.end()); return false; }, path);
249 return result;
250}
251
252 template struct PLASK_API GeometryObjectD<2>;
253 template struct PLASK_API GeometryObjectD<3>;
254
255} // namespace plask