SheafSystem  0.0.0.0
line_surface_intersecter.cc
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
20 
21 #include "SheafSystem/line_surface_intersecter.h"
22 
23 #include "SheafSystem/assert_contract.h"
24 #include "SheafSystem/base_space_poset.h"
25 #include "SheafSystem/e3.h"
26 #include "SheafSystem/sec_at1_space.h"
27 #include "SheafSystem/sec_e3.h"
28 #include "SheafSystem/section_space_schema_poset.h"
29 
30 using namespace std;
31 using namespace geometry; // Workaround for MSVC++ bug
32 using namespace fiber_bundle::vd_algebra;
33 using namespace fiber_bundle::ed_algebra;
34 using namespace fiber_bundle::e3_algebra;
35 
36 //#define DIAGNOSTIC_OUTPUT
37 
38 // ===========================================================
39 // LINE_SURFACE_INTERSECTER FACET
40 // ===========================================================
41 
42 // PUBLIC MEMBER FUNCTIONS
43 
46 {
47 
48  // Preconditions:
49 
50  // Body:
51 
52  _coords = &xcoords;
53 
54  _coords->get_read_access();
55 
56  _host = &(_coords->schema().host()->base_space());
57  _surface_id_space = &_host->blocks().id_space();
58  _eval_id_space = &_coords->schema().evaluation().id_space();
59  _locator = new d_array_point_locator<3, 2>(*_coords, xbin_ubs);
60 
61  _coords->release_access();
62 
63  // Postconditions:
64 
65  ensure(invariant());
66 
67  // Exit:
68 
69  return;
70 }
71 
74 {
75 
76  // Preconditions:
77 
78 
79  // Body:
80 
81  not_implemented();
82 
83  // Postconditions:
84 
85  ensure(invariant());
86 
87  // Exit:
88 
89  return;
90 }
91 
94 {
95  // Preconditions:
96 
97 
98  // Body:
99 
100  delete _locator;
101 
102  // Postconditions:
103 
104  // Exit:
105 
106  return;
107 }
108 
111 coords() const
112 {
113  return *_coords;
114 }
115 
116 void
118 intersect(const e3_lite& xp0, const e3_lite& xp1, intersection_set_type& xresult) const
119 {
120  //cout << "Entering line_surface_intersecter::intersect:" << endl;
121 // cerr << endl;
122 // cerr << "Entering line_surface_intersecter::intersect:" << endl;
123 
124 // cout << " xp0 = " << xp0 << endl;
125 // cout << " xp1 = " << xp1 << endl;
126 // cout << " _locator->lb() " << _locator->lb() << endl;
127 // cout << " _locator->ub() " << _locator->ub() << endl;
128 // cout << endl;
129 
130  // Preconditions:
131 
133 
134  require(unexecutable("temporarily only implemented for lines parallel to z axis"));
135  require(xp0[0] == xp1[0]);
136  require(xp0[1] == xp1[1]);
137  require(xp0[0] <= _locator->ub()[0]);
138  require(xp0[1] <= _locator->ub()[1]);
139  require(xp0[0] >= _locator->lb()[0]);
140  require(xp0[1] >= _locator->lb()[1]);
141 
142  // Body:
143 
144  // cout << "xp0: " << xp0 << endl;
145  // cout << "xp1: " << xp1 << endl;
146 
147  xresult.clear();
148 
149  d_bounding_box<3, 2> lbox;
150  d_bin_coordinates<3, 2> rel_pos;
151 
152  // Get the bounds for this eval member and put them in the bounding box.
153  // Must convert from the global coordinate system to search
154  // structure-relative coordinates.
155 
156  sec_vd_value_type gbl_pos[3];
157  gbl_pos[0] = xp0[0];
158  gbl_pos[1] = xp0[1];
159 
160  gbl_pos[2] = 0.0; // Doesn't matter what value this is.
161 
162  _locator->relative_position_pa(gbl_pos, 3, rel_pos);
163  rel_pos[2] = 0;
164 
165 // cerr << " lower bound: lbox.put_lb(rel_pos)" << endl;
166 // cerr << " gbl_pos[0], rel_pos[0] = " << gbl_pos[0] << " : " << rel_pos[0] << endl;
167 // cerr << " gbl_pos[1], rel_pos[1] = " << gbl_pos[1] << " : " << rel_pos[1] << endl;
168 // cerr << " gbl_pos[2], rel_pos[2] = " << gbl_pos[2] << " : " << rel_pos[2] << endl;
169 // cerr << endl;
170 
171  lbox.put_lb(rel_pos);
172 
173  _locator->relative_position_pa(gbl_pos, 3, rel_pos);
174  rel_pos[2] = (_locator->bin_ub()[2])-1;
175 
176 // cerr << " upper bound: lbox.put_ub(rel_pos)" << endl;
177 // cerr << " gbl_pos[0], rel_pos[0] = " << gbl_pos[0] << " : " << rel_pos[0] << endl;
178 // cerr << " gbl_pos[1], rel_pos[1] = " << gbl_pos[1] << " : " << rel_pos[1] << endl;
179 // cerr << " gbl_pos[2], rel_pos[2] = " << gbl_pos[2] << " : " << rel_pos[2] << endl;
180 // cerr << endl;
181 
182  lbox.put_ub(rel_pos);
183 
184  box_set_type lboxes;
185 
186  // Get intersection candidates.
187 
188  _locator->box_list(&lbox, lboxes);
189 
190  // Check each candidate for intersection.
191 
192  e3_lite lintersection;
193  box_set_type::iterator lbox_itr = lboxes.begin();
194  while(lbox_itr != lboxes.end())
195  {
196  // cout << "Testing for intersection with triangle " << (*lbox_itr)->member_id().hub_pod() << endl;
197 
198  if(intersect(xp0, xp1, **lbox_itr, lintersection))
199  {
200  // Found an intersection;
201  // insert the result.
202 
203  // cout << "found intersection" << endl;
204 
206 
208  // This is the behavior we want for an intersection on an edge between
209  // two triangles in the same surface, but not what we want if two
210  // surfaces happen to overlap at the intersection point.
211 
212  intersection_set_type::value_type lval(lintersection[2],(*lbox_itr)->branch_id().pod());
213  xresult.insert(lval);
214  }
215 
216  ++lbox_itr;
217  }
218 
219  // Postconditions:
220 
221 
222  // Exit:
223 
224 // //cout << "Leaving line_surface_intersecter::intersect:" << endl;
225 // cerr << "Leaving line_surface_intersecter::intersect:" << endl;
226 // cerr << endl;
227 
228  return;
229 }
230 
231 
232 // PROTECTED MEMBER FUNCTIONS
233 
234 
237 {
238 
239  // Preconditions:
240 
241 
242  // Body:
243 
244  not_implemented();
245 
246  // Postconditions:
247 
248  ensure(invariant());
249 
250  // Exit:
251 
252  return;
253 }
254 
255 bool
257 intersect(const e3_lite& xpp, const e3_lite& xpq, const d_bounding_box<3, 2>& xbox, e3_lite& xr) const
258 {
259  // Preconditions:
260 
261 
262  // Body:
263 
264  // Line-triangle intersection from Christer Erickson,
265  // "Real Time Collision Detection", Section 5.3.4
266 
267  // Get the coordinates of the vertices of the triangle
268 
269  sec_vd_dof_type* ldofs = _locator->gathered_dofs().base() + xbox.dofs_index();
270 
271  vd_value_type ax = ldofs[0], ay = ldofs[1], az = ldofs[2];
272  e3_lite a(ax, ay, az);
273 
274  vd_value_type bx = ldofs[3], by = ldofs[4], bz = ldofs[5];
275  e3_lite b(bx, by, bz);
276 
277  vd_value_type cx = ldofs[6], cy = ldofs[7], cz = ldofs[8];
278  e3_lite c(cx, cy, cz);
279 
280  // cout << "a: " << a << endl;
281  // cout << "b: " << b << endl;
282  // cout << "c: " << c << endl;
283 
284 
285  // Create vectors for edges
286 
287  e3_lite pq(xpq);
288  pq -= xpp;
289 
290  e3_lite pa(a);
291  pa -= xpp;
292 
293  e3_lite pb(b);
294  pb -= xpp;
295 
296  e3_lite pc(c);
297  pc -= xpp;
298 
299  // Test if pq is inside edges bc, ca, and ab. Done by testing
300  // that the signed tetrahedral volumes, computed using scalar triple
301  // products, are all the same sign. Same sign means either all three
302  // are <= 0 or all three are >= 0.
303 
304  e3_lite m;
305  cross(pq, pc, m);
306 
307  vd_value_type u = dot(pb, m);
308 
309  // cout << "u: " << u << endl;
310 
311  vd_value_type v = -dot(pa, m);
312 
313  // cout << "v: " << v << endl;
314 
315  bool same_sign = ((u < 0) == (v < 0)) || (u == 0) || (v == 0);
316 
317  // cout << "same_sign: " << boolalpha << same_sign << noboolalpha << endl;
318 
319  if(!same_sign) return false;
320 
321  e3_lite n;
322  cross(pb, pa, n);
323  vd_value_type w = dot(pq, n);
324 
325  // cout << "w: " << w << endl;
326 
327  same_sign = ((u < 0) == (w < 0)) || (u == 0) || (w == 0);
328 
329  // cout << "same_sign: " << boolalpha << same_sign << noboolalpha << endl;
330 
331  if(!same_sign) return false;
332 
333  // If all three are zero, the line is parallel to the triangle;
334  // we can't compute an intersection point.
335 
336  bool all_zero = (u == 0) && (v == 0) && (w == 0) ;
337 
338  if(all_zero) return false;
339 
340  // Found an intersection.
341 
342  // Compute the barycentric coordinates of the intersection.
343 
344  vd_value_type denom = 1.0/(u + v + w);
345  u *= denom;
346  v *= denom;
347  w *= denom;
348 
349  // Compute the intersection point from the barycentric coordinates.
350 
351  xr[0] = u*ax + v*bx + w*cx;
352  xr[1] = u*ay + v*by + w*cy;
353  xr[2] = u*az + v*bz + w*cz;
354 
355  // Postconditions:
356 
357 
358  // Exit:
359 
360  return true;
361 }
362 
363 // PRIVATE MEMBER FUNCTIONS
364 
365 
366 // ===========================================================
367 // ANY FACET
368 // ===========================================================
369 
370 // PUBLIC MEMBER FUNCTIONS
371 
372 bool
374 is_ancestor_of(const any *other) const
375 {
376 
377  // Preconditions:
378 
379  require(other != 0);
380 
381  // Body:
382 
383  // True if other conforms to this
384 
385  bool result = dynamic_cast<const line_surface_intersecter*>(other) != 0;
386 
387  // Postconditions:
388 
389  return result;
390 }
391 
394 clone() const
395 {
396  line_surface_intersecter* result;
397 
398  // Preconditions:
399 
400  // Body:
401 
402  result = new line_surface_intersecter();
403 
404  // Postconditions:
405 
406  ensure(result != 0);
407  ensure(is_same_type(result));
408 
409  // Exit:
410 
411  return result;
412 }
413 
417 {
418 
419  // Preconditions:
420 
421 
422  // Body:
423 
424  not_implemented();
425 
426  // Postconditions:
427 
428  ensure(invariant());
429 
430  // Exit
431 
432  return *this;
433 }
434 
435 bool
437 invariant() const
438 {
439  bool result = true;
440 
441  if(invariant_check())
442  {
443  // Prevent recursive calls to invariant
444 
445  disable_invariant_check();
446 
447  // Must satisfy base class invariant
448 
449  invariance(any::invariant());
450 
451  // Invariances for this class:
452 
453  // Finished, turn invariant checking back on.
454 
455  enable_invariant_check();
456  }
457 
458  // Exit
459 
460  return result;
461 }
462 
463 
464 // ===========================================================
465 // NON-MEMBER FUNCTIONS
466 // ===========================================================
467 
468 std::ostream&
470 operator<<(std::ostream& xos, const line_surface_intersecter& xp)
471 {
472  // Preconditions:
473 
474 
475  // Body:
476 
477  xos << *(xp._host) << endl;
478 
479  xos << *(xp._coords->host()) << endl;
480 
481  xos << *(xp._locator) << endl;
482 
483  // Postconditions:
484 
485 
486  // Exit:
487 
488  return xos;
489 }
std::map< sec_vd_value_type, pod_index_type, really_less_than > intersection_set_type
The type of intersetion set, a map from z coordinate to surface id; sorted by z coordinate.
Namespace containing the Euclidean vector algebra functions for the fiber_bundles component of the sh...
Definition: ed.h:442
virtual bool is_ancestor_of(const any *other) const
Conformance test; true if other conforms to this.
Euclidean vector space of dimension 3 (volatile version).
Definition: e3.h:116
search_structure_type::box_set_type box_set_type
The type of search structure box set.
void put_lb(const d_bin_coordinates< DC, DB > &xlb)
Copies the contents of xlb to lb().
base_space_poset * _host
The base space.
virtual line_surface_intersecter * clone() const
Virtual constructor, makes a new instance of the same type as this.
STL namespace.
virtual void get_read_access() const
Get read access to the state associated with this.
host_type * host() const
The poset this is a member of.
Definition: sec_at1.cc:525
const sec_e3 & coords() const
The section space containing the surfaces.
virtual bool invariant() const
Class invariant.
SHEAF_DLL_SPEC vd_value_type dot(const ed &x0, const ed &x1, bool xauto_access)
The Euclidean "dot" product of x0 with x1 (version for persistent types).
Definition: ed.cc:863
Fixed point relative coordinates for a tree domain.
sec_e3 * _coords
The coordinate section for lines.
Abstract base class with useful features for all objects.
Definition: any.h:39
void intersect(const e3_lite &xp0, const e3_lite &xp1, intersection_set_type &xresult) const
Computes the intersections of the line passing through points xp0 and xp1 with the surfaces defined b...
Namespace containing the 3D Euclidean vector algebra functions for the fiber_bundles component of the...
Definition: e3.h:834
size_type dofs_index() const
Index into the gathered dofs array for the evaluation member this bounds.
line_surface_intersecter()
Default constructor; disabled.
A line-surface intersection query.
A bounding box that can be strung together into a list.
SHEAF_DLL_SPEC double same_sign(double xa, double xb)
Convert xa to have the same sign as xb.
Definition: svd.cc:521
A section of a fiber bundle with a 3-dimensional Euclidean vector space fiber.
Definition: sec_e3.h:47
void SHEAF_DLL_SPEC cross(const e3 &x0, const e3 &x1, e3 &xresult, bool xauto_access)
The 3D Euclidean vector "cross" product of x0 with x1 (pre-allocated version).
Definition: e3.cc:2112
SHEAF_DLL_SPEC std::ostream & operator<<(std::ostream &xos, const array_cylindrical_point_locator &xpl)
Insert array_cylindrical_point_locator xpl into ostream xos.
void put_ub(const d_bin_coordinates< DC, DB > &xub)
Copies the contents of xub to ub().
search_structure_type * _locator
The intersection search structure.
double sec_vd_dof_type
The type of degree of freedom in the section space.
Definition: fiber_bundle.h:78
Namespace containing the vector algrebra functions for the fiber_bundles component of the sheaf syste...
Definition: e3.h:1135
Namespace for geometry component of sheaf system.
Definition: field_vd.h:54
vd_value_type sec_vd_value_type
The type of component in the value of a section at a point.
Definition: fiber_bundle.h:73
line_surface_intersecter & operator=(const line_surface_intersecter &xother)
Assignment operator.
double vd_value_type
The type of component in the fiber; the scalar type in the fiber vector space.
Definition: fiber_bundle.h:63
A point location query in domains with global coordinate dimension DC and local coordinate dimension ...