NCBI C++ ToolKit
tri_perimeter.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: tri_perimeter.cpp 43891 2019-09-16 13:50:00Z evgeniev $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Peter Meric, Bob Falk
27  *
28  * File Description:
29  * Helper class to extract a single perimeter from a bunch of triangles
30  *
31  */
32 
33 #include <ncbi_pch.hpp>
35 
37 
39  CVect2<float>& v2p,
40  CVect2<float>& v3p) {
41 
42  size_t idx1 = AddVertex(v1p);
43  size_t idx2 = AddVertex(v2p);
44  size_t idx3 = AddVertex(v3p);
45 
46  size_t e1 = AddEdge(idx1, idx2);
47  size_t e2 = AddEdge(idx2, idx3);
48  size_t e3 = AddEdge(idx3, idx1);
49 
50  m_Triangles.push_back(CVect3<size_t>(e1, e2, e3));
51 
52  return (m_Triangles.size() - 1);
53 }
54 
56 {
57  float min_dist = 1e10f;
58  size_t min_idx = (size_t)-1;
59 
60  for (size_t i = 0; i < m_Vertices.size(); ++i) {
61  float dist = (v - m_Vertices[i]).Length2();
62  if (dist < min_dist) {
63  min_idx = i;
64  min_dist = dist;
65  }
66  }
67 
68  if (min_dist > 1e-6f) {
69  min_idx = m_Vertices.size();
70  m_Vertices.push_back(v);
71  }
72 
73  return min_idx;
74 }
75 
76 size_t CTriPerimeter::AddEdge(size_t vert1, size_t vert2)
77 {
78  // edges will have lower index first
79  CVect2<size_t> edge(vert1, vert2);
80 
81  if (vert1 > vert2) {
82  edge.Set(vert2, vert1);
83  }
84 
85  vector<CVect2<size_t> >::iterator iter;
86  iter = find(m_Edges.begin(), m_Edges.end(), edge);
87 
88  if (iter != m_Edges.end())
89  return (size_t(iter - m_Edges.begin()));
90 
91  m_Edges.push_back(edge);
92  return m_Edges.size() - 1;
93 }
94 
95 /// returns empty vec if no perimeter can be found.
96 vector<CVect2<float> > CTriPerimeter::GetPerimiter() const
97 {
98  // First find all unshared edges
99  vector<int> edge_tris(m_Edges.size(), 0);
100 
101  size_t i;
102  for (i = 0; i < m_Triangles.size(); ++i) {
103  for (int j = 0; j < 3; ++j)
104  edge_tris[m_Triangles[i][j]] += 1;
105  }
106 
107  vector<size_t> unshared_edges;
108  for (i = 0; i < edge_tris.size(); ++i) {
109  if (edge_tris[i] == 1)
110  unshared_edges.push_back(i);
111  }
112 
113  vector<size_t> perimeter_vertices;
114  vector<CVect2<float> > perimeter;
115 
116  // Take the first unshared edge then loop over the edges repeatedly taking
117  // each time an edge that connects to the second vertex until the second
118  // vertex of an edge connects to the first vertex of the first edge or
119  // no match is found.
120  bool done = false;
121  if (unshared_edges.size() < 3)
122  return perimeter;
123 
124  size_t first_vert = m_Edges[unshared_edges.back()][0];
125  size_t last_vert = m_Edges[unshared_edges.back()][1];
126 
127  perimeter_vertices.push_back(first_vert);
128  perimeter_vertices.push_back(last_vert);
129 
130  unshared_edges.pop_back();
131 
132  while (!done && unshared_edges.size() > 0) {
133  int next_edge = -1;
134 
135  for (i = 0; i < unshared_edges.size() && next_edge == -1; ++i) {
136  if (m_Edges[unshared_edges[i]][0] == last_vert) {
137  last_vert = m_Edges[unshared_edges[i]][1];
138  if (last_vert == first_vert)
139  done = true;
140  else
141  perimeter_vertices.push_back(last_vert);
142 
143  next_edge = (int)i;
144  }
145  else if (m_Edges[unshared_edges[i]][1] == last_vert) {
146  last_vert = m_Edges[unshared_edges[i]][0];
147  if (last_vert == first_vert)
148  done = true;
149  else
150  perimeter_vertices.push_back(last_vert);
151 
152  next_edge = (int)i;
153  }
154  }
155  if (next_edge != -1) {
156  unshared_edges.erase(unshared_edges.begin() + next_edge);
157  }
158  else {
159  done = true;
160  }
161  }
162 
163  if (unshared_edges.size() == 0) {
164  for (i = 0; i < perimeter_vertices.size(); ++i)
165  perimeter.push_back(m_Vertices[perimeter_vertices[i]]);
166  }
167 
168  return perimeter;
169 }
170 
std::vector< CVect3< size_t > > m_Triangles
std::vector< CVect2< float > > m_Vertices
size_t AddTri(CVect2< float > &v1p, CVect2< float > &v2p, CVect2< float > &v3p)
size_t AddVertex(CVect2< float > &v)
std::vector< CVect2< float > > GetPerimiter() const
returns empty vec if no perimeter can be found.
std::vector< CVect2< size_t > > m_Edges
size_t AddEdge(size_t vert1, size_t vert2)
void Set(T x, T y)
Definition: vect2.hpp:260
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
int i
done
Definition: token1.c:1
Modified on Fri Sep 20 14:57:45 2024 by modify_doxy.py rev. 669887