PLaSK library

Loading...
Searching...
No Matches
extruded_triangular3d.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__MESH_EXTRUDED_TRIANGULAR3D_H
15#define PLASK__MESH_EXTRUDED_TRIANGULAR3D_H
16
17#include "axis1d.hpp"
18#include "triangular2d.hpp"
19
20#include <boost/icl/interval_set.hpp>
21#include <boost/icl/closed_interval.hpp>
22
23 namespace plask {
24
28 struct PLASK_API ExtrudedTriangularMesh3D: public MeshD<3> {
29
30 typedef plask::Boundary<ExtrudedTriangularMesh3D> Boundary;
31
32 TriangularMesh2D longTranMesh;
33
34 shared_ptr<MeshAxis> vertAxis;
35
37 bool vertFastest;
38
42 struct PLASK_API Element {
43 const ExtrudedTriangularMesh3D& mesh;
44 std::size_t longTranIndex, vertIndex;
45
46 Element(const ExtrudedTriangularMesh3D& mesh, std::size_t longTranIndex, std::size_t vertIndex)
47 : mesh(mesh), longTranIndex(longTranIndex), vertIndex(vertIndex) {}
48
49 Element(const ExtrudedTriangularMesh3D& mesh, std::size_t elementIndex);
50
52 std::size_t getIndex() const { return mesh.elementIndex(longTranIndex, vertIndex); }
53
59 std::size_t getBottomNodeIndex(std::size_t bottom_triangle_node_nr) const {
60 return mesh.index(longTranElement().getNodeIndex(bottom_triangle_node_nr), vertIndex);
61 }
62
68 std::size_t getTopNodeIndex(std::size_t top_triangle_node_nr) const {
69 return mesh.index(longTranElement().getNodeIndex(top_triangle_node_nr), vertIndex+1);
70 }
71
77 Vec<3, double> getBottomNode(std::size_t bottom_triangle_node_nr) const {
78 return mesh.at(longTranElement().getNodeIndex(bottom_triangle_node_nr), vertIndex);
79 }
80
86 Vec<3, double> getTopNode(std::size_t bottom_triangle_node_nr) const {
87 return mesh.at(longTranElement().getNodeIndex(bottom_triangle_node_nr), vertIndex+1);
88 }
89
91 Vec<3, double> getMidpoint() const;
92
97 double getBaseArea() const { return longTranElement().getArea(); }
98
103 double getHeight() const { return mesh.vertAxis->at(vertIndex+1) - mesh.vertAxis->at(vertIndex); }
104
106
110 double getArea() const { return getBaseArea() * getHeight(); }
111 double getVolume() const { return getArea(); }
113
119 bool contains(Vec<3, double> p) const;
120
125 Box3D getBoundingBox() const;
126
127 private:
128 TriangularMesh2D::Element longTranElement() const { return mesh.longTranMesh.element(longTranIndex); }
129 };
130
136 class PLASK_API Elements {
137
138 static inline Element deref(const ExtrudedTriangularMesh3D& mesh, std::size_t index) { return mesh.getElement(index); }
139 public:
140 typedef IndexedIterator<const ExtrudedTriangularMesh3D, Element, deref> const_iterator;
141 typedef const_iterator iterator;
142
143 const ExtrudedTriangularMesh3D* mesh;
144
145 explicit Elements(const ExtrudedTriangularMesh3D& mesh): mesh(&mesh) {}
146
147 Element at(std::size_t index) const {
148 if (index >= mesh->getElementsCount())
149 throw OutOfBoundsException("extrudedTriangularMesh3D::Elements::at", "index", index, 0, mesh->getElementsCount()-1);
150 return Element(*mesh, index);
151 }
152
153 Element operator[](std::size_t index) const {
154 return Element(*mesh, index);
155 }
156
161 std::size_t size() const { return mesh->getElementsCount(); }
162
163 bool empty() const { return (mesh->vertAxis->size() <= 1) || (mesh->longTranMesh.getElementsCount() == 0); }
164
166 const_iterator begin() const { return const_iterator(mesh, 0); }
167
169 const_iterator end() const { return const_iterator(mesh, size()); }
170 };
171
172 class ElementMesh;
173
178 shared_ptr<ElementMesh> getElementMesh() const { return make_shared<ElementMesh>(this); }
179
181 Elements elements() const { return Elements(*this); }
182 Elements getElements() const { return elements(); }
183
185
190 Element element(std::size_t elementIndex) const { return Element(*this, elementIndex); }
191 Element getElement(std::size_t elementIndex) const { return element(elementIndex); }
193
194 Vec<3, double> at(std::size_t index) const override;
195
196 std::size_t size() const override;
197
198 bool empty() const override;
199
200 void writeXML(XMLElement& object) const override;
201
208 Vec<3, double> at(std::size_t longTranIndex, std::size_t vertIndex) const;
209
216 std::size_t index(std::size_t longTranIndex, std::size_t vertIndex) const {
217 return vertFastest ?
218 longTranIndex * vertAxis->size() + vertIndex :
219 vertIndex * longTranMesh.size() + longTranIndex;
220 }
221
227 std::pair<std::size_t, std::size_t> longTranAndVertIndices(std::size_t index) const;
228
234 std::size_t vertIndex(std::size_t index) const;
235
242 std::size_t elementIndex(std::size_t longTranElementIndex, std::size_t vertElementIndex) const {
243 return vertFastest ?
244 longTranElementIndex * (vertAxis->size()-1) + vertElementIndex :
245 vertElementIndex * longTranMesh.getElementsCount() + longTranElementIndex;
246 }
247
252 std::size_t getElementsCount() const {
253 const std::size_t vertSize = vertAxis->size();
254 return vertSize == 0 ? 0 : (vertSize-1) * longTranMesh.getElementsCount();
255 }
256
257 bool operator==(const ExtrudedTriangularMesh3D& to_compare) const;
258
259 bool operator!=(const ExtrudedTriangularMesh3D& to_compare) const {
260 return !(*this == to_compare);
261 }
262
263 protected:
264
265 bool hasSameNodes(const MeshD<3> &to_compare) const override;
266
267 private:
268 enum class SideBoundaryDir { BACK, FRONT, LEFT, RIGHT, ALL };
269
270 static constexpr TriangularMesh2D::BoundaryDir boundaryDir3Dto2D(SideBoundaryDir d) { return TriangularMesh2D::BoundaryDir(d); }
271
273 typedef boost::icl::right_open_interval<std::size_t> LayersInterval;
274
276 typedef boost::icl::interval_set<std::size_t, std::less, LayersInterval> LayersIntervalSet;
277
282 template <SideBoundaryDir boundaryDir>
283 std::set<std::size_t> boundaryNodes(const LayersIntervalSet& layers, const GeometryD<3>& geometry, const GeometryObject& object, const PathHints *path = nullptr) const;
284
293 TriangularMesh2D::SegmentsCounts countSegmentsIn(std::size_t layer, const GeometryD<3> &geometry, const GeometryObject &object, const PathHints *path = nullptr) const;
294
300 LayersInterval layersIn(const Box3D& box) const;
301
307 LayersIntervalSet layersIn(const std::vector<Box3D>& boxes) const;
308
312 template <SideBoundaryDir boundaryDir>
313 static Boundary getObjBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
314
318 template <SideBoundaryDir boundaryDir>
319 static Boundary getObjBoundary(shared_ptr<const GeometryObject> object);
320
321 // for left, right, front, back boundaries of whole mesh or box:
322 struct ExtrudedTriangularBoundaryImpl: public BoundaryNodeSetImpl {
323
324 struct IteratorImpl: public BoundaryNodeSetImpl::IteratorImpl {
325
326 const ExtrudedTriangularBoundaryImpl &boundary;
327
328 std::set<std::size_t>::const_iterator longTranIter;
329
330 std::size_t vertIndex;
331
332 IteratorImpl(const ExtrudedTriangularBoundaryImpl &boundary, std::set<std::size_t>::const_iterator longTranIter, std::size_t vertIndex)
333 : boundary(boundary), longTranIter(longTranIter), vertIndex(vertIndex)
334 {}
335
336 /*IteratorImpl(const ExtrudedTriangularBoundaryImpl &boundary, std::size_t vertIndex)
337 : IteratorImpl(boundary, boundary.longTranIndices.begin(), vertIndex)
338 {}*/
339
340 std::size_t dereference() const override {
341 return boundary.mesh.index(*longTranIter, vertIndex);
342 }
343
344 void increment() override {
345 if (boundary.mesh.vertFastest) {
346 ++vertIndex;
347 if (vertIndex == boundary.vertIndices.upper()) {
348 vertIndex = boundary.vertIndices.lower();
349 ++longTranIter;
350 }
351 } else {
352 ++longTranIter;
353 if (longTranIter == boundary.longTranIndices.end()) {
354 longTranIter = boundary.longTranIndices.begin();
355 ++vertIndex;
356 }
357 }
358 }
359
360 bool equal(const typename BoundaryNodeSetImpl::IteratorImpl& other) const override {
361 return longTranIter == static_cast<const IteratorImpl&>(other).longTranIter &&
362 vertIndex == static_cast<const IteratorImpl&>(other).vertIndex;
363 }
364
365 std::unique_ptr<PolymorphicForwardIteratorImpl<std::size_t, std::size_t>> clone() const override {
366 return std::unique_ptr<PolymorphicForwardIteratorImpl<std::size_t, std::size_t>>(new IteratorImpl(*this));
367 }
368
369 };
370
371 const ExtrudedTriangularMesh3D &mesh;
372
373 std::set<std::size_t> longTranIndices;
374
375 LayersInterval vertIndices;
376
377 ExtrudedTriangularBoundaryImpl(
378 const ExtrudedTriangularMesh3D &mesh,
379 std::set<std::size_t> longTranIndices,
380 LayersInterval vertIndices)
381 : mesh(mesh), longTranIndices(std::move(longTranIndices)), vertIndices(vertIndices)
382 {
383 }
384
385 bool contains(std::size_t mesh_index) const override {
386 std::pair<std::size_t, std::size_t> lt_v = mesh.longTranAndVertIndices(mesh_index);
387 return vertIndices.lower() <= lt_v.second && lt_v.second < vertIndices.upper()
388 && longTranIndices.find(lt_v.first) != longTranIndices.end();
389 }
390
391 bool empty() const override { return vertIndices.lower() == vertIndices.upper() || longTranIndices.empty(); }
392
393 std::size_t size() const override { return (vertIndices.upper() - vertIndices.lower()) * longTranIndices.size(); }
394
395 BoundaryNodeSetImpl::const_iterator begin() const override {
396 return BoundaryNodeSetImpl::const_iterator(new IteratorImpl(*this, longTranIndices.begin(), vertIndices.lower()));
397 }
398
399 BoundaryNodeSetImpl::const_iterator end() const override {
400 return BoundaryNodeSetImpl::const_iterator(
401 mesh.vertFastest ?
402 new IteratorImpl(*this, longTranIndices.end(), vertIndices.lower()) :
403 new IteratorImpl(*this, longTranIndices.begin(), vertIndices.upper())
404 );
405 }
406 };
407
408 // for top and bottom boundaries of whole mesh:
409 struct ExtrudedTriangularWholeLayerBoundaryImpl: public BoundaryNodeSetImpl {
410
411 struct IteratorImpl: public BoundaryNodeSetImpl::IteratorImpl {
412
413 const ExtrudedTriangularWholeLayerBoundaryImpl &boundary;
414
415 std::size_t longTranIndex;
416
417 IteratorImpl(const ExtrudedTriangularWholeLayerBoundaryImpl &boundary, std::size_t longTranIndex)
418 : boundary(boundary), longTranIndex(longTranIndex)
419 {}
420
421 std::size_t dereference() const override {
422 return boundary.mesh.index(longTranIndex, boundary.vertIndex);
423 }
424
425 void increment() override {
426 ++longTranIndex;
427 }
428
429 bool equal(const typename BoundaryNodeSetImpl::IteratorImpl& other) const override {
430 return longTranIndex == static_cast<const IteratorImpl&>(other).longTranIndex;
431 }
432
433 std::unique_ptr<PolymorphicForwardIteratorImpl<std::size_t, std::size_t>> clone() const override {
434 return std::unique_ptr<PolymorphicForwardIteratorImpl<std::size_t, std::size_t>>(new IteratorImpl(*this));
435 }
436
437 };
438
439 const ExtrudedTriangularMesh3D &mesh;
440
441 std::size_t vertIndex;
442
443 ExtrudedTriangularWholeLayerBoundaryImpl(const ExtrudedTriangularMesh3D &mesh, std::size_t vertIndex)
444 : mesh(mesh), vertIndex(vertIndex)
445 {
446 }
447
448 bool contains(std::size_t mesh_index) const override {
449 return mesh.vertIndex(mesh_index) == this->vertIndex;
450 }
451
452 bool empty() const override { return mesh.vertAxis->empty(); }
453
454 std::size_t size() const override { return mesh.vertAxis->size(); }
455
456 BoundaryNodeSetImpl::const_iterator begin() const override {
457 return BoundaryNodeSetImpl::const_iterator(new IteratorImpl(*this, 0));
458 }
459
460 BoundaryNodeSetImpl::const_iterator end() const override {
461 return BoundaryNodeSetImpl::const_iterator(new IteratorImpl(*this, mesh.longTranMesh.size()));
462 }
463 };
464
468 template <SideBoundaryDir boundaryDir>
469 static Boundary getMeshBoundary();
470
476 template <SideBoundaryDir boundaryDir>
477 static Boundary getBoxBoundary(const Box3D& box);
478
485 BoundaryNodeSet topOrBottomBoundaryNodeSet(const Box3D &box, bool top) const;
486
495 BoundaryNodeSet topOrBottomBoundaryNodeSet(const GeometryD<3>& geometry, const GeometryObject& object, const PathHints *path, bool top) const;
496
497 public:
498
499 static Boundary getBackBoundary();
500 static Boundary getFrontBoundary();
501 static Boundary getLeftBoundary();
502 static Boundary getRightBoundary();
503 static Boundary getBottomBoundary();
504 static Boundary getTopBoundary();
505 static Boundary getAllSidesBoundary();
506
507 static Boundary getBackOfBoundary(const Box3D& box);
508 static Boundary getFrontOfBoundary(const Box3D& box);
509 static Boundary getLeftOfBoundary(const Box3D& box);
510 static Boundary getRightOfBoundary(const Box3D& box);
511 static Boundary getBottomOfBoundary(const Box3D& box);
512 static Boundary getTopOfBoundary(const Box3D& box);
513 static Boundary getAllSidesOfBoundary(const Box3D& box);
514
515 static Boundary getBackOfBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
516 static Boundary getBackOfBoundary(shared_ptr<const GeometryObject> object);
517 static Boundary getBackOfBoundary(shared_ptr<const GeometryObject> object, const PathHints *path) {
518 return path ? getBackOfBoundary(object, *path) : getBackOfBoundary(object);
519 }
520
521 static Boundary getFrontOfBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
522 static Boundary getFrontOfBoundary(shared_ptr<const GeometryObject> object);
523 static Boundary getFrontOfBoundary(shared_ptr<const GeometryObject> object, const PathHints *path) {
524 return path ? getFrontOfBoundary(object, *path) : getFrontOfBoundary(object);
525 }
526
527 static Boundary getLeftOfBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
528 static Boundary getLeftOfBoundary(shared_ptr<const GeometryObject> object);
529 static Boundary getLeftOfBoundary(shared_ptr<const GeometryObject> object, const PathHints *path) {
530 return path ? getLeftOfBoundary(object, *path) : getLeftOfBoundary(object);
531 }
532
533 static Boundary getRightOfBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
534 static Boundary getRightOfBoundary(shared_ptr<const GeometryObject> object);
535 static Boundary getRightOfBoundary(shared_ptr<const GeometryObject> object, const PathHints *path) {
536 return path ? getRightOfBoundary(object, *path) : getRightOfBoundary(object);
537 }
538
539 static Boundary getAllSidesBoundaryIn(shared_ptr<const GeometryObject> object, const PathHints& path);
540 static Boundary getAllSidesBoundaryIn(shared_ptr<const GeometryObject> object);
541 static Boundary getAllSidesBoundaryIn(shared_ptr<const GeometryObject> object, const PathHints *path) {
542 return path ? getAllSidesBoundaryIn(object, *path) : getAllSidesBoundaryIn(object);
543 }
544
545 static Boundary getTopOfBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
546 static Boundary getTopOfBoundary(shared_ptr<const GeometryObject> object);
547 static Boundary getTopOfBoundary(shared_ptr<const GeometryObject> object, const PathHints *path) {
548 return path ? getTopOfBoundary(object, *path) : getTopOfBoundary(object);
549 }
550
551 static Boundary getBottomOfBoundary(shared_ptr<const GeometryObject> object, const PathHints &path);
552 static Boundary getBottomOfBoundary(shared_ptr<const GeometryObject> object);
553 static Boundary getBottomOfBoundary(shared_ptr<const GeometryObject> object, const PathHints *path) {
554 return path ? getBottomOfBoundary(object, *path) : getBottomOfBoundary(object);
555 }
556};
557
558 class ExtrudedTriangularMesh3D::ElementMesh: public MeshD<3> {
559
561 const ExtrudedTriangularMesh3D* originalMesh;
562
563 public:
564 ElementMesh(const ExtrudedTriangularMesh3D* originalMesh): originalMesh(originalMesh) {}
565
566 LocalCoords at(std::size_t index) const override {
567 return originalMesh->element(index).getMidpoint();
568 }
569
570 std::size_t size() const override {
571 return originalMesh->getElementsCount();
572 }
573
574 const ExtrudedTriangularMesh3D& getOriginalMesh() const { return *originalMesh; }
575
576 protected:
577
578 bool hasSameNodes(const MeshD<3> &to_compare) const override;
579};
580
581
582// ------------------ Nearest Neighbor interpolation ---------------------
583
584 template <typename DstT, typename SrcT>
585 struct PLASK_API NearestNeighborExtrudedTriangularMesh3DLazyDataImpl: public InterpolatedLazyDataImpl<DstT, ExtrudedTriangularMesh3D, const SrcT>
586{
587 RtreeOfTriangularMesh2DNodes nodesIndex;
588
589 NearestNeighborExtrudedTriangularMesh3DLazyDataImpl(
590 const shared_ptr<const ExtrudedTriangularMesh3D>& src_mesh,
591 const DataVector<const SrcT>& src_vec,
592 const shared_ptr<const MeshD<3>>& dst_mesh,
593 const InterpolationFlags& flags);
594
595 DstT at(std::size_t index) const override;
596};
597
598 template <typename SrcT, typename DstT>
599 struct InterpolationAlgorithm<ExtrudedTriangularMesh3D, SrcT, DstT, INTERPOLATION_NEAREST> {
600 static LazyData<DstT> interpolate(const shared_ptr<const ExtrudedTriangularMesh3D>& src_mesh,
601 const DataVector<const SrcT>& src_vec,
602 const shared_ptr<const MeshD<3>>& dst_mesh,
603 const InterpolationFlags& flags)
604 {
605 if (src_mesh->empty()) throw BadMesh("interpolate", "source mesh empty");
606 return new NearestNeighborExtrudedTriangularMesh3DLazyDataImpl<typename std::remove_const<DstT>::type,
607 typename std::remove_const<SrcT>::type>
608 (src_mesh, src_vec, dst_mesh, flags);
609 }
610
611};
612
613
614// ------------------ Barycentric / Linear interpolation ---------------------
615
616 template <typename DstT, typename SrcT>
617 struct PLASK_API BarycentricExtrudedTriangularMesh3DLazyDataImpl: public InterpolatedLazyDataImpl<DstT, ExtrudedTriangularMesh3D, const SrcT>
618{
619 TriangularMesh2D::ElementIndex elementIndex;
620
621 BarycentricExtrudedTriangularMesh3DLazyDataImpl(
622 const shared_ptr<const ExtrudedTriangularMesh3D>& src_mesh,
623 const DataVector<const SrcT>& src_vec,
624 const shared_ptr<const MeshD<3>>& dst_mesh,
625 const InterpolationFlags& flags);
626
627 DstT at(std::size_t index) const override;
628};
629
630 template <typename SrcT, typename DstT>
631 struct InterpolationAlgorithm<ExtrudedTriangularMesh3D, SrcT, DstT, INTERPOLATION_LINEAR> {
632 static LazyData<DstT> interpolate(const shared_ptr<const ExtrudedTriangularMesh3D>& src_mesh,
633 const DataVector<const SrcT>& src_vec,
634 const shared_ptr<const MeshD<3>>& dst_mesh,
635 const InterpolationFlags& flags)
636 {
637 if (src_mesh->empty()) throw BadMesh("interpolate", "source mesh empty");
638 return new BarycentricExtrudedTriangularMesh3DLazyDataImpl<typename std::remove_const<DstT>::type,
639 typename std::remove_const<SrcT>::type>
640 (src_mesh, src_vec, dst_mesh, flags);
641 }
642
643};
644
645
646// ------------------ Element mesh Nearest Neighbor interpolation ---------------------
647
648 template <typename DstT, typename SrcT>
649 struct PLASK_API NearestNeighborElementExtrudedTriangularMesh3DLazyDataImpl: public InterpolatedLazyDataImpl<DstT, ExtrudedTriangularMesh3D::ElementMesh, const SrcT>
650{
651 TriangularMesh2D::ElementIndex elementIndex;
652
653 NearestNeighborElementExtrudedTriangularMesh3DLazyDataImpl(
654 const shared_ptr<const ExtrudedTriangularMesh3D::ElementMesh>& src_mesh,
655 const DataVector<const SrcT>& src_vec,
656 const shared_ptr<const MeshD<3>>& dst_mesh,
657 const InterpolationFlags& flags);
658
659 DstT at(std::size_t index) const override;
660};
661
662 template <typename SrcT, typename DstT>
663 struct InterpolationAlgorithm<ExtrudedTriangularMesh3D::ElementMesh, SrcT, DstT, INTERPOLATION_NEAREST> {
664 static LazyData<DstT> interpolate(const shared_ptr<const ExtrudedTriangularMesh3D::ElementMesh>& src_mesh,
665 const DataVector<const SrcT>& src_vec,
666 const shared_ptr<const MeshD<3>>& dst_mesh,
667 const InterpolationFlags& flags)
668 {
669 if (src_mesh->empty()) throw BadMesh("interpolate", "source mesh empty");
670 return new NearestNeighborElementExtrudedTriangularMesh3DLazyDataImpl<typename std::remove_const<DstT>::type,
671 typename std::remove_const<SrcT>::type>
672 (src_mesh, src_vec, dst_mesh, flags);
673 }
674
675};
676
677
678} // namespace plask
679
680#endif // PLASK__MESH_EXTRUDED_TRIANGULAR3D_H