00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "searchableSurfacesQueries.H"
00027 #include <OpenFOAM/ListOps.H>
00028 #include <OpenFOAM/OFstream.H>
00029 #include <meshTools/meshTools.H>
00030
00031
00032
00033 defineTypeNameAndDebug(Foam::searchableSurfacesQueries, 0);
00034
00035
00036
00037 Foam::pointIndexHit Foam::searchableSurfacesQueries::tempFindNearest
00038 (
00039 const searchableSurface& surf,
00040 const point& pt,
00041 const scalar initDistSqr
00042 )
00043 {
00044 pointField onePoint(1, pt);
00045 scalarField oneDist(1, initDistSqr);
00046 List<pointIndexHit> oneHit(1);
00047 surf.findNearest(onePoint, oneDist, oneHit);
00048 return oneHit[0];
00049 }
00050
00051
00052
00053 Foam::scalar Foam::searchableSurfacesQueries::sumDistSqr
00054 (
00055 const PtrList<searchableSurface>& allSurfaces,
00056 const labelList& surfacesToTest,
00057 const scalar initDistSqr,
00058 const point& pt
00059 )
00060 {
00061 scalar sum = 0;
00062
00063 forAll(surfacesToTest, testI)
00064 {
00065 label surfI = surfacesToTest[testI];
00066
00067 pointIndexHit hit
00068 (
00069 tempFindNearest(allSurfaces[surfI], pt, initDistSqr)
00070 );
00071
00072
00073 sum += magSqr(hit.hitPoint()-pt);
00074 }
00075 return sum;
00076 }
00077
00078
00079
00080
00081
00082 Foam::scalar Foam::searchableSurfacesQueries::tryMorphTet
00083 (
00084 const PtrList<searchableSurface>& allSurfaces,
00085 const labelList& surfacesToTest,
00086 const scalar initDistSqr,
00087 List<vector>& p,
00088 List<scalar>& y,
00089 vector& pSum,
00090 const label ihi,
00091 const scalar fac
00092 )
00093 {
00094 scalar fac1 = (1.0-fac)/vector::nComponents;
00095 scalar fac2 = fac1-fac;
00096
00097 vector ptry = pSum*fac1-p[ihi]*fac2;
00098
00099 scalar ytry = sumDistSqr(allSurfaces, surfacesToTest, initDistSqr, ptry);
00100
00101 if (ytry < y[ihi])
00102 {
00103 y[ihi] = ytry;
00104 pSum += ptry - p[ihi];
00105 p[ihi] = ptry;
00106 }
00107 return ytry;
00108 }
00109
00110
00111 bool Foam::searchableSurfacesQueries::morphTet
00112 (
00113 const PtrList<searchableSurface>& allSurfaces,
00114 const labelList& surfacesToTest,
00115 const scalar initDistSqr,
00116 const scalar convergenceDistSqr,
00117 const label maxIter,
00118 List<vector>& p,
00119 List<scalar>& y
00120 )
00121 {
00122 vector pSum = sum(p);
00123
00124 autoPtr<OFstream> str;
00125 label vertI = 0;
00126 if (debug)
00127 {
00128 wordList names(surfacesToTest.size());
00129 forAll(surfacesToTest, i)
00130 {
00131 names[i] = allSurfaces[surfacesToTest[i]].name();
00132 }
00133 Pout<< "searchableSurfacesQueries::morphTet : intersection of "
00134 << names << " starting from points:" << p << endl;
00135 str.reset(new OFstream("track.obj"));
00136 meshTools::writeOBJ(str(), p[0]);
00137 vertI++;
00138 }
00139
00140 for (label iter = 0; iter < maxIter; iter++)
00141 {
00142
00143 label ilo, ihi, inhi;
00144 {
00145 labelList sortedIndices;
00146 sortedOrder(y, sortedIndices);
00147 ilo = sortedIndices[0];
00148 ihi = sortedIndices[sortedIndices.size()-1];
00149 inhi = sortedIndices[sortedIndices.size()-2];
00150 }
00151
00152 if (debug)
00153 {
00154 Pout<< "Iteration:" << iter
00155 << " lowest:" << y[ilo] << " highest:" << y[ihi]
00156 << " points:" << p << endl;
00157
00158 meshTools::writeOBJ(str(), p[ilo]);
00159 vertI++;
00160 str()<< "l " << vertI-1 << ' ' << vertI << nl;
00161 }
00162
00163 if (y[ihi] < convergenceDistSqr)
00164 {
00165
00166 Swap(p[0], p[ilo]);
00167 Swap(y[0], y[ilo]);
00168 return true;
00169 }
00170
00171
00172 scalar ytry = tryMorphTet
00173 (
00174 allSurfaces,
00175 surfacesToTest,
00176 10*y[ihi],
00177 p,
00178 y,
00179 pSum,
00180 ihi,
00181 -1.0
00182 );
00183
00184 if (ytry <= y[ilo])
00185 {
00186
00187 ytry = tryMorphTet
00188 (
00189 allSurfaces,
00190 surfacesToTest,
00191 10*y[ihi],
00192 p,
00193 y,
00194 pSum,
00195 ihi,
00196 2.0
00197 );
00198 }
00199 else if (ytry >= y[inhi])
00200 {
00201
00202
00203 scalar ysave = y[ihi];
00204
00205 ytry = tryMorphTet
00206 (
00207 allSurfaces,
00208 surfacesToTest,
00209 10*y[ihi],
00210 p,
00211 y,
00212 pSum,
00213 ihi,
00214 0.5
00215 );
00216
00217 if (ytry >= ysave)
00218 {
00219
00220 forAll(p, i)
00221 {
00222 if (i != ilo)
00223 {
00224 p[i] = 0.5*(p[i] + p[ilo]);
00225 y[i] = sumDistSqr
00226 (
00227 allSurfaces,
00228 surfacesToTest,
00229 y[ihi],
00230 p[i]
00231 );
00232 }
00233 }
00234 pSum = sum(p);
00235 }
00236 }
00237 }
00238
00239 if (debug)
00240 {
00241 meshTools::writeOBJ(str(), p[0]);
00242 vertI++;
00243 str()<< "l " << vertI-1 << ' ' << vertI << nl;
00244 }
00245
00246
00247 label ilo = findMin(y);
00248 Swap(p[0], p[ilo]);
00249 Swap(y[0], y[ilo]);
00250 return false;
00251 }
00252
00253
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 void Foam::searchableSurfacesQueries::mergeHits
00320 (
00321 const point& start,
00322 const scalar mergeDist,
00323
00324 const label testI,
00325 const List<pointIndexHit>& surfHits,
00326
00327 labelList& allSurfaces,
00328 List<pointIndexHit>& allInfo,
00329 scalarList& allDistSqr
00330 )
00331 {
00332
00333 scalarList surfDistSqr(surfHits.size());
00334 forAll(surfHits, i)
00335 {
00336 surfDistSqr[i] = magSqr(surfHits[i].hitPoint()-start);
00337 }
00338
00339 forAll(surfDistSqr, i)
00340 {
00341 label index = findLower(allDistSqr, surfDistSqr[i]);
00342
00343
00344 if
00345 (
00346 index >= 0
00347 && (mag(allDistSqr[index]-surfDistSqr[i]) < mergeDist)
00348 )
00349 {
00350
00351
00352
00353
00354
00355 }
00356 else
00357 {
00358
00359 label next = index+1;
00360 if
00361 (
00362 next < allDistSqr.size()
00363 && (mag(allDistSqr[next]-surfDistSqr[i]) < mergeDist)
00364 )
00365 {
00366
00367
00368
00369
00370 }
00371 else
00372 {
00373
00374 label sz = allSurfaces.size();
00375 allSurfaces.setSize(sz+1);
00376 allInfo.setSize(allSurfaces.size());
00377 allDistSqr.setSize(allSurfaces.size());
00378
00379 for (label j = sz-1; j > index; --j)
00380 {
00381 allSurfaces[j+1] = allSurfaces[j];
00382 allInfo[j+1] = allInfo[j];
00383 allDistSqr[j+1] = allDistSqr[j];
00384 }
00385
00386 allSurfaces[index+1] = testI;
00387 allInfo[index+1] = surfHits[i];
00388 allDistSqr[index+1] = surfDistSqr[i];
00389 }
00390 }
00391 }
00392 }
00393
00394
00395
00396
00397
00398 void Foam::searchableSurfacesQueries::findAnyIntersection
00399 (
00400 const PtrList<searchableSurface>& allSurfaces,
00401 const labelList& surfacesToTest,
00402 const pointField& start,
00403 const pointField& end,
00404 labelList& hitSurfaces,
00405 List<pointIndexHit>& hitInfo
00406 )
00407 {
00408 hitSurfaces.setSize(start.size());
00409 hitSurfaces = -1;
00410 hitInfo.setSize(start.size());
00411
00412
00413 labelList hitMap(identity(start.size()));
00414 pointField p0(start);
00415 pointField p1(end);
00416 List<pointIndexHit> intersectInfo(start.size());
00417
00418 forAll(surfacesToTest, testI)
00419 {
00420
00421 allSurfaces[surfacesToTest[testI]].findLineAny(p0, p1, intersectInfo);
00422
00423
00424 label newI = 0;
00425 forAll(intersectInfo, i)
00426 {
00427 if (intersectInfo[i].hit())
00428 {
00429 hitInfo[hitMap[i]] = intersectInfo[i];
00430 hitSurfaces[hitMap[i]] = testI;
00431 }
00432 else
00433 {
00434 if (i != newI)
00435 {
00436 hitMap[newI] = hitMap[i];
00437 p0[newI] = p0[i];
00438 p1[newI] = p1[i];
00439 }
00440 newI++;
00441 }
00442 }
00443
00444
00445 if (newI == 0)
00446 {
00447 break;
00448 }
00449
00450
00451 hitMap.setSize(newI);
00452 p0.setSize(newI);
00453 p1.setSize(newI);
00454 intersectInfo.setSize(newI);
00455 }
00456 }
00457
00458
00459 void Foam::searchableSurfacesQueries::findAllIntersections
00460 (
00461 const PtrList<searchableSurface>& allSurfaces,
00462 const labelList& surfacesToTest,
00463 const pointField& start,
00464 const pointField& end,
00465 labelListList& hitSurfaces,
00466 List<List<pointIndexHit> >& hitInfo
00467 )
00468 {
00469
00470
00471
00472
00473
00474
00475
00476 hitSurfaces.setSize(start.size());
00477 hitInfo.setSize(start.size());
00478
00479 if (surfacesToTest.empty())
00480 {
00481 return;
00482 }
00483
00484
00485 allSurfaces[surfacesToTest[0]].findLineAll(start, end, hitInfo);
00486
00487
00488 List<scalarList> hitDistSqr(hitInfo.size());
00489 forAll(hitInfo, pointI)
00490 {
00491 const List<pointIndexHit>& pHits = hitInfo[pointI];
00492
00493 labelList& pSurfaces = hitSurfaces[pointI];
00494 pSurfaces.setSize(pHits.size());
00495 pSurfaces = 0;
00496
00497 scalarList& pDistSqr = hitDistSqr[pointI];
00498 pDistSqr.setSize(pHits.size());
00499 forAll(pHits, i)
00500 {
00501 pDistSqr[i] = magSqr(pHits[i].hitPoint() - start[pointI]);
00502 }
00503 }
00504
00505
00506 if (surfacesToTest.size() > 1)
00507 {
00508
00509
00510
00511
00512 const vectorField smallVec
00513 (
00514 1E2*SMALL*(end-start)
00515 + vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
00516 );
00517
00518
00519
00520
00521 const scalarField mergeDist(2*mag(smallVec)*mag(end-start));
00522
00523
00524 for (label testI = 1; testI < surfacesToTest.size(); testI++)
00525 {
00526 List<List<pointIndexHit> > surfHits;
00527 allSurfaces[surfacesToTest[testI]].findLineAll
00528 (
00529 start,
00530 end,
00531 surfHits
00532 );
00533
00534 forAll(surfHits, pointI)
00535 {
00536 mergeHits
00537 (
00538 start[pointI],
00539 mergeDist[pointI],
00540
00541 testI,
00542 surfHits[pointI],
00543
00544 hitSurfaces[pointI],
00545 hitInfo[pointI],
00546 hitDistSqr[pointI]
00547 );
00548 }
00549 }
00550 }
00551 }
00552
00553
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 void Foam::searchableSurfacesQueries::findNearest
00645 (
00646 const PtrList<searchableSurface>& allSurfaces,
00647 const labelList& surfacesToTest,
00648 const pointField& samples,
00649 const scalarField& nearestDistSqr,
00650 labelList& nearestSurfaces,
00651 List<pointIndexHit>& nearestInfo
00652 )
00653 {
00654
00655 nearestSurfaces.setSize(samples.size());
00656 nearestSurfaces = -1;
00657 nearestInfo.setSize(samples.size());
00658
00659
00660 scalarField minDistSqr(nearestDistSqr);
00661 List<pointIndexHit> hitInfo(samples.size());
00662
00663 forAll(surfacesToTest, testI)
00664 {
00665 allSurfaces[surfacesToTest[testI]].findNearest
00666 (
00667 samples,
00668 minDistSqr,
00669 hitInfo
00670 );
00671
00672
00673 forAll(hitInfo, pointI)
00674 {
00675 if (hitInfo[pointI].hit())
00676 {
00677 minDistSqr[pointI] = magSqr
00678 (
00679 hitInfo[pointI].hitPoint()
00680 - samples[pointI]
00681 );
00682 nearestInfo[pointI] = hitInfo[pointI];
00683 nearestSurfaces[pointI] = testI;
00684 }
00685 }
00686 }
00687 }
00688
00689
00690
00691 Foam::pointIndexHit Foam::searchableSurfacesQueries::facesIntersection
00692 (
00693 const PtrList<searchableSurface>& allSurfaces,
00694 const labelList& surfacesToTest,
00695 const scalar initDistSqr,
00696 const scalar convergenceDistSqr,
00697 const point& start
00698 )
00699 {
00700
00701
00702 List<point> nearest(surfacesToTest.size()+1);
00703
00704 point sumNearest = vector::zero;
00705
00706 forAll(surfacesToTest, i)
00707 {
00708 pointIndexHit hit
00709 (
00710 tempFindNearest(allSurfaces[surfacesToTest[i]], start, initDistSqr)
00711 );
00712
00713 if (hit.hit())
00714 {
00715 nearest[i] = hit.hitPoint();
00716 sumNearest += nearest[i];
00717 }
00718 else
00719 {
00720 FatalErrorIn
00721 (
00722 "searchableSurfacesQueries::facesIntersection"
00723 "(const labelList&, const scalar, const scalar, const point&)"
00724 ) << "Did not find point within distance "
00725 << initDistSqr << " of starting point " << start
00726 << " on surface "
00727 << allSurfaces[surfacesToTest[i]].IOobject::name()
00728 << abort(FatalError);
00729 }
00730 }
00731
00732 nearest[nearest.size()-1] = sumNearest / surfacesToTest.size();
00733
00734
00735
00736 List<scalar> nearestDist(nearest.size());
00737
00738 forAll(nearestDist, i)
00739 {
00740 nearestDist[i] = sumDistSqr
00741 (
00742 allSurfaces,
00743 surfacesToTest,
00744 initDistSqr,
00745 nearest[i]
00746 );
00747 }
00748
00749
00750
00751
00752 bool converged = morphTet
00753 (
00754 allSurfaces,
00755 surfacesToTest,
00756 initDistSqr,
00757 convergenceDistSqr,
00758 2000,
00759 nearest,
00760 nearestDist
00761 );
00762
00763
00764 pointIndexHit intersection;
00765
00766 if (converged)
00767 {
00768
00769 intersection = tempFindNearest
00770 (
00771 allSurfaces[surfacesToTest[0]],
00772 nearest[0],
00773 nearestDist[0]
00774 );
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 return intersection;
00812 }
00813
00814
00815
00816