1 #include "moab/DiscreteGeometry/HiReconstruction.hpp"
2 #include "moab/DiscreteGeometry/DGMSolver.hpp"
3 #include "moab/HalfFacetRep.hpp"
4
5 #ifdef MOAB_HAVE_MPI
6 #include "moab/ParallelComm.hpp"
7 #endif
8 #include "MBTagConventions.hpp"
9
10 #define HIREC_USE_AHF
11
12 #include <cmath>
13 #include <deque>
14 #include <iostream>
15
16 namespace moab
17 {
18 HiReconstruction::HiReconstruction( Core* impl, ParallelComm* comm, EntityHandle meshIn, int minpnts, bool recwhole )
19 : mbImpl( impl ), pcomm( comm ), _mesh2rec( meshIn ), _MINPNTS( minpnts )
20 {
21 assert( NULL != impl );
22 ErrorCode error;
23 _MINEPS = 1e-12;
24 _dim = 0;
25 _hasfittings = false;
26 _hasderiv = false;
27 #ifdef MOAB_HAVE_MPI
28 if( !pcomm )
29 {
30 pcomm = moab::ParallelComm::get_pcomm( mbImpl, 0 );
31 }
32 #endif
33
34 error = initialize( recwhole );
35 if( MB_SUCCESS != error )
36 {
37 std::cout << "Error initializing HiReconstruction\n" << std::endl;
38 exit( 1 );
39 }
40 }
41
42 HiReconstruction::~HiReconstruction()
43 {
44 #ifdef MOAB_HAVE_AHF
45 ahf = NULL;
46 #else
47 delete ahf;
48 #endif
49 }
50
51 ErrorCode HiReconstruction::initialize( bool recwhole )
52 {
53 ErrorCode error;
54
55 #ifdef HIREC_USE_AHF
56 std::cout << "HIREC_USE_AHF: Initializing" << std::endl;
57 ahf = new HalfFacetRep( mbImpl, pcomm, _mesh2rec, false );
58 if( !ahf )
59 {
60 return MB_MEMORY_ALLOCATION_FAILED;
61 }
62 error = ahf->initialize();MB_CHK_ERR( error );
63 #else
64 ahf = NULL;
65 #endif
66
67
68 error = mbImpl->get_entities_by_dimension( _mesh2rec, 0, _inverts );MB_CHK_ERR( error );
69 error = mbImpl->get_entities_by_dimension( _mesh2rec, 1, _inedges );MB_CHK_ERR( error );
70 error = mbImpl->get_entities_by_dimension( _mesh2rec, 2, _infaces );MB_CHK_ERR( error );
71 error = mbImpl->get_entities_by_dimension( _mesh2rec, 3, _incells );MB_CHK_ERR( error );
72 if( _inedges.size() && _infaces.empty() && _incells.empty() )
73 {
74 _dim = 1;
75 _MAXPNTS = 13;
76 }
77 else if( _infaces.size() && _incells.empty() )
78 {
79 _dim = 2;
80 _MAXPNTS = 128;
81 }
82 else
83 {
84 MB_SET_ERR( MB_FAILURE, "Encountered a non-manifold mesh or a mesh with volume elements" );
85 }
86
87
88 #ifdef MOAB_HAVE_MPI
89 if( pcomm )
90 {
91 error = pcomm->filter_pstatus( _inverts, PSTATUS_GHOST, PSTATUS_NOT, -1, &_verts2rec );MB_CHK_ERR( error );
92 }
93 else
94 {
95 _verts2rec = _inverts;
96 }
97 #else
98 _verts2rec = _inverts;
99 #endif
100 _nv2rec = _verts2rec.size();
101
102 if( recwhole )
103 {
104
105 if( 2 == _dim )
106 {
107 compute_average_vertex_normals_surf();
108 }
109 else if( 1 == _dim )
110 {
111 compute_average_vertex_tangents_curve();
112 }
113 else
114 {
115 MB_SET_ERR( MB_FAILURE, "Unknow space dimension" );
116 }
117 _hasderiv = true;
118 }
119 return error;
120 }
121
122
125
126 ErrorCode HiReconstruction::reconstruct3D_surf_geom( int degree, bool interp, bool safeguard, bool reset )
127 {
128 assert( 2 == _dim );
129 if( _hasfittings && !reset )
130 {
131
132 return MB_SUCCESS;
133 }
134 else
135 {
136 _initfittings = _hasfittings = false;
137 }
138
139 initialize_surf_geom( degree );
140 ErrorCode error;
141 double *coeffs, *coords;
142 int* degree_out;
143 int ncoeffs = ( degree + 2 ) * ( degree + 1 ) / 2;
144
145
146
147
148 for( Range::iterator ivert = _verts2rec.begin(); ivert != _verts2rec.end(); ++ivert )
149 {
150 int index = _verts2rec.index( *ivert );
151
152
157
158 size_t istr = _vertID2coeffID[index];
159 coords = &( _local_coords[9 * index] );
160 coeffs = &( _local_fit_coeffs[istr] );
161 degree_out = &( _degrees_out[index] );
162 _interps[index] = interp;
163 error = polyfit3d_walf_surf_vertex( *ivert, interp, degree, _MINPNTS, safeguard, 9, coords, degree_out, ncoeffs,
164 coeffs );MB_CHK_ERR( error );
165
166
167
168 }
169
170
171
172
173 _geom = HISURFACE;
174 _hasfittings = true;
175 return error;
176 }
177
178 ErrorCode HiReconstruction::reconstruct3D_surf_geom( size_t npts,
179 int* degrees,
180 bool* interps,
181 bool safeguard,
182 bool reset )
183 {
184 assert( _dim == 2 );
185 if( npts != _nv2rec )
186 {
187 MB_SET_ERR( MB_FAILURE, "Input number of degrees doesn't match number of vertices" );
188 }
189 if( _hasfittings && !reset )
190 {
191 return MB_SUCCESS;
192 }
193 else
194 {
195 _initfittings = _hasfittings = false;
196 }
197 ErrorCode error;
198
199 initialize_surf_geom( npts, degrees );
200 double *coeffs, *coords;
201 int* degree_out;
202 size_t i = 0;
203 for( Range::iterator ivert = _verts2rec.begin(); ivert != _verts2rec.end(); ++ivert, ++i )
204 {
205 int index = _verts2rec.index( *ivert );
206 assert( -1 != index );
207 size_t istr = _vertID2coeffID[index];
208 coords = &( _local_coords[9 * index] );
209 coeffs = &( _local_fit_coeffs[istr] );
210 degree_out = &( _degrees_out[index] );
211 _interps[index] = interps[i];
212 int ncoeffs = ( degrees[i] + 2 ) * ( degrees[i] + 1 ) / 2;
213 error = polyfit3d_walf_surf_vertex( *ivert, interps[i], degrees[i], _MINPNTS, safeguard, 9, coords, degree_out,
214 ncoeffs, coeffs );MB_CHK_ERR( error );
215 }
216 _geom = HISURFACE;
217 _hasfittings = true;
218 return error;
219 }
220
221 ErrorCode HiReconstruction::reconstruct3D_curve_geom( int degree, bool interp, bool safeguard, bool reset )
222 {
223 assert( _dim == 1 );
224 if( _hasfittings && !reset )
225 {
226 return MB_SUCCESS;
227 }
228 else
229 {
230 _initfittings = _hasfittings = false;
231 }
232 initialize_3Dcurve_geom( degree );
233 ErrorCode error;
234 double *coords = 0, *coeffs;
235 int* degree_out;
236 int ncoeffs = 3 * ( degree + 1 );
237 for( Range::iterator ivert = _verts2rec.begin(); ivert != _verts2rec.end(); ++ivert )
238 {
239 int index = _verts2rec.index( *ivert );
240 assert( index != -1 );
241 size_t istr = _vertID2coeffID[index];
242 coeffs = &( _local_fit_coeffs[istr] );
243 degree_out = &( _degrees_out[index] );
244 _interps[index] = interp;
245 error = polyfit3d_walf_curve_vertex( *ivert, interp, degree, _MINPNTS, safeguard, 0, coords, degree_out,
246 ncoeffs, coeffs );MB_CHK_ERR( error );
247 }
248 _geom = HI3DCURVE;
249 _hasfittings = true;
250 return error;
251 }
252
253 ErrorCode HiReconstruction::reconstruct3D_curve_geom( size_t npts,
254 int* degrees,
255 bool* interps,
256 bool safeguard,
257 bool reset )
258 {
259 assert( _dim == 1 );
260 ErrorCode error;
261 if( npts != _nv2rec )
262 {
263 MB_SET_ERR( MB_FAILURE, "Input number of degrees doesn't match the number of vertices" );
264 }
265 if( _hasfittings && !reset )
266 {
267 return MB_SUCCESS;
268 }
269 else
270 {
271 _initfittings = _hasfittings = false;
272 }
273
274 initialize_3Dcurve_geom( npts, degrees );
275 double *coords = 0, *coeffs;
276 int* degree_out;
277 size_t i = 0;
278 for( Range::iterator ivert = _verts2rec.begin(); ivert != _verts2rec.end(); ++ivert, ++i )
279 {
280 int index = _verts2rec.index( *ivert );
281 size_t istr = _vertID2coeffID[index];
282 coeffs = &( _local_fit_coeffs[istr] );
283 degree_out = &( _degrees_out[index] );
284 _interps[index] = interps[i];
285 int ncoeffs = 3 * ( degrees[i] + 1 );
286 error = polyfit3d_walf_curve_vertex( *ivert, interps[i], degrees[i], _MINPNTS, safeguard, 0, coords, degree_out,
287 ncoeffs, coeffs );MB_CHK_ERR( error );
288 }
289 _geom = HI3DCURVE;
290 _hasfittings = true;
291 return error;
292 }
293
294 ErrorCode HiReconstruction::polyfit3d_walf_surf_vertex( const EntityHandle vid,
295 const bool interp,
296 int degree,
297 int minpnts,
298 const bool safeguard,
299 const int ncoords,
300 double* coords,
301 int* degree_out,
302 const int ncoeffs,
303 double* coeffs )
304 {
305 assert( _dim == 2 );
306 ErrorCode error;
307 int ring = estimate_num_rings( degree, interp );
308
309
310 Range ngbvs;
311 error = obtain_nring_ngbvs( vid, ring, minpnts, ngbvs );MB_CHK_ERR( error );
312
313
317
318
319 size_t nverts = ngbvs.size();
320 assert( nverts );
321 double* ngbcoords = new double[nverts * 3];
322 error = mbImpl->get_coords( ngbvs, ngbcoords );MB_CHK_ERR( error );
323
324 double* ngbnrms = new double[nverts * 3];
325 error = get_normals_surf( ngbvs, ngbnrms );MB_CHK_ERR( error );
326
327 int index = ngbvs.index( vid );
328 assert( index != -1 );
329 std::swap( ngbcoords[0], ngbcoords[3 * index] );
330 std::swap( ngbcoords[1], ngbcoords[3 * index + 1] );
331 std::swap( ngbcoords[2], ngbcoords[3 * index + 2] );
332 std::swap( ngbnrms[0], ngbnrms[3 * index] );
333 std::swap( ngbnrms[1], ngbnrms[3 * index + 1] );
334 std::swap( ngbnrms[2], ngbnrms[3 * index + 2] );
335
336 int degree_pnt, degree_qr;
337 polyfit3d_surf_get_coeff( nverts, ngbcoords, ngbnrms, degree, interp, safeguard, ncoords, coords, ncoeffs, coeffs,
338 degree_out, °ree_pnt, °ree_qr );
339 delete[] ngbcoords;
340 delete[] ngbnrms;
341 return error;
342 }
343
344 ErrorCode HiReconstruction::polyfit3d_walf_curve_vertex( const EntityHandle vid,
345 const bool interp,
346 int degree,
347 int minpnts,
348 const bool safeguard,
349 const int ncoords,
350 double* coords,
351 int* degree_out,
352 const int ncoeffs,
353 double* coeffs )
354 {
355 ErrorCode error;
356 int ring = estimate_num_rings( degree, interp );
357
358 Range ngbvs;
359 error = obtain_nring_ngbvs( vid, ring, minpnts, ngbvs );MB_CHK_ERR( error );
360
361 size_t nverts = ngbvs.size();
362 assert( nverts );
363 double* ngbcoords = new double[nverts * 3];
364 error = mbImpl->get_coords( ngbvs, ngbcoords );MB_CHK_ERR( error );
365
366 double* ngbtangs = new double[nverts * 3];
367 error = get_tangents_curve( ngbvs, ngbtangs );MB_CHK_ERR( error );
368
369 int index = ngbvs.index( vid );
370 assert( index != -1 );
371 std::swap( ngbcoords[0], ngbcoords[3 * index] );
372 std::swap( ngbcoords[1], ngbcoords[3 * index + 1] );
373 std::swap( ngbcoords[2], ngbcoords[3 * index + 2] );
374 std::swap( ngbtangs[0], ngbtangs[3 * index] );
375 std::swap( ngbtangs[1], ngbtangs[3 * index + 1] );
376 std::swap( ngbtangs[2], ngbtangs[3 * index + 2] );
377
378 polyfit3d_curve_get_coeff( nverts, ngbcoords, ngbtangs, degree, interp, safeguard, ncoords, coords, ncoeffs, coeffs,
379 degree_out );
380 delete[] ngbcoords;
381 delete[] ngbtangs;
382 return error;
383 }
384
385
388
389 ErrorCode HiReconstruction::hiproj_walf_in_element( EntityHandle elem,
390 const int nvpe,
391 const int npts2fit,
392 const double* naturalcoords2fit,
393 double* newcoords )
394 {
395 assert( newcoords );
396 ErrorCode error;
397
398 std::vector< EntityHandle > elemconn;
399 error = mbImpl->get_connectivity( &elem, 1, elemconn );MB_CHK_ERR( error );
400 if( nvpe != (int)elemconn.size() )
401 {
402 MB_SET_ERR( MB_FAILURE, "element connectivity table size doesn't match input size" );
403 }
404
405 if( !_hasfittings )
406 {
407 MB_SET_ERR( MB_FAILURE, "There is no existing fitting results" );
408 }
409 else
410 {
411 std::ostringstream convert;
412 convert << elem;
413 std::string ID = convert.str();
414 for( int i = 0; i < nvpe; ++i )
415 {
416 if( -1 == _verts2rec.index( elemconn[i] ) )
417 {
418 MB_SET_ERR( MB_FAILURE, "There is no existing fitting results for element " + ID );
419 }
420 }
421 }
422
423 for( int i = 0; i < npts2fit; ++i )
424 {
425 if( !check_barycentric_coords( nvpe, naturalcoords2fit + i * nvpe ) )
426 {
427 MB_SET_ERR( MB_FAILURE, "Wrong barycentric coordinates" );
428 }
429 }
430
431 double* elemcoords = new double[nvpe * 3];
432 error = mbImpl->get_coords( &( elemconn[0] ), nvpe, elemcoords );MB_CHK_ERR( error );
433
434 double* coords2fit = new double[3 * npts2fit]();
435 for( int i = 0; i < npts2fit; ++i )
436 {
437 for( int j = 0; j < nvpe; ++j )
438 {
439 coords2fit[3 * i] += naturalcoords2fit[i * nvpe + j] * elemcoords[3 * j];
440 coords2fit[3 * i + 1] += naturalcoords2fit[i * nvpe + j] * elemcoords[3 * j + 1];
441 coords2fit[3 * i + 2] += naturalcoords2fit[i * nvpe + j] * elemcoords[3 * j + 2];
442 }
443 }
444
445 double* hiproj_new = new double[3 * npts2fit];
446
447 for( int i = 0; i < npts2fit; ++i )
448 {
449 newcoords[3 * i] = newcoords[3 * i + 1] = newcoords[3 * i + 2] = 0;
450 }
451
452 for( int j = 0; j < nvpe; ++j )
453 {
454 error = hiproj_walf_around_vertex( elemconn[j], npts2fit, coords2fit, hiproj_new );MB_CHK_ERR( error );
455 for( int i = 0; i < npts2fit; ++i )
456 {
457 newcoords[3 * i] += naturalcoords2fit[i * nvpe + j] * hiproj_new[3 * i];
458 newcoords[3 * i + 1] += naturalcoords2fit[i * nvpe + j] * hiproj_new[3 * i + 1];
459 newcoords[3 * i + 2] += naturalcoords2fit[i * nvpe + j] * hiproj_new[3 * i + 2];
460 }
461 }
462 delete[] elemcoords;
463 delete[] coords2fit;
464 delete[] hiproj_new;
465 return error;
466 }
467
468 ErrorCode HiReconstruction::hiproj_walf_around_vertex( EntityHandle vid,
469 const int npts2fit,
470 const double* coords2fit,
471 double* hiproj_new )
472 {
473 if( !_hasfittings )
474 {
475 MB_SET_ERR( MB_FAILURE, "There is no existing fitting results" );
476 }
477 else if( -1 == _verts2rec.index( vid ) )
478 {
479 std::ostringstream convert;
480 convert << vid;
481 std::string VID = convert.str();
482 MB_SET_ERR( MB_FAILURE, "There is no existing fitting results for vertex " + VID );
483 }
484 ErrorCode error;
485
486 double local_origin[3];
487 error = mbImpl->get_coords( &vid, 1, local_origin );MB_CHK_ERR( error );
488
489 int index = _verts2rec.index( vid );
490 bool interp = _interps[index];
491 int local_deg = _degrees_out[index];
492 double *uvw_coords, *local_coeffs;
493 if( _geom == HISURFACE )
494 {
495 uvw_coords = &( _local_coords[9 * index] );
496
497 size_t istr = _vertID2coeffID[index];
498 local_coeffs = &( _local_fit_coeffs[istr] );
499 walf3d_surf_vertex_eval( local_origin, uvw_coords, local_deg, local_coeffs, interp, npts2fit, coords2fit,
500 hiproj_new );
501 }
502 else if( _geom == HI3DCURVE )
503 {
504 uvw_coords = &( _local_coords[3 * index] );
505 size_t istr = _vertID2coeffID[index];
506 local_coeffs = &( _local_fit_coeffs[istr] );
507 walf3d_curve_vertex_eval( local_origin, uvw_coords, local_deg, local_coeffs, interp, npts2fit, coords2fit,
508 hiproj_new );
509 }
510 return error;
511 }
512
513 void HiReconstruction::walf3d_surf_vertex_eval( const double* local_origin,
514 const double* local_coords,
515 const int local_deg,
516 const double* local_coeffs,
517 const bool interp,
518 const int npts2fit,
519 const double* coords2fit,
520 double* hiproj_new )
521 {
522 double xaxis[3], yaxis[3], zaxis[3];
523 for( int i = 0; i < 3; ++i )
524 {
525 xaxis[i] = local_coords[i];
526 yaxis[i] = local_coords[3 + i];
527 zaxis[i] = local_coords[6 + i];
528 }
529
530 std::vector< double > basis( ( local_deg + 2 ) * ( local_deg + 1 ) / 2 - 1 );
531 for( int i = 0; i < npts2fit; ++i )
532 {
533 double local_pos[3];
534 for( int j = 0; j < 3; ++j )
535 {
536 local_pos[j] = coords2fit[3 * i + j] - local_origin[j];
537 }
538 double u, v, height = 0;
539 u = DGMSolver::vec_innerprod( 3, local_pos, xaxis );
540 v = DGMSolver::vec_innerprod( 3, local_pos, yaxis );
541 basis[0] = u;
542 basis[1] = v;
543 int l = 1;
544 for( int k = 2; k <= local_deg; ++k )
545 {
546 ++l;
547 basis[l] = u * basis[l - k];
548 for( int id = 0; id < k; ++id )
549 {
550 ++l;
551 basis[l] = basis[l - k - 1] * v;
552 }
553 }
554 if( !interp )
555 {
556 height = local_coeffs[0];
557 }
558 for( int p = 0; p <= l; ++p )
559 {
560 height += local_coeffs[p + 1] * basis[p];
561 }
562 hiproj_new[3 * i] = local_origin[0] + u * xaxis[0] + v * yaxis[0] + height * zaxis[0];
563 hiproj_new[3 * i + 1] = local_origin[1] + u * xaxis[1] + v * yaxis[1] + height * zaxis[1];
564 hiproj_new[3 * i + 2] = local_origin[2] + u * xaxis[2] + v * yaxis[2] + height * zaxis[2];
565 }
566
567 }
568
569 void HiReconstruction::walf3d_curve_vertex_eval( const double* local_origin,
570 const double* local_coords,
571 const int local_deg,
572 const double* local_coeffs,
573 const bool interp,
574 const int npts2fit,
575 const double* coords2fit,
576 double* hiproj_new )
577 {
578 assert( local_origin && local_coords && local_coeffs );
579 int ncoeffspvpd = local_deg + 1;
580 for( int i = 0; i < npts2fit; ++i )
581 {
582
583 double vec[3], ans[3] = { 0, 0, 0 };
584 DGMSolver::vec_linear_operation( 3, 1, coords2fit + 3 * i, -1, local_origin, vec );
585 double u = DGMSolver::vec_innerprod( 3, local_coords, vec );
586
587 if( !interp )
588 {
589 ans[0] = local_coeffs[0];
590 ans[1] = local_coeffs[ncoeffspvpd];
591 ans[2] = local_coeffs[2 * ncoeffspvpd];
592 }
593 double uk = 1;
594 for( int j = 1; j < ncoeffspvpd; ++j )
595 {
596 uk *= u;
597 ans[0] += uk * local_coeffs[j];
598 ans[1] += uk * local_coeffs[j + ncoeffspvpd];
599 ans[2] += uk * local_coeffs[j + 2 * ncoeffspvpd];
600 }
601 hiproj_new[3 * i] = ans[0] + local_origin[0];
602 hiproj_new[3 * i + 1] = ans[1] + local_origin[1];
603 hiproj_new[3 * i + 2] = ans[2] + local_origin[2];
604 }
605 }
606
607 bool HiReconstruction::get_fittings_data( EntityHandle vid,
608 GEOMTYPE& geomtype,
609 std::vector< double >& coords,
610 int& degree_out,
611 std::vector< double >& coeffs,
612 bool& interp )
613 {
614 if( !_hasfittings )
615 {
616 return false;
617 }
618 else
619 {
620 int index = _verts2rec.index( vid );
621 if( -1 == index )
622 {
623 std::cout << "Input vertex is not locally hosted vertex in this mesh set" << std::endl;
624 return false;
625 }
626 geomtype = _geom;
627 if( HISURFACE == _geom )
628 {
629 coords.insert( coords.end(), _local_coords.begin() + 9 * index, _local_coords.begin() + 9 * index + 9 );
630 degree_out = _degrees_out[index];
631 interp = _interps[index];
632 int ncoeffs = ( degree_out + 2 ) * ( degree_out + 1 ) >> 1;
633 size_t istr = _vertID2coeffID[index];
634 coeffs.insert( coeffs.end(), _local_fit_coeffs.begin() + istr, _local_fit_coeffs.begin() + istr + ncoeffs );
635 }
636 else if( HI3DCURVE == _geom )
637 {
638 coords.insert( coords.end(), _local_coords.begin() + 3 * index, _local_coords.begin() + 3 * index + 3 );
639 degree_out = _degrees_out[index];
640 interp = _interps[index];
641 int ncoeffs = 3 * ( degree_out + 1 );
642 size_t istr = _vertID2coeffID[index];
643 coeffs.insert( coeffs.end(), _local_fit_coeffs.begin() + istr, _local_fit_coeffs.begin() + istr + ncoeffs );
644 }
645 return true;
646 }
647 }
648
649
652
653 int HiReconstruction::estimate_num_rings( int degree, bool interp )
654 {
655 return interp ? ( ( degree + 1 ) >> 1 ) + ( ( degree + 1 ) & 1 ) : ( ( degree + 2 ) >> 1 ) + ( ( degree + 2 ) & 1 );
656 }
657
658 ErrorCode HiReconstruction::vertex_get_incident_elements( const EntityHandle& vid,
659 const int elemdim,
660 std::vector< EntityHandle >& adjents )
661 {
662 ErrorCode error;
663 assert( elemdim == _dim );
664 #ifdef HIREC_USE_AHF
665 error = ahf->get_up_adjacencies( vid, elemdim, adjents );MB_CHK_ERR( error );
666 #else
667 error = mbImpl->get_adjacencies( &vid, 1, elemdim, false, adjents );MB_CHK_ERR( error );
668 #endif
669 return error;
670 }
671
672 ErrorCode HiReconstruction::obtain_nring_ngbvs( const EntityHandle vid, int ring, const int minpnts, Range& ngbvs )
673 {
674 ErrorCode error;
675 std::deque< EntityHandle > todo;
676 todo.push_back( vid );
677 ngbvs.insert( vid );
678 EntityHandle pre, nxt;
679 for( int i = 1; i <= ring; ++i )
680 {
681 int count = todo.size();
682 while( count )
683 {
684 EntityHandle center = todo.front();
685 todo.pop_front();
686 --count;
687 std::vector< EntityHandle > adjents;
688 error = vertex_get_incident_elements( center, _dim, adjents );MB_CHK_ERR( error );
689 for( size_t j = 0; j < adjents.size(); ++j )
690 {
691 std::vector< EntityHandle > elemconn;
692 error = mbImpl->get_connectivity( &adjents[j], 1, elemconn );MB_CHK_ERR( error );
693 int nvpe = elemconn.size();
694 for( int k = 0; k < nvpe; ++k )
695 {
696 if( elemconn[k] == center )
697 {
698 pre = k == 0 ? elemconn[nvpe - 1] : elemconn[k - 1];
699 nxt = elemconn[( k + 1 ) % nvpe];
700 if( ngbvs.find( pre ) == ngbvs.end() )
701 {
702 ngbvs.insert( pre );
703 todo.push_back( pre );
704 }
705 if( ngbvs.find( nxt ) == ngbvs.end() )
706 {
707 ngbvs.insert( nxt );
708 todo.push_back( nxt );
709 }
710 break;
711 }
712 }
713 }
714 }
715 if( _MAXPNTS <= (int)ngbvs.size() )
716 {
717
718 return error;
719 }
720 if( !todo.size() )
721 {
722
723 return error;
724 }
725 if( ( i == ring ) && ( minpnts > (int)ngbvs.size() ) )
726 {
727
728 ++ring;
729 }
730 }
731 return error;
732 }
733
734 void HiReconstruction::initialize_surf_geom( const int degree )
735 {
736 if( !_hasderiv )
737 {
738 compute_average_vertex_normals_surf();
739 _hasderiv = true;
740 }
741 if( !_initfittings )
742 {
743 int ncoeffspv = ( degree + 2 ) * ( degree + 1 ) / 2;
744 _degrees_out.assign( _nv2rec, 0 );
745 _interps.assign( _nv2rec, false );
746 _vertID2coeffID.resize( _nv2rec );
747 _local_fit_coeffs.assign( _nv2rec * ncoeffspv, 0 );
748 for( size_t i = 0; i < _nv2rec; ++i )
749 {
750 _vertID2coeffID[i] = i * ncoeffspv;
751 }
752 _initfittings = true;
753 }
754 }
755
756 void HiReconstruction::initialize_surf_geom( const size_t npts, const int* degrees )
757 {
758 if( !_hasderiv )
759 {
760 compute_average_vertex_normals_surf();
761 _hasderiv = true;
762 }
763 if( !_initfittings )
764 {
765 assert( _nv2rec == npts );
766 _degrees_out.assign( _nv2rec, 0 );
767 _interps.assign( _nv2rec, false );
768 _vertID2coeffID.resize( _nv2rec );
769 size_t index = 0;
770 for( size_t i = 0; i < _nv2rec; ++i )
771 {
772 _vertID2coeffID[i] = index;
773 index += ( degrees[i] + 2 ) * ( degrees[i] + 1 ) / 2;
774 }
775 _local_fit_coeffs.assign( index, 0 );
776 _initfittings = true;
777 }
778 }
779
780 void HiReconstruction::initialize_3Dcurve_geom( const int degree )
781 {
782 if( !_hasderiv )
783 {
784 compute_average_vertex_tangents_curve();
785 _hasderiv = true;
786 }
787 if( !_initfittings )
788 {
789 int ncoeffspvpd = degree + 1;
790 _degrees_out.assign( _nv2rec, 0 );
791 _interps.assign( _nv2rec, false );
792 _vertID2coeffID.resize( _nv2rec );
793 _local_fit_coeffs.assign( _nv2rec * ncoeffspvpd * 3, 0 );
794 for( size_t i = 0; i < _nv2rec; ++i )
795 {
796 _vertID2coeffID[i] = i * ncoeffspvpd * 3;
797 }
798 _initfittings = true;
799 }
800 }
801
802 void HiReconstruction::initialize_3Dcurve_geom( const size_t npts, const int* degrees )
803 {
804 if( !_hasderiv )
805 {
806 compute_average_vertex_tangents_curve();
807 _hasderiv = true;
808 }
809 if( !_hasfittings )
810 {
811 assert( _nv2rec == npts );
812 _degrees_out.assign( _nv2rec, 0 );
813 _interps.assign( _nv2rec, false );
814 _vertID2coeffID.reserve( _nv2rec );
815 size_t index = 0;
816 for( size_t i = 0; i < _nv2rec; ++i )
817 {
818 _vertID2coeffID[i] = index;
819 index += 3 * ( degrees[i] + 1 );
820 }
821 _local_fit_coeffs.assign( index, 0 );
822 _initfittings = true;
823 }
824 }
825
826
837
838
841 ErrorCode HiReconstruction::average_vertex_normal( const EntityHandle vid, double* nrm )
842 {
843 ErrorCode error;
844 std::vector< EntityHandle > adjfaces;
845 error = vertex_get_incident_elements( vid, 2, adjfaces );MB_CHK_ERR( error );
846 int npolys = adjfaces.size();
847 if( !npolys )
848 {
849 MB_SET_ERR( MB_FAILURE, "Vertex has no incident 2D entities" );
850 }
851 else
852 {
853 double v1[3], v2[3], v3[3], a[3], b[3], c[3];
854 nrm[0] = nrm[1] = nrm[2] = 0;
855 for( int i = 0; i < npolys; ++i )
856 {
857
858 std::vector< EntityHandle > elemconn;
859 error = mbImpl->get_connectivity( &adjfaces[i], 1, elemconn );MB_CHK_ERR( error );
860 EntityHandle pre, nxt;
861 int nvpe = elemconn.size();
862 for( int j = 0; j < nvpe; ++j )
863 {
864 if( vid == elemconn[j] )
865 {
866 pre = j == 0 ? elemconn[nvpe - 1] : elemconn[j - 1];
867 nxt = elemconn[( j + 1 ) % nvpe];
868 break;
869 }
870 }
871
872 error = mbImpl->get_coords( &pre, 1, a );MB_CHK_ERR( error );
873 error = mbImpl->get_coords( &vid, 1, b );MB_CHK_ERR( error );
874 error = mbImpl->get_coords( &nxt, 1, c );MB_CHK_ERR( error );
875 DGMSolver::vec_linear_operation( 3, 1, c, -1, b, v1 );
876 DGMSolver::vec_linear_operation( 3, 1, a, -1, b, v2 );
877 DGMSolver::vec_crossprod( v1, v2, v3 );
878 DGMSolver::vec_linear_operation( 3, 1, nrm, 1, v3, nrm );
879 }
880 #ifndef NDEBUG
881 assert( DGMSolver::vec_normalize( 3, nrm, nrm ) );
882 #endif
883 }
884 return error;
885 }
886
887 ErrorCode HiReconstruction::compute_average_vertex_normals_surf()
888 {
889 if( _hasderiv )
890 {
891 return MB_SUCCESS;
892 }
893 ErrorCode error;
894 _local_coords.assign( 9 * _nv2rec, 0 );
895 size_t index = 0;
896 for( Range::iterator ivert = _verts2rec.begin(); ivert != _verts2rec.end(); ++ivert, ++index )
897 {
898 error = average_vertex_normal( *ivert, &( _local_coords[9 * index + 6] ) );MB_CHK_ERR( error );
899 }
900 return error;
901 }
902
903 ErrorCode HiReconstruction::get_normals_surf( const Range& vertsh, double* nrms )
904 {
905 ErrorCode error = MB_SUCCESS;
906 if( _hasderiv )
907 {
908 size_t id = 0;
909 for( Range::iterator ivert = vertsh.begin(); ivert != vertsh.end(); ++ivert, ++id )
910 {
911 int index = _verts2rec.index( *ivert );
912 #ifdef MOAB_HAVE_MPI
913 if( -1 == index )
914 {
915
916 error = average_vertex_normal( *ivert, nrms + 3 * id );MB_CHK_ERR( error );
917 }
918 else
919 {
920 nrms[3 * id] = _local_coords[9 * index + 6];
921 nrms[3 * id + 1] = _local_coords[9 * index + 7];
922 nrms[3 * id + 2] = _local_coords[9 * index + 8];
923 }
924 #else
925 assert( -1 != index );
926 nrms[3 * id] = _local_coords[9 * index + 6];
927 nrms[3 * id + 1] = _local_coords[9 * index + 7];
928 nrms[3 * id + 2] = _local_coords[9 * index + 8];
929 #endif
930 }
931 }
932 else
933 {
934 size_t id = 0;
935 for( Range::iterator ivert = vertsh.begin(); ivert != vertsh.end(); ++ivert, ++id )
936 {
937 error = average_vertex_normal( *ivert, nrms + 3 * id );MB_CHK_ERR( error );
938 }
939 }
940 return error;
941 }
942
943 ErrorCode HiReconstruction::average_vertex_tangent( const EntityHandle vid, double* tang )
944 {
945 ErrorCode error;
946 std::vector< EntityHandle > adjedges;
947 error = vertex_get_incident_elements( vid, 1, adjedges );MB_CHK_ERR( error );
948 int nedges = adjedges.size();
949 if( !nedges )
950 {
951 MB_SET_ERR( MB_FAILURE, "Vertex has no incident edges" );
952 }
953 else
954 {
955 assert( nedges <= 2 );
956 tang[0] = tang[1] = tang[2] = 0;
957 for( int i = 0; i < nedges; ++i )
958 {
959 std::vector< EntityHandle > edgeconn;
960 error = mbImpl->get_connectivity( &adjedges[i], 1, edgeconn );
961 double istr[3], iend[3], t[3];
962 error = mbImpl->get_coords( &( edgeconn[0] ), 1, istr );
963 error = mbImpl->get_coords( &( edgeconn[1] ), 1, iend );
964 DGMSolver::vec_linear_operation( 3, 1, iend, -1, istr, t );
965 DGMSolver::vec_linear_operation( 3, 1, tang, 1, t, tang );
966 }
967 #ifndef NDEBUG
968 assert( DGMSolver::vec_normalize( 3, tang, tang ) );
969 #endif
970 }
971 return error;
972 }
973
974 ErrorCode HiReconstruction::compute_average_vertex_tangents_curve()
975 {
976 if( _hasderiv )
977 {
978 return MB_SUCCESS;
979 }
980 ErrorCode error;
981 _local_coords.assign( 3 * _nv2rec, 0 );
982 size_t index = 0;
983 for( Range::iterator ivert = _verts2rec.begin(); ivert != _verts2rec.end(); ++ivert, ++index )
984 {
985 error = average_vertex_tangent( *ivert, &( _local_coords[3 * index] ) );MB_CHK_ERR( error );
986 }
987 return error;
988 }
989
990 ErrorCode HiReconstruction::get_tangents_curve( const Range& vertsh, double* tangs )
991 {
992 ErrorCode error = MB_SUCCESS;
993 if( _hasderiv )
994 {
995 size_t id = 0;
996 for( Range::iterator ivert = vertsh.begin(); ivert != vertsh.end(); ++ivert, ++id )
997 {
998 int index = _verts2rec.index( *ivert );
999 #ifdef MOAB_HAVE_MPI
1000 if( -1 != index )
1001 {
1002 tangs[3 * id] = _local_coords[3 * index];
1003 tangs[3 * id + 1] = _local_coords[3 * index + 1];
1004 tangs[3 * id + 2] = _local_coords[3 * index + 2];
1005 }
1006 else
1007 {
1008 error = average_vertex_tangent( *ivert, tangs + 3 * id );MB_CHK_ERR( error );
1009 }
1010 #else
1011 assert( -1 != index );
1012 tangs[3 * id] = _local_coords[3 * index];
1013 tangs[3 * id + 1] = _local_coords[3 * index + 1];
1014 tangs[3 * id + 2] = _local_coords[3 * index + 2];
1015 #endif
1016 }
1017 }
1018 else
1019 {
1020 size_t id = 0;
1021 for( Range::iterator ivert = vertsh.begin(); ivert != vertsh.end(); ++ivert, ++id )
1022 {
1023 error = average_vertex_tangent( *ivert, tangs + 3 * id );MB_CHK_ERR( error );
1024 }
1025 }
1026 return error;
1027 }
1028
1029
1032
1033 void HiReconstruction::polyfit3d_surf_get_coeff( const int nverts,
1034 const double* ngbcoords,
1035 const double* ngbnrms,
1036 int degree,
1037 const bool interp,
1038 const bool safeguard,
1039 const int ncoords,
1040 double* coords,
1041 const int ncoeffs,
1042 double* coeffs,
1043 int* degree_out,
1044 int* degree_pnt,
1045 int* degree_qr )
1046 {
1047 if( nverts <= 0 )
1048 {
1049 return;
1050 }
1051
1052
1053
1054
1055
1056
1057 double nrm[3] = { ngbnrms[0], ngbnrms[1], ngbnrms[2] }, tang1[3] = { 0, 0, 0 }, tang2[3] = { 0, 0, 0 };
1058 if( fabs( nrm[0] ) > fabs( nrm[1] ) && fabs( nrm[0] ) > fabs( nrm[2] ) )
1059 {
1060 tang1[1] = 1.0;
1061 }
1062 else
1063 {
1064 tang1[0] = 1.0;
1065 }
1066
1067 DGMSolver::vec_projoff( 3, tang1, nrm, tang1 );
1068 #ifndef NDEBUG
1069 assert( DGMSolver::vec_normalize( 3, tang1, tang1 ) );
1070 #endif
1071 DGMSolver::vec_crossprod( nrm, tang1, tang2 );
1072 if( 9 <= ncoords && coords )
1073 {
1074 coords[0] = tang1[0];
1075 coords[1] = tang1[1];
1076 coords[2] = tang1[2];
1077 coords[3] = tang2[0];
1078 coords[4] = tang2[1];
1079 coords[5] = tang2[2];
1080 coords[6] = nrm[0];
1081 coords[7] = nrm[1];
1082 coords[8] = nrm[2];
1083 }
1084 if( !ncoeffs || !coeffs )
1085 {
1086 return;
1087 }
1088 else
1089 {
1090 assert( ncoeffs >= ( degree + 2 ) * ( degree + 1 ) / 2 );
1091 }
1092
1093
1094 int npts2fit = nverts - interp;
1095 if( 0 == npts2fit )
1096 {
1097 *degree_out = *degree_pnt = *degree_qr = 0;
1098 for( int i = 0; i < ncoeffs; ++i )
1099 {
1100 coeffs[i] = 0;
1101 }
1102
1103 return;
1104 }
1105 std::vector< double > us( npts2fit * 2 );
1106 std::vector< double > bs( npts2fit );
1107 for( int i = interp; i < nverts; ++i )
1108 {
1109 int k = i - interp;
1110 double uu[3];
1111 DGMSolver::vec_linear_operation( 3, 1, ngbcoords + 3 * i, -1, ngbcoords, uu );
1112 us[k * 2] = DGMSolver::vec_innerprod( 3, tang1, uu );
1113 us[k * 2 + 1] = DGMSolver::vec_innerprod( 3, tang2, uu );
1114 bs[k] = DGMSolver::vec_innerprod( 3, nrm, uu );
1115 }
1116
1117
1118 std::vector< double > ws( npts2fit );
1119 int nzeros = compute_weights( npts2fit, 2, &( us[0] ), nverts, ngbnrms, degree, _MINEPS, &( ws[0] ) );
1120
1121
1122 if( nzeros )
1123 {
1124 if( nzeros == npts2fit )
1125 {
1126 *degree_out = *degree_pnt = *degree_qr = 0;
1127 for( int i = 0; i < ncoeffs; ++i )
1128 {
1129 coeffs[i] = 0;
1130 }
1131
1132 return;
1133 }
1134 int index = 0;
1135 for( int i = 0; i < npts2fit; ++i )
1136 {
1137 if( ws[i] )
1138 {
1139 if( i > index )
1140 {
1141 us[index * 2] = us[i * 2];
1142 us[index * 2 + 1] = us[i * 2 + 1];
1143 bs[index] = bs[i];
1144 ws[index] = ws[i];
1145 }
1146 ++index;
1147 }
1148 }
1149 npts2fit -= nzeros;
1150 assert( index == npts2fit );
1151 us.resize( npts2fit * 2 );
1152 bs.resize( npts2fit );
1153 ws.resize( npts2fit );
1154
1157 }
1158
1159
1160
1161
1162 eval_vander_bivar_cmf( npts2fit, &( us[0] ), 1, &( bs[0] ), degree, &( ws[0] ), interp, safeguard, degree_out,
1163 degree_pnt, degree_qr );
1164
1165
1166 int ncoeffs_out = ( *degree_out + 2 ) * ( *degree_out + 1 ) / 2;
1167 assert( ncoeffs_out <= ncoeffs );
1168 coeffs[0] = 0;
1169 for( int j = 0; j < ncoeffs_out - interp; ++j )
1170 {
1171 coeffs[j + interp] = bs[j];
1172 }
1173
1174 }
1175
1176 void HiReconstruction::eval_vander_bivar_cmf( const int npts2fit,
1177 const double* us,
1178 const int ndim,
1179 double* bs,
1180 int degree,
1181 const double* ws,
1182 const bool interp,
1183 const bool safeguard,
1184 int* degree_out,
1185 int* degree_pnt,
1186 int* degree_qr )
1187 {
1188
1189 int ncols = ( ( ( degree + 2 ) * ( degree + 1 ) ) >> 1 ) - interp;
1190 while( 1 < degree && npts2fit < ncols )
1191 {
1192 --degree;
1193 ncols = ( ( ( degree + 2 ) * ( degree + 1 ) ) >> 1 ) - interp;
1194 }
1195 *degree_pnt = degree;
1196
1197
1198
1199
1200 std::vector< double > V;
1201 DGMSolver::gen_vander_multivar( npts2fit, 2, us, degree, V );
1202
1203 if( interp )
1204 {
1205 V.erase( V.begin(), V.begin() + npts2fit );
1206 }
1207
1215
1216
1217 for( int i = 0; i < npts2fit; ++i )
1218 {
1219 for( int j = 0; j < ncols; ++j )
1220 {
1221 V[j * npts2fit + i] *= ws[i];
1222 }
1223 for( int k = 0; k < ndim; ++k )
1224 {
1225 bs[k * npts2fit + i] *= ws[i];
1226 }
1227 }
1228
1229
1230 std::vector< double > ts( ncols );
1231 DGMSolver::rescale_matrix( npts2fit, ncols, &( V[0] ), &( ts[0] ) );
1232
1233
1234 std::vector< double > D( ncols );
1235 int rank;
1236 DGMSolver::qr_polyfit_safeguarded( npts2fit, ncols, &( V[0] ), &( D[0] ), &rank );
1237
1238
1239 int ncols_sub = ncols;
1240 while( rank < ncols_sub )
1241 {
1242 --degree;
1243 if( degree == 0 )
1244 {
1245
1246 *degree_out = *degree_qr = degree;
1247 for( int i = 0; i < npts2fit; ++i )
1248 {
1249 for( int k = 0; k < ndim; ++k )
1250 {
1251 bs[k * npts2fit + i] = 0;
1252 }
1253 }
1254 return;
1255 }
1256 else
1257 {
1258 ncols_sub = ( ( ( degree + 2 ) * ( degree + 1 ) ) >> 1 ) - interp;
1259 }
1260 }
1261 *degree_qr = degree;
1262
1263
1264
1265
1276
1277
1278 DGMSolver::compute_qtransposeB( npts2fit, ncols_sub, &( V[0] ), ndim, bs );
1279
1280
1290
1291
1292
1293 for( int i = 0; i < ncols_sub; ++i )
1294 {
1295 V[i * npts2fit + i] = D[i];
1296 }
1297
1298
1299 if( safeguard )
1300 {
1301
1302
1303 DGMSolver::backsolve_polyfit_safeguarded( 2, degree, interp, npts2fit, ncols_sub, &( V[0] ), ndim, bs,
1304 &( ts[0] ), degree_out );
1305 }
1306 else
1307 {
1308 DGMSolver::backsolve( npts2fit, ncols_sub, &( V[0] ), 1, bs, &( ts[0] ) );
1309 *degree_out = degree;
1310 }
1311
1316 }
1317
1318 void HiReconstruction::polyfit3d_curve_get_coeff( const int nverts,
1319 const double* ngbcors,
1320 const double* ngbtangs,
1321 int degree,
1322 const bool interp,
1323 const bool safeguard,
1324 const int ncoords,
1325 double* coords,
1326 const int ncoeffs,
1327 double* coeffs,
1328 int* degree_out )
1329 {
1330 if( !nverts )
1331 {
1332 return;
1333 }
1334
1335 double tang[3] = { ngbtangs[0], ngbtangs[1], ngbtangs[2] };
1336 if( coords && ncoords > 2 )
1337 {
1338 coords[0] = tang[0];
1339 coords[1] = tang[1];
1340 coords[2] = tang[2];
1341 }
1342 if( !coeffs || !ncoeffs )
1343 {
1344 return;
1345 }
1346 else
1347 {
1348 assert( ncoeffs >= 3 * ( degree + 1 ) );
1349 }
1350
1351 int npts2fit = nverts - interp;
1352 if( !npts2fit )
1353 {
1354 *degree_out = 0;
1355 for( int i = 0; i < ncoeffs; ++i )
1356 {
1357 coeffs[0] = 0;
1358 }
1359 return;
1360 }
1361 std::vector< double > us( npts2fit );
1362 std::vector< double > bs( npts2fit * 3 );
1363 double uu[3];
1364 for( int i = interp; i < nverts; ++i )
1365 {
1366 int k = i - interp;
1367 DGMSolver::vec_linear_operation( 3, 1, ngbcors + 3 * i, -1, ngbcors, uu );
1368 us[k] = DGMSolver::vec_innerprod( 3, uu, tang );
1369 bs[k] = uu[0];
1370 bs[npts2fit + k] = uu[1];
1371 bs[2 * npts2fit + k] = uu[2];
1372 }
1373
1374
1375 std::vector< double > ws( npts2fit );
1376 int nzeros = compute_weights( npts2fit, 1, &( us[0] ), nverts, ngbtangs, degree, _MINEPS, &( ws[0] ) );
1377 assert( nzeros <= npts2fit );
1378
1379
1380 if( nzeros )
1381 {
1382 if( nzeros == npts2fit )
1383 {
1384
1385 *degree_out = 0;
1386 for( int i = 0; i < ncoeffs; ++i )
1387 {
1388 coeffs[i] = 0;
1389 }
1390 return;
1391 }
1392 int npts_new = npts2fit - nzeros;
1393 std::vector< double > bs_temp( 3 * npts_new );
1394 int index = 0;
1395 for( int i = 0; i < npts2fit; ++i )
1396 {
1397 if( ws[i] )
1398 {
1399 if( i > index )
1400 {
1401 us[index] = us[i];
1402 ws[index] = ws[i];
1403 }
1404 bs_temp[index] = bs[i];
1405 bs_temp[index + npts_new] = bs[i + npts2fit];
1406 bs_temp[index + 2 * npts_new] = bs[i + 2 * npts2fit];
1407 ++index;
1408 }
1409 }
1410 assert( index == npts_new );
1411 npts2fit = npts_new;
1412 us.resize( index );
1413 ws.resize( index );
1414 bs = bs_temp;
1415
1416 std::vector< double >().swap( bs_temp );
1417 }
1418
1419
1420 eval_vander_univar_cmf( npts2fit, &( us[0] ), 3, &( bs[0] ), degree, &( ws[0] ), interp, safeguard, degree_out );
1421
1422 int ncoeffs_out_pvpd = *degree_out + 1;
1423 assert( ncoeffs >= 3 * ncoeffs_out_pvpd );
1424
1425 coeffs[0] = coeffs[ncoeffs_out_pvpd] = coeffs[2 * ncoeffs_out_pvpd] = 0;
1426 for( int i = 0; i < ncoeffs_out_pvpd - interp; ++i )
1427 {
1428 coeffs[i + interp] = bs[i];
1429 coeffs[i + interp + ncoeffs_out_pvpd] = bs[i + npts2fit];
1430 coeffs[i + interp + 2 * ncoeffs_out_pvpd] = bs[i + 2 * npts2fit];
1431 }
1432 }
1433
1434 void HiReconstruction::eval_vander_univar_cmf( const int npts2fit,
1435 const double* us,
1436 const int ndim,
1437 double* bs,
1438 int degree,
1439 const double* ws,
1440 const bool interp,
1441 const bool safeguard,
1442 int* degree_out )
1443 {
1444
1445 int ncols = degree + 1 - interp;
1446 while( npts2fit < ncols && degree >= 1 )
1447 {
1448 --degree;
1449 ncols = degree + 1 - interp;
1450 }
1451 if( !degree )
1452 {
1453 if( interp )
1454 {
1455 for( int icol = 0; icol < ndim; ++icol )
1456 {
1457 bs[icol * npts2fit] = 0;
1458 }
1459 }
1460 for( int irow = 1; irow < npts2fit; ++irow )
1461 {
1462 for( int icol = 0; icol < ndim; ++icol )
1463 {
1464 bs[icol * npts2fit + irow] = 0;
1465 }
1466 }
1467 *degree_out = 0;
1468 return;
1469 }
1470
1471 std::vector< double > V;
1472 DGMSolver::gen_vander_multivar( npts2fit, 1, us, degree, V );
1473
1474 if( interp )
1475 {
1476 V.erase( V.begin(), V.begin() + npts2fit );
1477 }
1478
1479
1480 for( int i = 0; i < npts2fit; ++i )
1481 {
1482 for( int j = 0; j < ncols; ++j )
1483 {
1484 V[j * npts2fit + i] *= ws[i];
1485 }
1486 for( int k = 0; k < ndim; ++k )
1487 {
1488 bs[k * npts2fit + i] *= ws[i];
1489 }
1490 }
1491
1492
1493 std::vector< double > ts( ncols );
1494 DGMSolver::rescale_matrix( npts2fit, ncols, &( V[0] ), &( ts[0] ) );
1495
1496
1497 std::vector< double > D( ncols );
1498 int rank;
1499 DGMSolver::qr_polyfit_safeguarded( npts2fit, ncols, &( V[0] ), &( D[0] ), &rank );
1500
1501
1502 int ncols_sub = ncols;
1503 while( rank < ncols_sub )
1504 {
1505 --degree;
1506 if( !degree )
1507 {
1508
1509
1510 *degree_out = 0;
1511 for( int i = 0; i < npts2fit; ++i )
1512 {
1513 for( int k = 0; k < ndim; ++k )
1514 {
1515 bs[k * npts2fit + i] = 0;
1516 }
1517 }
1518 }
1519 ncols_sub = degree + 1 - interp;
1520 }
1521
1522
1523 DGMSolver::compute_qtransposeB( npts2fit, ncols_sub, &( V[0] ), ndim, bs );
1524
1525
1526
1527 for( int i = 0; i < ncols_sub; ++i )
1528 {
1529 V[i * npts2fit + i] = D[i];
1530 }
1531
1532 if( safeguard )
1533 {
1534 DGMSolver::backsolve_polyfit_safeguarded( 1, degree, interp, npts2fit, ncols, &( V[0] ), ndim, bs, ws,
1535 degree_out );
1536 }
1537 else
1538 {
1539 DGMSolver::backsolve( npts2fit, ncols_sub, &( V[0] ), ndim, bs, &( ts[0] ) );
1540 *degree_out = degree;
1541 }
1542 }
1543
1544 int HiReconstruction::compute_weights( const int nrows,
1545 const int ncols,
1546 const double* us,
1547 const int nngbs,
1548 const double* ngbnrms,
1549 const int degree,
1550 const double toler,
1551 double* ws )
1552 {
1553 assert( nrows <= _MAXPNTS && ws );
1554 bool interp = false;
1555 if( nngbs != nrows )
1556 {
1557 assert( nngbs == nrows + 1 );
1558 interp = true;
1559 }
1560 double epsilon = 1e-2;
1561
1562
1563 for( int i = 0; i < nrows; ++i )
1564 {
1565 ws[i] = DGMSolver::vec_innerprod( ncols, us + i * ncols, us + i * ncols );
1566 }
1567
1568
1569 double h = 0;
1570 for( int i = 0; i < nrows; ++i )
1571 {
1572 h += ws[i];
1573 }
1574 h /= (double)nrows;
1575
1576
1577 int nzeros = 0;
1578 for( int i = 0; i < nrows; ++i )
1579 {
1580 double costheta = DGMSolver::vec_innerprod( 3, ngbnrms, ngbnrms + 3 * ( i + interp ) );
1581 if( costheta > toler )
1582 {
1583 ws[i] = costheta * pow( ws[i] / h + epsilon, -1 * (double)degree / 2.0 );
1584 }
1585 else
1586 {
1587 ws[i] = 0;
1588 ++nzeros;
1589 }
1590 }
1591 return nzeros;
1592 }
1593 bool HiReconstruction::check_barycentric_coords( const int nws, const double* naturalcoords )
1594 {
1595 double sum = 0;
1596 for( int i = 0; i < nws; ++i )
1597 {
1598 if( naturalcoords[i] < -_MINEPS )
1599 {
1600 return false;
1601 }
1602 sum += naturalcoords[i];
1603 }
1604 if( fabs( 1 - sum ) > _MINEPS )
1605 {
1606 return false;
1607 }
1608 else
1609 {
1610 return true;
1611 }
1612 }
1613 }