BRL-CAD
shape_recognition_cone.cpp
Go to the documentation of this file.
1 #include "common.h"
2 
3 #include <set>
4 #include <map>
5 
6 #include "bu/log.h"
7 #include "bu/str.h"
8 #include "bu/malloc.h"
9 #include "shape_recognition.h"
10 
11 
12 int
14 {
15  std::set<int>::iterator f_it;
16  std::set<int> planar_surfaces;
17  std::set<int> conic_surfaces;
18  std::set<int> active_edges;
19  // First, check surfaces. If a surface is anything other than planes or cones,
20  // the verdict is no. If we don't have one planar surface and one or more
21  // conic surfaces, the verdict is no.
22  for (int i = 0; i < data->faces_cnt; i++) {
23  int f_ind = data->faces[i];
24  ON_BrepFace *used_face = &(data->brep->m_F[f_ind]);
25  int surface_type = (int)GetSurfaceType(used_face->SurfaceOf(), NULL);
26  switch (surface_type) {
27  case SURFACE_PLANE:
28  planar_surfaces.insert(f_ind);
29  break;
30  case SURFACE_CONE:
31  conic_surfaces.insert(f_ind);
32  break;
33  default:
34  return 0;
35  break;
36  }
37  }
38  if (planar_surfaces.size() < 2) return 0;
39  if (conic_surfaces.size() < 1) return 0;
40 
41  // Second, check if all conic surfaces share the same base point, apex point and radius.
42  ON_Cone cone;
43  data->brep->m_F[*conic_surfaces.begin()].SurfaceOf()->IsCone(&cone);
44  for (f_it = conic_surfaces.begin(); f_it != conic_surfaces.end(); f_it++) {
45  ON_Cone f_cone;
46  data->brep->m_F[(*f_it)].SurfaceOf()->IsCone(&f_cone);
47  ON_3dPoint fbp = f_cone.BasePoint();
48  ON_3dPoint bp = cone.BasePoint();
49  if (fbp.DistanceTo(bp) > 0.01) return 0;
50  ON_3dPoint fap = f_cone.ApexPoint();
51  ON_3dPoint ap = cone.ApexPoint();
52  if (fap.DistanceTo(ap) > 0.01) return 0;
53  if (!(NEAR_ZERO(cone.radius - f_cone.radius, 0.01))) return 0;
54  }
55 
56  // Third, see if the planar face and the planes of any non-linear edges from the conic
57  // faces are coplanar. TODO - do we need to do this?
58  ON_Plane p1;
59  data->brep->m_F[*planar_surfaces.begin()].SurfaceOf()->IsPlanar(&p1);
60 
61  // Fourth, check that the conic axis and the planar face are perpendicular. If they
62  // are not it isn't fatal, but we need to add a subtracting tgc and return a comb
63  // to handle this situation so for now for simplicity require the perpendicular condition
64  if (p1.Normal().IsParallelTo(cone.Axis(), 0.01) == 0) {
65  std::cout << "p1 Normal: " << p1.Normal().x << "," << p1.Normal().y << "," << p1.Normal().z << "\n";
66  std::cout << "cone axis: " << cone.Axis().x << "," << cone.Axis().y << "," << cone.Axis().z << "\n";
67  return 0;
68  }
69 
70 
71  // Fifth, remove degenerate edge sets. A degenerate edge set is defined as two
72  // linear segments having the same two vertices. (To be sure, we should probably
73  // check curve directions in loops in some fashion...)
74  std::set<int> degenerate;
75  for (int i = 0; i < data->edges_cnt; i++) {
76  int e_it = data->edges[i];
77  if (degenerate.find(e_it) == degenerate.end()) {
78  ON_BrepEdge& edge = data->brep->m_E[e_it];
79  if (edge.EdgeCurveOf()->IsLinear()) {
80  for (int j = 0; j < data->edges_cnt; j++) {
81  int f_ind = data->edges[j];
82  ON_BrepEdge& edge2 = data->brep->m_E[f_ind];
83  if (edge2.EdgeCurveOf()->IsLinear()) {
84  if ((edge.Vertex(0)->Point() == edge2.Vertex(0)->Point() && edge.Vertex(1)->Point() == edge2.Vertex(1)->Point()) ||
85  (edge.Vertex(1)->Point() == edge2.Vertex(0)->Point() && edge.Vertex(0)->Point() == edge2.Vertex(1)->Point()))
86  {
87  degenerate.insert(e_it);
88  degenerate.insert(f_ind);
89  break;
90  }
91  }
92  }
93  }
94  }
95  }
96  for (int i = 0; i < data->edges_cnt; i++) {
97  active_edges.insert(data->edges[i]);
98  }
99  std::set<int>::iterator e_it;
100  for (e_it = degenerate.begin(); e_it != degenerate.end(); e_it++) {
101  //std::cout << "erasing " << *e_it << "\n";
102  active_edges.erase(*e_it);
103  }
104 
105 
106  // Sixth, check for any remaining linear segments. If we have a real
107  // cone and not just a partial, all the linear segments should have
108  // washed out.
109  for (e_it = active_edges.begin(); e_it != active_edges.end(); e_it++) {
110  ON_BrepEdge& edge = data->brep->m_E[*e_it];
111  if (edge.EdgeCurveOf()->IsLinear()) return 0;
112  }
113 
114  // Seventh, make sure all the curved edges are on the same circle.
115  // TODO - this is only for a true cone object - a TGC, which can also
116  // be handled here, will have parallel circles
117  ON_Circle circle;
118  int circle_set= 0;
119  for (e_it = active_edges.begin(); e_it != active_edges.end(); e_it++) {
120  ON_BrepEdge& edge = data->brep->m_E[*e_it];
121  ON_Arc arc;
122  if (edge.EdgeCurveOf()->IsArc(NULL, &arc, 0.01)) {
123  ON_Circle circ(arc.StartPoint(), arc.MidPoint(), arc.EndPoint());
124  if (!circle_set) {
125  circle_set = 1;
126  circle = circ;
127  }
128  if (!NEAR_ZERO(circ.Center().DistanceTo(circle.Center()), 0.01)){
129  std::cout << "found extra circle - no go\n";
130  return 0;
131  }
132  }
133  }
134 
135  data->type = CONE;
136 
137  ON_3dVector hvect(cone.ApexPoint() - cone.BasePoint());
138 
139  data->params->origin[0] = cone.BasePoint().x;
140  data->params->origin[1] = cone.BasePoint().y;
141  data->params->origin[2] = cone.BasePoint().z;
142  data->params->hv[0] = hvect.x;
143  data->params->hv[1] = hvect.y;
144  data->params->hv[2] = hvect.z;
145  data->params->radius = circle.Radius();
146  data->params->r2 = 0.000001;
147  data->params->height = hvect.Length();
148 
149  return 1;
150 }
151 
152 int
154 {
155  std::set<int>::iterator f_it;
156  std::set<int> planar_surfaces;
157  std::set<int> conic_surfaces;
158 
159  for (int i = 0; i < data->faces_cnt; i++) {
160  int f_ind = data->faces[i];
161  ON_BrepFace *used_face = &(data->brep->m_F[f_ind]);
162  int surface_type = (int)GetSurfaceType(used_face->SurfaceOf(), NULL);
163  switch (surface_type) {
164  case SURFACE_PLANE:
165  planar_surfaces.insert(f_ind);
166  break;
167  case SURFACE_CONE:
168  conic_surfaces.insert(f_ind);
169  break;
170  default:
171  return 0;
172  break;
173  }
174  }
175 
176  // Second, check if all conic surfaces share the same base point, apex point and radius.
177  ON_Cone cone;
178  data->brep->m_F[*conic_surfaces.begin()].SurfaceOf()->IsCone(&cone, cone_tol);
179  for (f_it = conic_surfaces.begin(); f_it != conic_surfaces.end(); f_it++) {
180  ON_Cone f_cone;
181  data->brep->m_F[(*f_it)].SurfaceOf()->IsCone(&f_cone, cone_tol);
182  ON_3dPoint fbp = f_cone.BasePoint();
183  ON_3dPoint bp = cone.BasePoint();
184  if (fbp.DistanceTo(bp) > cone_tol) return 0;
185  ON_3dPoint fap = f_cone.ApexPoint();
186  ON_3dPoint ap = cone.ApexPoint();
187  if (fap.DistanceTo(ap) > cone_tol) return 0;
188  if (!(NEAR_ZERO(cone.radius - f_cone.radius, cone_tol))) return 0;
189  }
190 
191  // Characterize the planes of the non-linear edges. We need one or two planes - one
192  // indicates a true cone, two indicates a truncated cone. More indicates something
193  // we aren't currently set up to handle.
194  std::set<int> arc_set_1, arc_set_2;
195  ON_Circle set1_c, set2_c;
196  int arc1_circle_set= 0;
197  int arc2_circle_set = 0;
198 
199  for (int i = 0; i < data->edges_cnt; i++) {
200  int ei = data->edges[i];
201  ON_BrepEdge& edge = data->brep->m_E[ei];
202  if (!edge.EdgeCurveOf()->IsLinear()) {
203 
204  ON_Arc arc;
205  if (edge.EdgeCurveOf()->IsArc(NULL, &arc, cone_tol)) {
206  int assigned = 0;
207  ON_Circle circ(arc.StartPoint(), arc.MidPoint(), arc.EndPoint());
208  //std::cout << "circ " << circ.Center().x << " " << circ.Center().y << " " << circ.Center().z << "\n";
209  if (!arc1_circle_set) {
210  arc1_circle_set = 1;
211  set1_c = circ;
212  //std::cout << "center 1 " << set1_c.Center().x << " " << set1_c.Center().y << " " << set1_c.Center().z << "\n";
213  } else {
214  if (!arc2_circle_set) {
215  if (!(NEAR_ZERO(circ.Center().DistanceTo(set1_c.Center()), cone_tol))){
216  arc2_circle_set = 1;
217  set2_c = circ;
218  //std::cout << "center 2 " << set2_c.Center().x << " " << set2_c.Center().y << " " << set2_c.Center().z << "\n";
219  }
220  }
221  }
222  if (NEAR_ZERO(circ.Center().DistanceTo(set1_c.Center()), cone_tol)){
223  arc_set_1.insert(ei);
224  assigned = 1;
225  }
226  if (arc2_circle_set) {
227  if (NEAR_ZERO(circ.Center().DistanceTo(set2_c.Center()), cone_tol)){
228  arc_set_2.insert(ei);
229  assigned = 1;
230  }
231  }
232  if (!assigned) {
233  std::cout << "found extra circle - no go\n";
234  return 0;
235  }
236  }
237  }
238  }
239 
240  if (!arc2_circle_set) {
241  std::cout << "True cone!\n";
242  data->type = CONE;
243 
244  ON_3dVector hvect(cone.ApexPoint() - cone.BasePoint());
245  ON_3dPoint closest_to_base = set1_c.Plane().ClosestPointTo(cone.BasePoint());
246 
247  data->params->origin[0] = closest_to_base.x;
248  data->params->origin[1] = closest_to_base.y;
249  data->params->origin[2] = closest_to_base.z;
250  data->params->hv[0] = hvect.x;
251  data->params->hv[1] = hvect.y;
252  data->params->hv[2] = hvect.z;
253  data->params->radius = set1_c.Radius();
254  data->params->r2 = 0.000001;
255  data->params->height = set1_c.Plane().DistanceTo(cone.ApexPoint());
256 
257  } else {
258  std::cout << "TGC!\n";
259  }
260  return 0;
261 }
262 
263 // Local Variables:
264 // tab-width: 8
265 // mode: C++
266 // c-basic-offset: 4
267 // indent-tabs-mode: t
268 // c-file-style: "stroustrup"
269 // End:
270 // ex: shiftwidth=4 tabstop=8
Header file for the BRL-CAD common definitions.
COMPLEX data[64]
Definition: fftest.c:34
int cone_csg(struct subbrep_object_data *data, fastf_t cone_tol)
surface_t GetSurfaceType(const ON_Surface *in_surface, struct filter_obj *obj)
#define NEAR_ZERO(val, epsilon)
Definition: color.c:55
unsigned char * bp
Definition: rot.c:56
Definition: joint.h:84
int subbrep_is_cone(struct subbrep_object_data *data, fastf_t cone_tol)
double fastf_t
Definition: defines.h:300
csg_object_params * params