16#include <boost/range/irange.hpp>
17#include <boost/icl/interval_map.hpp>
18#include <unordered_map>
20#include "../utils/interpolation.hpp"
44 if (B.c0 < lo.c0) lo.c0 = B.c0;
else up.c0 = B.c0;
45 if (B.c1 < lo.c1) lo.c1 = B.c1;
else up.c1 = B.c1;
47 if (C.c0 < lo.c0) lo.c0 = C.c0;
else if (C.c0 > up.c0) up.c0 = C.c0;
48 if (C.c1 < lo.c1) lo.c1 = C.c1;
else if (C.c1 > up.c1) up.c1 = C.c1;
53 for (std::size_t i = 0; i <
mesh.
nodes.size(); ++i)
65 mesh.elementNodes.shrink_to_fit();
66 mesh.nodes.shrink_to_fit();
70 mesh.elementNodes.push_back({addNode(p1), addNode(
p2), addNode(
p3)});
75 auto it = this->indexOfNode.emplace(
node, mesh.nodes.size());
77 this->mesh.nodes.push_back(
node);
78 return it.first->second;
82 TriangularMesh2D::ElementIndex::Rtree::value_type
operator()(std::size_t index)
const {
87 return std::make_pair(
89 vec(std::min(std::min(n0.c0, n1.c0), n2.c0), std::min(std::min(n0.c1, n1.c1), n2.c1)),
90 vec(std::max(std::max(n0.c0, n1.c0), n2.c0), std::max(std::max(n0.c1, n1.c1), n2.c1))
108 for (
auto v: rtree | boost::geometry::index::adaptors::queried(boost::geometry::index::intersects(p))) {
109 const Element el = mesh.getElement(
v.second);
112 return INDEX_NOT_FOUND;
116 for (
auto v: rtree | boost::geometry::index::adaptors::queried(boost::geometry::index::intersects(p))) {
117 const Element el = mesh.getElement(
v.second);
127 if (predicate(el))
builder.add(el);
132 object.attr(
"type",
"triangular2d");
134 object.addTag(
"node").attr(
"tran",
node.tran()).attr(
"vert",
node.vert());
136 object.addTag(
"element").attr(
"a", el[0]).attr(
"b", el[1]).attr(
"c", el[2]);
140 return a <
b ? std::make_pair(
a,
b) : std::make_pair(
b,
a);
144 ++counter[
makeSegment(el.getNodeIndex(0), el.getNodeIndex(1))];
145 ++counter[
makeSegment(el.getNodeIndex(1), el.getNodeIndex(2))];
146 ++counter[
makeSegment(el.getNodeIndex(2), el.getNodeIndex(0))];
158 if (
box.contains(el.getNode(0)) &&
box.contains(el.getNode(1)) &&
box.contains(el.getNode(2)))
159 countSegmentsOf(
result, el);
172 countSegmentsOf(
result, el);
183 if (geometry.objectIncludes(
object, path, el.getNode(0)) &&
184 geometry.objectIncludes(
object, path, el.getNode(1)) &&
185 geometry.objectIncludes(
object, path, el.getNode(2)))
186 countSegmentsOf(
result, el);
191 std::set<std::size_t>
result;
192 for (
const std::pair<TriangularMesh2D::Segment, std::size_t>& s: segmentsCount)
194 result.insert(s.first.first);
195 result.insert(s.first.second);
200template <
int DIR,
template<
class>
class Compare = std::less>
203 constexpr static int SEG_DIR = 1 - DIR;
212 min(mesh.nodes[segment.first][DIR]),
213 max(mesh.nodes[segment.second][DIR])
216 if (Compare<double>()(
max,
min))
221 return Compare<TriangularMesh2D::Segment>::operator()(this->segment, other.
segment);
226 return this->segment == other.
segment;
238 if (point[SEG_DIR] == f[SEG_DIR])
239 return Compare<double>()(point[DIR], f[DIR]);
241 if (point[SEG_DIR] == s[SEG_DIR])
242 return Compare<double>()(point[DIR], s[DIR]);
244 if (f[SEG_DIR] < s[SEG_DIR])
245 return Compare<double>()(point[DIR], interpolation::linear(f[SEG_DIR], f[DIR], s[SEG_DIR], s[DIR], point[SEG_DIR]));
248 return Compare<double>()(point[DIR], interpolation::linear(s[SEG_DIR], s[DIR], f[SEG_DIR], f[DIR], point[SEG_DIR]));
253template<
int DIR,
template<
class>
class Compare = std::less>
258 : maxOfMins(to_append.
min) { set.insert(to_append); }
265 if (Compare<double>::operator()(maxOfMins, right.maxOfMins)) {
266 SetT this_set_backup = std::move(set);
268 maxOfMins = right.maxOfMins;
269 insert(this_set_backup);
276 return this->set == other.set;
282 if (s.dominates(mesh, point))
return true;
287 typedef std::set<SegmentSetMember<DIR, Compare>, Compare<SegmentSetMember<DIR, Compare>>> SetT;
289 void insert(
const SetT& right) {
291 if (!Compare<double>::operator()(s.
max, maxOfMins))
306template<
int SEG_DIR,
template<
class>
class Compare>
309 std::set<std::size_t>
result;
311 for (
const std::pair<TriangularMesh2D::Segment, std::size_t>& s: segmentsCount)
315 boost::icl::interval<double>::closed(this->
nodes[seg.first][SEG_DIR],
this->nodes[
seg.second][SEG_DIR]),
318 result.insert(s.first.first);
319 result.insert(s.first.second);
464 if (*side ==
"bottom")
468 if (*side ==
"right")
511 result.elementNodes.push_back({
531static RegisterMeshReader rectangular2d_reader(
"triangular2d", readTriangularMesh2D);
541template<
typename DstT,
typename SrcT>
543 const shared_ptr<const TriangularMesh2D>& src_mesh,
545 const shared_ptr<
const MeshD<2>>& dst_mesh,
554template <
typename DstT,
typename SrcT>
557 auto point = this->dst_mesh->
at(index);
559 for (
auto v: nodesIndex | boost::geometry::index::adaptors::queried(boost::geometry::index::nearest(
wrapped_point, 1)))
560 return this->flags.postprocess(point,
this->src_vec[
v]);
578template<
typename DstT,
typename SrcT>
581 elementIndex(*src_mesh)
585template <
typename DstT,
typename SrcT>
588 auto point = this->dst_mesh->
at(index);
590 for (
auto v: elementIndex.rtree | boost::geometry::index::adaptors::queried(boost::geometry::index::intersects(
wrapped_point))) {
591 const auto el = this->src_mesh->getElement(
v.second);
593 if (
b.c0 < 0.0 ||
b.c1 < 0.0 ||
b.c2 < 0.0)
continue;
594 return this->flags.postprocess(point,
595 b.c0*
this->src_vec[el.getNodeIndex(0)] +
596 b.c1*this->src_vec[el.getNodeIndex(1)] +
597 b.c2*this->src_vec[el.getNodeIndex(2)]);
599 return NaN<
decltype(this->src_vec[0])>();
616template<
typename DstT,
typename SrcT>
618 const shared_ptr<const TriangularMesh2D::ElementMesh>& src_mesh,
620 const shared_ptr<
const MeshD<2>>& dst_mesh,
623 elementIndex(src_mesh->getOriginalMesh())
627template<
typename DstT,
typename SrcT>
629 auto point = this->dst_mesh->
at(index);
633 return NaN<
decltype(this->src_vec[0])>();
634 return this->flags.postprocess(point, this->src_vec[
element_index]);
650 if (this->originalMesh == c->originalMesh)
return true;