Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
PeriodicContourTopology.h
Go to the documentation of this file.
1#ifndef model_PeriodicContourTopology_H_
2#define model_PeriodicContourTopology_H_
3
4#include <vector>
5#include <cstddef>
6
7namespace model
8{
9 // Inspect the committed unwrapped contour, before moving or contracting
10 // endpoints. Coincident seam copies are one geometric vertex; both copies
11 // must retain a genuine bend, including a reversal along the same line.
12 template <class Nodes>
13 void retainPeriodicContourBends(const Nodes& nodes,const double tolerance)
14 {
15 for(size_t i=0;i<nodes.size();++i)
16 {
17 if(!nodes[i]->isPeriodicSubdivision())
18 {
19 continue;
20 }
21 size_t previous=(i+nodes.size()-1)%nodes.size();
22 size_t next=(i+1)%nodes.size();
23 while(previous!=i && (nodes[previous]->get_P()-nodes[i]->get_P()).norm()<=tolerance)
24 {
25 previous=(previous+nodes.size()-1)%nodes.size();
26 }
27 while(next!=i && (nodes[next]->get_P()-nodes[i]->get_P()).norm()<=tolerance)
28 {
29 next=(next+1)%nodes.size();
30 }
31 const auto incoming=(nodes[i]->get_P()-nodes[previous]->get_P()).eval();
32 const auto outgoing=(nodes[next]->get_P()-nodes[i]->get_P()).eval();
33 if(previous!=i && next!=i &&
34 (incoming.dot(outgoing)<=0 ||
35 incoming.cross(outgoing).norm()>tolerance*(incoming.norm()+outgoing.norm())))
36 {
37 nodes[i]->periodicContourVertex=true;
38 }
39 }
40 }
41
42 // With two anchors, require both ordered paths to traverse the same
43 // unwrapped segment monotonically in opposite directions. Area alone is
44 // insufficient: a self-intersecting contour can have zero signed area.
45 template <class Nodes>
46 bool retracesContourSegment(const Nodes& nodes,const std::vector<size_t>& anchors,const double tolerance)
47 {
48 if(anchors.empty())
49 {
50 return false;
51 }
52 if(anchors.size()==1)
53 {
54 for(const auto& node : nodes)
55 {
56 if((node->get_P()-nodes[anchors.front()]->get_P()).norm()>tolerance)
57 {
58 return false;
59 }
60 }
61 return true;
62 }
63 if(anchors.size()!=2)
64 {
65 return false;
66 }
67 for(size_t path=0;path<2;++path)
68 {
69 const size_t begin=anchors[path];
70 const size_t end=anchors[1-path];
71 const auto origin=nodes[begin]->get_P();
72 const auto chord=(nodes[end]->get_P()-origin).eval();
73 const double length=chord.norm();
74 double previous=0;
75 for(size_t i=(begin+1)%nodes.size();i!=end;i=(i+1)%nodes.size())
76 {
77 const auto offset=(nodes[i]->get_P()-origin).eval();
78 if(length<=tolerance)
79 {
80 if(offset.norm()>tolerance)
81 {
82 return false;
83 }
84 }
85 else
86 {
87 const double distance=offset.dot(chord)/length;
88 if(distance<previous-tolerance || distance>length+tolerance ||
89 (offset-distance*chord/length).norm()>tolerance)
90 {
91 return false;
92 }
93 previous=distance;
94 }
95 }
96 }
97 return true;
98 }
99}
100#endif
void retainPeriodicContourBends(const Nodes &nodes, const double tolerance)
bool retracesContourSegment(const Nodes &nodes, const std::vector< size_t > &anchors, const double tolerance)
int end[2]
int i