Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Overlay_primitives.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // $Id: Overlay_primitives.C,v 1.15 2008/12/06 08:43:28 mtcampbe Exp $
24 
25 //==========================================================
26 // The implementation of the two basic primitive: intersection and projection.
27 // This file uses the HDS accessor.
28 //
29 // Author: Xiangmin Jiao
30 // Date: 12/13/2000
31 //==========================================================
32 
33 #include "Overlay_primitives.h"
34 #include <cmath>
35 #include <algorithm>
36 #include <CGAL/solve.h>
37 
39 
41 
43  : _pane(acc.get_pane(h)), _ne(count_edges(h))
44 {
45  RFC_precondition ( _ne==3 || _ne==4);
46 
48 
49  Size nn=ene.size_of_nodes();
50  int r=-1;
51  Value v = _pane->get_lid(h->vertex());
52  _nodes.resize(nn);
53 
54  for ( Size i=0; i<nn; ++i) {
55  if ((_nodes[i] = ene[i])==v) r=(i+_ne-1)%_ne;
56  }
57  RFC_assertion( r>=0 && r<int(_ne));
58  if (r>0) {
59  std::rotate( &_nodes[0], &_nodes[r], &_nodes[_ne]);
60  if (nn>_ne) std::rotate( &_nodes[_ne], &_nodes[_ne+r], &_nodes[_ne+_ne]);
61  }
62 }
63 
65  : _pane(acc.get_pane(h)), _ne(3)
66 {
67  _nodes.resize(_ne, -1);
68 
69  _nodes[0] = _pane->get_lid( h->origin());
70  _nodes[1] = _pane->get_lid( h->destination());
71 }
72 
73 // This function computes the intersection of the edge [b->org,b->dst]
74 // with [g->org,g->dst]. It assumes that the two edges are not
75 // parallel. The output c1 and c2 are parameterization of
76 // the locations of the intersection. It snaps the intersections
77 // onto vertices if their parameterizations are close to 0 or 1.
78 // Returns true iff both |*c1| and |*c2| are in [0,1].
80 intersect( const Halfedge *hb,
81  const Halfedge *hg,
82  Real start,
83  Real *c1,
84  Real *c2,
85  Real *orien_match,
86  Real *normal_match,
87  bool is_opposite,
88  Real eps_e) const {
89  RFC_assertion( !hg->is_border());
90 
91  // Switch blue edge if it is a border edge to use Point_set.
92  bool is_b_border = acc.is_border(hb);
93  if ( is_b_border) hb = acc.get_opposite( hb);
94 
95  const Point_set pbs(hb);
96  const Point_set pgs(hg);
97  const Normal_set ngs(hg);
98 
99  *c1 = start; // At input, set *c1 to start
100  intersect( pbs, pgs, ngs, c1, c2, is_b_border);
101 
102  if ( std::fabs( *c1) < 1/eps_e && std::fabs( *c2) < 1/eps_e) {
103  Vector_3 v2 = acc.get_normal( hg);
104  Vector_3 v1 = acc.get_normal( hb);
105  double prod1 = v1 * v2;
106 
107  v1 = acc.get_normal( acc.get_opposite(hb));
108  double prod2 = v1 * v2;
109 
110  // Reverse the sign if the two projdirs having different directions.
111  if ( is_opposite)
112  { prod1 = -prod1; prod2 = -prod2; }
113 
114  *normal_match = std::max(prod1, prod2);
115 
116  // Finally, we determine c1 and c2.
117  if ( std::fabs(*c1-1) <= eps_e) *c1 = 1.;
118  else if ( std::fabs(*c1) <= eps_e) *c1 = 0.;
119 
120  if ( std::fabs(*c2-1) <= eps_e) *c2 = 1.;
121  else if ( std::fabs(*c2) <= eps_e) *c2 = 0.;
122 
123  if ( orien_match) {
124  Vector_3 J[3];
125  J[0] = get_tangent( hb, *c1);
126  J[1] = get_tangent( hg, *c2);
127  J[2] = get_projdir( hg, *c2);
128  *orien_match = Vector_3::cross_product( J[0], J[1]) * J[2] /
129  std::sqrt( (J[0]*J[0]) * (J[1]*J[1]) * (J[2]*J[2]));
130 
131  if (is_b_border) *orien_match = -*orien_match;
132  }
133 
134  // Switch edge back
135  if ( is_b_border) { *c1 = 1-*c1; }
136 
137  return *c1 >= 0. && *c1 <= 1. && *c2 >= 0. && *c2 <= 1.;
138  }
139  else
140  return false;
141 }
142 
143 // The intersection is a quadratic function and in general it has two
144 // solutions. We pick the solution based on s (the parameterization on blue
145 // edge) and t (the parameterization on green edge) as follows:
146 // If any t is far less than 0 or far greater than 1, ignore this solution.
147 // If both s1 and s2 are greater than start, then take smaller one.
148 // If both are smaller than the start, then no intersection.
149 // If one is greater and the other is smaller, then return the greater one.
150 // In addition, it safeguards errors by comparing the residual against
151 // the longer of the green and blue edges.
153 intersect( const Point_set &pbs,
154  const Point_set &pgs,
155  const Normal_set &ngs,
156  Real *c1,
157  Real *c2, bool reversed) const {
158 
159  Vector_3 vb = pbs[1]-pbs[0], vg=pgs[1]-pgs[0], vn=ngs[1]-ngs[0];
160  Vector_3 vd = pgs[0]-pbs[0];
161 
162  Real c = Vector_3::cross_product( vb, ngs[0])*vd;
163  Real d = Vector_3::cross_product( vb, ngs[1])*( pgs[1]-pbs[0]);
164  Real a = Vector_3::cross_product( vb, vn) * vg;
165  Real b = d - c - a;
166 
167  // We now need to solve a*t^2 + b*t + c =0 to get t. First scale a, b, and c.
168  Real max_abc = std::max( std::max(std::fabs(a), std::fabs(b)), std::fabs(c));
169  if ( max_abc > 0)
170  { a /= max_abc; b /= max_abc; c /= max_abc; d /= max_abc; }
171 
172  Real s, t;
173  Real eps = 0.1, tol_fea = 1;
174 
175  if ( a == 0) {
176  // The two edges are parallel.
177  if ( b == 0)
178  { *c1 = *c2 = HUGE_VAL; return; }
179 
180  t = -c/b;
181 
182  if ( t >= -tol_fea && t <= 1+tol_fea) {
183  Real denominator = (1-t) * (Vector_3::cross_product( vg, ngs[0]) * vb) +
184  t * (Vector_3::cross_product( vg, ngs[1]) * vb);
185  Real nominator = (1-t) * (Vector_3::cross_product( vg, ngs[0]) * vd) +
186  t * (Vector_3::cross_product( vg, ngs[1]) * vd);
187  s = nominator / denominator;
188  }
189  else
190  { *c1 = *c2 = HUGE_VAL; return; }
191  }
192  else {
193  Real det = b*b - 4*a*c;
194  if ( det < 0)
195  { *c1 = *c2 = HUGE_VAL; return; }
196 
197  Real sqrt_d = std::sqrt( det);
198  Real s1, s2, t1, t2;
199 
200  if ( b>0) {
201  Real temp = -b - sqrt_d;
202  t1 = 2*c / temp;
203  t2 = temp / 2/ a;
204  }
205  else {
206  Real temp = -b + sqrt_d;
207  t1 = temp / 2 / a;
208  t2 = 2*c / temp;
209  }
210 
211  if ( std::fabs(t1 -1.) < eps || std::fabs(t2 -1.) < eps ) {
212  // Use alternative formula to compute intersection
213  Real b = -(c - d - a);
214  Real sqrt_d = std::sqrt( b*b - 4*a*d);
215  if ( det < 0)
216  { *c1 = *c2 = HUGE_VAL; return; }
217  if ( b>0) {
218  Real temp = -b - sqrt_d;
219  if (std::fabs(t1 - 1.) < eps) t1 = 1 + 2*d / temp;
220  if (std::fabs(t2 - 1.) < eps) t2 = 1 + temp / 2 / a;
221  }
222  else {
223  Real temp = -b + sqrt_d;
224  if (std::fabs(t1 - 1.) < eps) t1 = 1 + temp / 2 / a;
225  if (std::fabs(t2 - 1.) < eps) t2 = 1 + 2*d / temp;
226  }
227  }
228 
229  if ( t1 >= -tol_fea && t1 <= 1+tol_fea) {
230  Real denominator = (1-t1) * (Vector_3::cross_product( vg, ngs[0]) * vb) +
231  t1 * (Vector_3::cross_product( vg, ngs[1]) * vb);
232  Real numerator = (1-t1) * (Vector_3::cross_product( vg, ngs[0]) * vd) +
233  t1 * (Vector_3::cross_product( vg, ngs[1]) * vd);
234  s1 = numerator / denominator;
235  }
236  else
237  s1 = reversed ? HUGE_VAL : -HUGE_VAL;
238 
239  if ( t2 >= -tol_fea && t2 <= 1+tol_fea) {
240  Real denominator = (1-t2) * (Vector_3::cross_product( vg, ngs[0]) * vb) +
241  t2 * (Vector_3::cross_product( vg, ngs[1]) * vb);
242  Real numerator = (1-t2) * (Vector_3::cross_product( vg, ngs[0]) * vd) +
243  t2 * (Vector_3::cross_product( vg, ngs[1]) * vd);
244  s2 = numerator / denominator;
245  }
246  else
247  s2 = reversed ? HUGE_VAL : -HUGE_VAL;
248 
249  double start = *c1-eps;
250 
251  if ( !reversed) {
252  if ( s1 < start && s2 < start)
253  { *c1 = *c2 = HUGE_VAL; return; }
254  else if ( s2 < start || s1 >= start && s1 <= s2)
255  { s = s1; t = t1; }
256  else
257  { s = s2; t = t2; }
258  }
259  else {
260  if ( 1-s1 < start && 1-s2 < start)
261  { *c1 = *c2 = -HUGE_VAL; return; }
262  else if ( 1-s2 < start || 1-s1 >= start && 1-s1 <= 1-s2)
263  { s = s1; t = t1; }
264  else
265  { s = s2; t = t2; }
266  }
267  }
268 
269  // Check residule of the solution and make sure the direction between
270  // the two points is reasonably close to the projection direction
271  Generic_element e(3);
272  Vector_3 v2 = e.interpolate( ngs, t);
273  Vector_3 v3 = e.interpolate( pbs, s)-e.interpolate( pgs, t);
274  Real error = (v3-(v3*v2)/(v2*v2)*v2).squared_norm() / std::max( vb*vb,vg*vg);
275  if ( error >= _eps_p*_eps_p) {
276 #ifdef DEBUG
277  std::cerr << "WARNING: Rejecting intersection due to too large error "
278  << error << ". Solution was " << s << "," << t << std::endl;
279 #endif
280  *c1 = *c2 = HUGE_VAL;
281  }
282  else
283  { *c1 = s; *c2 = t; }
284 }
285 
286 // Project a point p onto an element along a given direction.
287 // The projection direction is given by the input parameter dir.
288 // If the input is Vector_3(0,0,0), evaluate the direction by
289 // sum N_i*n_i. Note that g and pt are in-out parameters.
290 bool
293  Halfedge **g,
294  Parent_type *pt,
295  Vector_3 dir,
296  Point_2 *nc_out,
297  const Real eps_p,
298  Real eps_np) const {
299  if ( eps_np < 0) eps_np = eps_p;
300  RFC_assertion( eps_p>_eps_c);
301  RFC_assertion( *pt != PARENT_VERTEX);
302 
303  // Construct two elements.
304  Point_set ps(*g);
305  Normal_set ns(*g);
306 
307  Point_2 nc(0.,0.);
308  Generic_element e(ps.size_of_edges()); // We ignore the midpoints
309  const bool comp_dir = ( dir == Vector_3(0,0,0));
310 
311  // Solve the equation using Newton's method for nonlinear equations.
312  Real t(0.);
314  RFC_assertion_code( const Size max_nsteps = 20);
315  double err = 1.e30, eps_c2=_eps_c*_eps_c;
316  for ( ;;RFC_assertion(++i<max_nsteps)) {
317  if ( comp_dir) e.interpolate( ns, nc, &dir);
318 
319  // evaluate f
320  Vector_3 f = e.interpolate( ps, nc) - p + t*dir;
321  double et = f*f / e.Jacobian_det( ps,nc);
322  if ( et <= eps_c2 || et >= err) break;
323  err = et;
324 
325  Vector_3 J[3];
326  e.Jacobian( ps, nc, J);
327  if ( comp_dir) {
328  Vector_3 J2[2];
329  e.Jacobian( ns, nc, J2);
330  J[0] = J[0] + t*J2[0];
331  J[1] = J[1] + t*J2[1];
332  }
333  J[2] = dir;
334 
335  // Solve the linear system Ju=f
336  Real u[3];
337  CGAL::solve( J[0][0], J[0][1], J[0][2], J[1][0], J[1][1], J[1][2],
338  J[2][0], J[2][1], J[2][2], f[0], f[1], f[2],
339  u[0], u[1], u[2]);
340 
341  nc = Point_2( nc[0] - u[0], nc[1] - u[1]); t -= u[2];
342 
343  if ( std::fabs( nc[0]) > 2 || std::fabs( nc[1]) > 2 ) {
344  // System is diverging
345  break;
346  }
347  }
348 
349  // Perturb nc by eps_p.
350  nc = Point_2( ( nc[0] <= eps_p && nc[0] >= -eps_np)
351  ? 0. : ( ( nc[0]>=1.-eps_p && nc[0]<=1.+eps_np) ? 1 : nc[0]),
352  ( nc[1] <= eps_p && nc[1] >= -eps_np)
353  ? 0. : ( ( nc[1]>=1.-eps_p && nc[1]<=1.+eps_np) ? 1 : nc[1]));
354 
355  // if the projection is restricted onto the edge, return it now.
356  if ( *pt == PARENT_EDGE) {
357  if ( nc[0] < 0.) { nc[0] = nc[1] = 0; }
358  else if ( nc[0] > 1.) { nc[0] = nc[1] = 0; *g = (*g)->next(); }
359  else nc = Point_2( nc[0], 0.);
360 
361  if ( nc[0] == 0 || nc[0] == 1) *pt = PARENT_VERTEX;
362  if ( nc_out) *nc_out = nc;
363  return true;
364  }
365 
366  // Otherwise, determine whether the projection is in the interior,
367  // on the edge, or at a vertex.
368  switch ( ps.size_of_edges()) {
369  case 3: {
370  if ( (nc[0] + nc[1]) >= 1-eps_p && (nc[0] + nc[1]) <= 1+eps_np) {
371  // Projects onto the diagonal edge
372  if ( nc[0] < eps_p) {
373  *g = (*g)->prev(); nc[0] = nc[1] = 0; *pt = PARENT_VERTEX;
374  }
375  else {
376  *g = (*g)->next(); nc = Point_2( nc[1], 0.);
377  *pt = (nc[1] == 0.) ? PARENT_VERTEX : PARENT_EDGE;
378  }
379  }
380  else if ( nc[0] == 0.) {
381  // Projects onto the horizontal edge
382  if ( nc[1] == 0.)
383  { nc[0] = nc[1] = 0; *pt = PARENT_VERTEX; }
384  else
385  { *g = (*g)->prev(); nc = Point_2( 1.-nc[1], 0.); *pt = PARENT_EDGE; }
386  }
387  else if ( nc[1] == 0.)
388  // Projects onto the vertical edge
389  { nc = Point_2( nc[0], 0.); *pt = PARENT_EDGE; }
390  else
391  { *pt = PARENT_FACE; }
392  if ( nc_out) *nc_out = nc;
393 
394  return ( nc[0] >= 0. && nc[1] >= 0. && nc[0]+nc[1] <= 1.);
395  }
396  case 4: {
397  // Projects onto the left edge
398  if ( nc[0] == 0.) {
399  if ( nc[1] == 0.)
400  { *pt = PARENT_VERTEX; }
401  else {
402  *g = (*g)->prev(); nc = Point_2( 1.-nc[1], 0.);
403  *pt = (nc[1] == 1.) ? PARENT_VERTEX : PARENT_EDGE;
404  }
405  }
406  else if ( nc[0] == 1.) {
407  // Projects onto the right edge
408  if ( nc[1] == 1.)
409  { *g = (*g)->next()->next(); nc[0] = nc[1] = 0; *pt = PARENT_VERTEX;}
410  else {
411  *g = (*g)->next(); nc = Point_2( nc[1], 0.);
412  *pt = (nc[1] == 0.) ? PARENT_VERTEX : PARENT_EDGE;
413  }
414  }
415  else if ( nc[1] == 0.)
416  // Projects onto the bottom edge
417  { *pt = PARENT_EDGE; }
418  else if ( nc[1] == 1.)
419  // Projects onto the top edge
420  { *g=(*g)->next()->next(); nc=Point_2(1.-nc[0],0.); *pt=PARENT_EDGE; }
421  else
422  { *pt = PARENT_FACE; }
423 
424  if ( nc_out) *nc_out = nc;
425 
426  return ( nc[0] >= 0. && nc[0] <= 1. && nc[1] >= 0. && nc[1] <= 1.);
427  }
428  default:
429  break;
430  }
431 
432  return false;
433 }
434 
435 // Solve the equation q=p1+s*(p2-p1)+u*n+v*b
436 // for s, u, and v and return s.
437 Real
439 project_green_feature( const Vector_3 &n, // Normal direction
440  const Vector_3 &t, // Tangential direction
441  const Point_3 &p1, // Source blue vertex
442  const Point_3 &p2, // Target blue vertex
443  const Point_3 &q, // Green vertex
444  const Real eps_e) const
445 {
446  Vector_3 f = q-p1;
447  Vector_3 c1 = p2-p1;
449 
450  Real s,u,v;
451  CGAL::solve( c1[0], c1[1], c1[2], n[0], n[1], n[2],
452  b[0], b[1], b[2], f[0], f[1], f[2], s, u, v);
453  if ( std::fabs(s) <= eps_e)
454  s = 0;
455  else if ( std::fabs(1.-s) <= eps_e)
456  s = 1.;
457 
458  return s;
459 }
460 
461 // Solve the equation p=q1+s*(q2-q1)+u*(n1+s*(n2-n1))+v*(b1+s*(b2-b1))
462 // for s, u, and v and return s;
463 Real
465 project_blue_feature( const Vector_3 &n1, const Vector_3 &n2,
466  const Vector_3 &t1, const Vector_3 &t2,
467  const Point_3 &q1, const Point_3 &q2,
468  const Point_3 &p,
469  const Real eps_e) const {
470  RFC_assertion( eps_e>_eps_c);
471  Real s=0, u=0, v=0;
472  Vector_3 b1 = Vector_3::cross_product( n1, t1);
473  Vector_3 b2 = Vector_3::cross_product( n2, t2);
474  Vector_3 qdiff=q2-q1, bdiff=b2-b1, ndiff=n2-n1;
475 
477  RFC_assertion_code( const Size max_nsteps = 20);
478  double err = 1.e30, eps_c2=_eps_c*_eps_c;
479  for ( ;;RFC_assertion(++i<max_nsteps)) {
480  Vector_3 c2 = (s*ndiff += n1);
481  Vector_3 c3 = (s*bdiff += b1);
482 
483  Vector_3 f = ((q1-p) += s*qdiff += u*c2 += v*c3);
484  double et = f*f / (qdiff*qdiff);
485 
486  if ( et <= eps_c2 || et >= err) break;
487  err = et;
488 
489  // Vector_3 c1 = (q2-q1) + u*(n2-n1) + v*(b2-b1);
490  Vector_3 c1 = (u*ndiff += v*bdiff += qdiff);
491  Real x[3];
492  CGAL::solve( c1[0], c1[1], c1[2], c2[0], c2[1], c2[2],
493  c3[0], c3[1], c3[2], f[0], f[1], f[2], x[0], x[1], x[2]);
494 
495  s -= x[0]; u -= x[1]; v -= x[2];
496  }
497 
498  if ( std::fabs(s) <= eps_e)
499  s = 0;
500  else if ( std::fabs(1.-s) <= eps_e)
501  s = 1.;
502 
503  return s;
504 }
505 
506 // Snap a blue ridge edge onto a green ridge vertex.
509  const Halfedge *g,
510  Real *cb,
511  Real *cg,
512  Parent_type *t,
513  Real tol) const {
514  const RFC_Pane_overlay *pn = acc.get_pane( g);
515  bool is_border = acc.is_border(b) || acc.is_border(acc.get_opposite(b));
516 
517  // If the green edge is a ridge, then do nothing
518  if ( pn->is_feature_1(g) && !is_border && *cg != 0 && *cg!=1) return;
519 
520  const Vertex *v=NULL;
521  if ( *cg <= tol) {
522  v = acc.get_origin(g);
523 
524  if (is_border && acc.is_border(v) || !is_border && acc.is_on_feature( v)) {
525  *cg = 0; *t = PARENT_VERTEX;
526  }
527  }
528  else if ( *cg >= 1-tol){
529  v = acc.get_destination(g);
530 
531  if (is_border && acc.is_border(v) || !is_border && acc.is_on_feature( v)) {
532  *cg = 1; *t = PARENT_VERTEX;
533  }
534  }
535 }
536 
537 // Snap a ridge vertex onto a ridge edge
540  Halfedge **g,
541  Parent_type *pt,
542  Point_2 *nc_p,
543  Real tol) const {
544  bool is_border = acc.is_border(v);
545  COM_assertion( acc.is_on_feature( v) && !acc.is_border( *g));
546 
547  Point_2 &nc = *nc_p;
548 
549  Vertex_set vs(*g);
550  RFC_Pane_overlay *pn = acc.get_pane(*g);
551 
552  // Otherwise, determine whether the projection is in the interior,
553  // on the edge, or at a vertex.
554  switch ( vs.size_of_edges()) {
555  case 3: {
556  double meas[3] = { nc[0], nc[1], 1-nc[0]-nc[1]};
557  Halfedge *hs[3] = { (*g)->prev(), *g, (*g)->next() };
558  bool is_feas[3];
559 
560  if ( is_border)
561  for ( int i=0; i<3; ++i) is_feas[i] = acc.is_border( hs[i]->opposite());
562  else
563  for ( int i=0; i<3; ++i) is_feas[i] = pn->is_feature_1( hs[i]);
564 
565  for ( int k=0; k<3; ++k) {
566  // Snap to the closest feature edge
567  if ( meas[k] <= tol && is_feas[k] &&
568  (meas[k] <= meas[(k+1)%3] || !is_feas[(k+1)%3]) &&
569  (meas[k] <= meas[(k+2)%3] || !is_feas[(k+2)%3])) {
570  *g = hs[k];
571 
572  if ( k==0) nc[0] = 1-nc[1]; else if ( k==2) nc[0] = nc[1];
573  nc[1] = 0;
574 
575  if ( nc[0]>=1) nc[0] = 1.; else if ( nc[0]<=0) nc[0] = 0.;
576  if ( nc[0] == 0. || nc[0]==1.) *pt = PARENT_VERTEX;
577  else *pt = PARENT_EDGE;
578 
579  return;
580  }
581  }
582 
583  const Vertex *org;
584  for (int k=0; k<3; ++k) {
585  // Snap to the closest feature vertex
586  if ( 1-meas[(k+1)%3] <= tol &&
587  ( acc.is_border( org= acc.get_origin( hs[k])) ||
588  !is_border && acc.is_on_feature( org))) {
589  *g = hs[k];
590  nc = Point_2( 0, 0);
591 
592  *pt = PARENT_VERTEX;
593  break;
594  }
595  }
596  return;
597  }
598  case 4: {
599  double meas[4] = { nc[0], nc[1], 1-nc[0], 1-nc[1]};
600  Halfedge *hs[4] = { (*g)->prev(), *g, (*g)->next(), (*g)->next()->next() };
601  bool is_feas[4];
602 
603  if ( is_border)
604  for ( int i=0; i<4; ++i) is_feas[i] = acc.is_border( hs[i]->opposite());
605  else
606  for ( int i=0; i<4; ++i) is_feas[i] = pn->is_feature_1( hs[i]);
607 
608  for ( int k=0; k<4; ++k) {
609  // Snap to the closest feature edge
610  if ( meas[k] <= tol && is_feas[k] &&
611  (meas[k] <= meas[(k+1)%4] || !is_feas[(k+1)%4]) &&
612  (meas[k] <= meas[(k+2)%4] || !is_feas[(k+2)%4]) &&
613  (meas[k] <= meas[(k+3)%4] || !is_feas[(k+3)%4]) ) {
614  *g = hs[k];
615 
616  nc[0] = meas[(k+3)%4];
617  nc[1] = 0.;
618 
619  if ( nc[0]>=1) nc[0] = 1.; else if ( nc[0]<=0) nc[0] = 0.;
620  if ( nc[0] == 0. || nc[0]==1.) *pt = PARENT_VERTEX;
621  else *pt = PARENT_EDGE;
622 
623  return;
624  }
625  }
626 
627  const Vertex *org;
628  for ( int k=0; k<4; ++k) {
629  // Snap to the closest feature vertex
630  if ( meas[ (k+3)%4] <= tol && meas[ k] <= tol &&
631  ( acc.is_border( org=acc.get_origin( hs[k])) ||
632  !is_border && acc.is_on_feature( org))) {
633  *g = hs[k];
634  nc = Point_2( 0, 0);
635 
636  *pt = PARENT_VERTEX;
637  break;
638  }
639  }
640  return;
641  }
642  default:
643  break;
644  }
645 }
646 
648 normalmatch( const Halfedge *b, const Halfedge *g) const {
649  RFC_assertion( acc.is_feature_1(b) && acc.is_feature_1(g));
650 
651  const Halfedge *bopp = acc.get_opposite(b), *gopp = acc.get_opposite(g);
652  const Vector_3& nrm_b = acc.get_normal( b);
653  const Vector_3& nrm_bopp = acc.get_normal( bopp);
654 
655  const Vector_3& nrm_g = acc.get_normal( g);
656  const Vector_3& nrm_gopp = acc.get_normal( gopp);
657 
658  // First, figure out best matching.
659  Real match[4] = { nrm_b*nrm_g, nrm_bopp*nrm_g,
660  nrm_b*nrm_gopp, nrm_bopp*nrm_gopp};
661 
662  // Find the best match.
663  Real best_match=-1; int m=0;
664  for ( int i=0; i<4; ++i) {
665  if ( match[i]>best_match) { best_match = match[m=i]; }
666  }
667 
668  // Return the other match
669  return match[3-m];
670 }
671 
673 
674 
675 
676 
677 
678 
Vector_3 get_tangent(const Halfedge *b, Real a) const
Vertex * get_origin(Halfedge *h) const
Definition: HDS_accessor.h:87
unsigned int Size
bool intersect(const Halfedge *b, const Halfedge *g, Real start, Real *c1, Real *c2, Real *dir, Real *dir_match, bool is_opposite, Real eps_e) const
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
An adaptor for enumerating node IDs of an element.
const NT & d
Real project_green_feature(const Vector_3 &n, const Vector_3 &t, const Point_3 &p1, const Point_3 &p2, const Point_3 &q, const Real eps_p) const
Halfedge * get_opposite(Halfedge *h) const
Definition: HDS_accessor.h:99
j indices k indices k
Definition: Indexing.h:6
Vertex_overlay * destination()
Definition: HDS_overlay.h:137
double s
Definition: blastest.C:80
RFC_Pane_overlay * get_pane(Vertex *v) const
Definition: HDS_accessor.h:128
NT q1
Base * base()
The id of its base COM::Pane object.
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
NT p1
Halfedge_overlay * opposite()
Definition: HDS_overlay.h:118
bool is_feature_1(const Halfedge *h) const
Definition: HDS_accessor.h:184
const Vector_3 & get_normal(const Halfedge *h) const
Definition: HDS_accessor.h:289
Vector_3 get_projdir(const Halfedge *b, Real a) const
double Real
Definition: mapbasic.h:322
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
double sqrt(double d)
Definition: double.h:73
SURF::Generic_element_2 Generic_element
Definition: rfc_basic.h:46
bool is_border() const
Definition: HDS_overlay.h:131
Real normalmatch(const Halfedge *b, const Halfedge *g) const
RFC_BEGIN_NAME_SPACE HDS_accessor< Tag_true > acc
int get_lid(const Vertex *v) const
Size size_of_edges() const
Vertex_overlay * origin()
Definition: HDS_overlay.h:135
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to and or **sell copies of the and to permit persons to whom the **Software is furnished to do subject to the following this list of conditions and the following disclaimers ****Redistributions in binary form must reproduce the above **copyright this list of conditions and the following **disclaimers in the documentation and or other materials **provided with the distribution ****Neither the names of the Center for Simulation of Advanced the University of nor the names of its **contributors may be used to endorse or promote products derived **from this Software without specific prior written permission ****THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE v
Definition: roccomf90.h:20
bool is_on_feature(const Vertex *v) const
Definition: HDS_accessor.h:174
void snap_blue_ridge_edge(const Halfedge *b, const Halfedge *g, Real *cb, Real *cg, Parent_type *t, Real tol=0.1) const
#define RFC_END_NAME_SPACE
Definition: rfc_basic.h:29
Parent_type
Definition: rfc_basic.h:49
Halfedge_overlay * prev()
Definition: HDS_overlay.h:123
Vertex_overlay * vertex()
Definition: HDS_overlay.h:106
Real project_blue_feature(const Vector_3 &n1, const Vector_3 &n2, const Vector_3 &t1, const Vector_3 &t2, const Point_3 &q1, const Point_3 &q2, const Point_3 &p, const Real eps_p) const
blockLoc i
Definition: read.cpp:79
#define RFC_BEGIN_NAME_SPACE
Definition: rfc_basic.h:28
void int int REAL * x
Definition: read.cpp:74
int size_of_nodes() const
Number of nodes per element.
const NT & n
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
void snap_blue_ridge_vertex(const Vertex *v, Halfedge **g, Parent_type *t, Point_2 *nc, Real tol=0.1) const
bool project_onto_element(const Point_3 &p, Halfedge **g, Parent_type *pt, Vector_3 dir, Point_2 *nc_out, const Real eps_p, Real eps_np=-1.) const
double det(const Matrix3D &A)
Halfedge_overlay * next()
Definition: HDS_overlay.h:120
Real squared_norm(const Vector_3 &v) const
#define RFC_assertion_code
Definition: rfc_basic.h:68
Size size_of_edges() const
const RFC_Pane_overlay * _pane
NT q
#define RFC_precondition
Definition: rfc_basic.h:63
Vertex * get_destination(Halfedge *h) const
Definition: HDS_accessor.h:93
Some basic geometric data types.
Definition: mapbasic.h:54
bool is_border(const Halfedge *h) const
Definition: HDS_accessor.h:153
std::vector< int > _nodes
bool is_feature_1(const Halfedge *h) const
#define RFC_assertion
Definition: rfc_basic.h:65
Facet_overlay * facet()
Definition: HDS_overlay.h:129
SURF::Vector_2< Real > Point_2
Definition: rfc_basic.h:43
CGAL_BEGIN_NAMESPACE void solve(const FT &a1, const FT &a2, const FT &a3, const FT &b1, const FT &b2, const FT &b3, const FT &c1, const FT &c2, const FT &c3, const FT &d1, const FT &d2, const FT &d3, FT &x, FT &y, FT &z)
Definition: solve.h:57