54 "Missing error message. This is a bug, please report it",
55 "Node count was different to number of present nodes",
56 "Element count was less than number of present elements",
57 "Mesh loaded, but failed to pass sanity checks" 73 while(matchLength !=n)
75 if(b[matchLength] !=a[(n+offset-matchLength)%n])
100 bool rotateMatch(
const unsigned int *a,
const unsigned int *b,
size_t n,
bool directionForwards=
true)
102 size_t matchLength=0;
109 unsigned int sign,delta;
110 if(directionForwards)
121 while(matchLength !=n)
123 if(b[matchLength] !=a[(delta+offset+sign*matchLength)%n])
159 size_t curMax=v.begin()->first;
161 for(
size_t ui=0;ui<v.size();ui++)
163 if(v[ui].first > curMax && v[ui].first <=value)
179 det = a[0][0] * a[1][1] - a[1][0] * a[0][1];
185 for (j1=0; j1<n; j1++) {
186 float **m =
new float*[n-1];
187 for (i=0; i<n-1; i++)
188 m[i] =
new float[n-1];
189 for (i=1; i<n; i++) {
191 for (j=0; j<n; j++) {
194 m[i-1][j2] = a[i][j];
199 for (i=0; i<n-1; i++)
215 rows =
new float*[4];
217 for(
unsigned int ui=0;ui<4;ui++)
218 rows[ui] =
new float[4];
220 for(
unsigned int ui=0;ui<3;ui++)
228 for(
unsigned int ui=0;ui<4;ui++)
235 for(
unsigned int ui=0;ui<4;ui++)
249 unsigned int edgeIdx(
unsigned int i,
unsigned int j)
294 if (n.
sqrMag() < (std::numeric_limits<float>::epsilon()) )
299 dir = rayEnd - rayStart;
305 rv1 = rayStart - tri[0];
306 rv2 = rayEnd - tri[0];
313 else if(rv1.
dotProd(n) < std::numeric_limits<float>::epsilon() &&
314 rv2.
dotProd(n) < std::numeric_limits<float>::epsilon())
333 float uu, uv, vv, wu, wv, D;
340 D = uv * uv - uu * vv;
344 s = (uv * wv - vv * wu) / D;
345 if (s < 0.0 || s > 1.0)
347 t = (uv * wu - uu * wv) / D;
348 if (t < 0.0 || (s + t) > 1.0)
366 vector<std::pair<
size_t,vector<size_t> > > &clusterList)
368 ASSERT(!clusterList.size());
371 marked.resize(ptVec.size(),
false);
373 for(
size_t ui=0;ui<ptVec.size();ui++)
375 vector<size_t> curClustered;
378 for(
size_t uj=0;uj<ptVec.size();uj++)
380 if(ui==uj|| marked[uj])
383 if(ptVec[ui].sqrDist(ptVec[uj]) < tolerance)
385 curClustered.push_back(uj);
393 if(curClustered.size())
396 clusterList.push_back(std::make_pair(ui,curClustered));
397 curClustered.clear();
405 std::list<std::pair<
size_t,vector<size_t> > > &clusterList)
407 ASSERT(clusterList.empty());
410 marked.resize(ptVec.size(),
false);
412 for(
size_t ui=0;ui<ptVec.size();ui++)
414 vector<size_t> curClustered;
417 for(
size_t uj=ui+1;uj<ptVec.size();uj++)
422 if(ptVec[ui].sqrDist(ptVec[uj]) < tolerance)
424 curClustered.push_back(uj);
432 if(curClustered.size())
435 clusterList.push_back(std::make_pair(ui,curClustered));
436 curClustered.clear();
447 o <<
" Node count :" <<
nodes.size() << endl;
448 o <<
" Point count :" <<
points.size() << endl;
449 o <<
" Line count :" <<
tetrahedra.size() << endl;
450 o <<
" Triangle count :" <<
triangles.size() << endl;
451 o <<
" Tetrahedra count :" <<
tetrahedra.size() << endl;
456 o <<
"Bounding box:" << endl;
461 for(
size_t ui=0;ui<
nodes.size();ui++)
464 centroid*=1.0/(float)
nodes.size();
466 o <<
"Centroid:" << endl;
467 o << centroid << endl;
473 ASSERT(std::is_sorted(orphans.begin(),orphans.end()));
475 ASSERT(std::adjacent_find(orphans.begin(),orphans.end()) == orphans.end())
480 vector<size_t> offsets;
481 offsets.resize(
nodes.size());
483 for(
size_t ui=0;ui<
nodes.size();ui++)
485 while(curOrphan < orphans.size() &&
486 orphans[curOrphan] <=ui)
488 offsets[ui]=curOrphan;
492 vector<size_t>::iterator itJ;
493 for(
size_t ui=0;ui<
points.size();ui++)
497 for(
size_t ui=0;ui<
lines.size();ui++)
498 for(
size_t uj=0;uj<2;uj++)
502 for(
size_t ui=0;ui<
triangles.size();ui++)
504 for(
size_t uj=0;uj<3;uj++)
514 for(
size_t uj=0;uj<4;uj++)
519 vector<Point3D> newNodes;
520 for(
size_t ui=0;ui<
nodes.size();ui++)
522 if(!binary_search(orphans.begin(),orphans.end(),ui))
523 newNodes.push_back(
nodes[ui]);
525 nodes.swap(newNodes);
534 bool Mesh::sameTriangle(
unsigned int ui,
unsigned int uj)
const 536 vector<unsigned int> t1,t2;
540 for(
unsigned int idx=0;idx<3;idx++)
546 std::sort(t1.begin(),t1.end());
547 std::sort(t2.begin(),t2.end());
549 return std::equal(t1.begin(),t1.end(),t2.begin());
555 vector<unsigned int> ta,tb;
559 for(
unsigned int idx=0;idx<3;idx++)
565 std::sort(ta.begin(),ta.end());
566 std::sort(tb.begin(),tb.end());
568 return std::equal(ta.begin(),ta.end(),tb.begin());
578 for(
unsigned int uj=0;uj<4; uj++)
580 for(
unsigned int uk=0;uk<4;uk++)
588 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
597 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
604 for(
size_t ui=0;ui<
triangles.size();ui++)
607 for(
unsigned int uj=0;uj<3; uj++)
609 for(
unsigned int uk=0;uk<3;uk++)
618 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
619 outStr <<
"vertex " << uj <<
" and " << uk
620 <<
" of triangle " << ui <<
"not unique" << endl;
621 outStr <<
triangles[ui].p[uj] <<
" node is duplicated" << std::endl;
631 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
638 for(
size_t ui=0;ui<
lines.size();ui++)
641 for(
unsigned int uj=0;uj<2; uj++)
643 for(
unsigned int uk=0;uk<2;uk++)
651 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
660 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
672 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
678 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
684 outStr <<
"It's INSANE. " << __LINE__ << std::endl;
699 vector<list<unsigned int> > vl;
700 vl.resize(
nodes.size());
702 for(
unsigned int ui=0;ui<
triangles.size();ui++)
704 for(
unsigned int uj=0;uj<3;uj++)
708 for(
unsigned int ui=0;ui<vl.size();ui++)
710 for(list<unsigned int>::iterator it=vl[ui].begin();
711 it!=vl[ui].end();++it)
715 for(list<unsigned int>::iterator itJ=it;
716 itJ!=vl[ui].end();++itJ)
721 if(sameTriangle(*it,*itJ))
723 if(std::find(dups.begin(),dups.end(),*itJ) == dups.end())
724 dups.push_back(*itJ);
731 for(
unsigned int ui=dups.size();ui--;)
742 vector<size_t> thisDup;
743 vector<pair<size_t,vector<size_t> > > dups;
748 for(
size_t ui=0;ui<dups.size();ui++)
750 std::sort(dups[ui].second.begin(),
751 dups[ui].second.end());
754 for(vector<pair<
size_t,vector<size_t> > >::iterator it=dups.begin();
758 vector<size_t>::iterator itJ;
760 for(
size_t ui=0;ui<
points.size();ui++)
762 itJ=find(it->second.begin(),it->second.end(),
points[ui]);
763 if(itJ !=it->second.end())
768 for(
size_t ui=0;ui<
lines.size();ui++)
770 for(
size_t uj=0;uj<2;uj++)
772 itJ=find(it->second.begin(),it->second.end(),
lines[ui].p[uj]);
773 if(itJ !=it->second.end())
774 lines[ui].p[uj]=it->first;
779 for(
size_t ui=0;ui<
triangles.size();ui++)
781 for(
size_t uj=0;uj<3;uj++)
783 itJ=find(it->second.begin(),it->second.end(),
triangles[ui].p[uj]);
784 if(itJ !=it->second.end())
792 for(
size_t uj=0;uj<4;uj++)
794 itJ=find(it->second.begin(),it->second.end(),
tetrahedra[ui].p[uj]);
795 if(itJ !=it->second.end())
804 vector<size_t> toRemove;
805 for(vector<pair<
size_t,vector<size_t> > >::iterator it=dups.begin();
808 for(
size_t ui=0;ui<it->second.size();ui++)
809 toRemove.push_back(it->second[ui]);
812 std::sort(toRemove.begin(),toRemove.end());
822 vector<bool> referenced(
nodes.size(),
false);
823 for(
size_t ui=0;ui<
points.size();ui++)
824 referenced[
points[ui]] =
true;
826 for(
size_t ui=0;ui<
lines.size();ui++)
827 for(
size_t uj=0;uj<2;uj++)
828 referenced[
lines[ui].p[uj]] =
true;
830 for(
size_t ui=0;ui<
triangles.size();ui++)
831 for(
size_t uj=0;uj<3;uj++)
835 for(
size_t uj=0;uj<4;uj++)
838 vector<size_t> orphans;
840 for(
size_t ui=0;ui<referenced.size();ui++)
844 orphans.push_back(ui);
860 nodes.resize(newsize);
876 vector<list<unsigned int> > vl;
877 vl.resize(
nodes.size());
879 for(
unsigned int ui=0;ui<
triangles.size();ui++)
881 for(
unsigned int uj=0;uj<3;uj++)
885 for(
unsigned int ui=0;ui<vl.size();ui++)
887 for(list<unsigned int>::iterator it=vl[ui].begin();
888 it!=vl[ui].end();++it)
892 for(list<unsigned int>::iterator itJ=it;
893 itJ!=vl[ui].end();++itJ)
898 if(sameTriangle(*it,*itJ))
900 if(std::find(dups.begin(),dups.end(),*itJ) == dups.end())
901 dups.push_back(*itJ);
914 sqrTol = tolerance*tolerance;
917 unsigned int numDups=0;
920 #pragma omp parallel for reduction(+:numDups) 921 for(
size_t ui=0;ui<
nodes.size();ui++)
923 for(
size_t uj=0;uj<
nodes.size();uj++)
947 const std::vector<float> &ptsY,
const std::vector<float> &ptsZ)
950 ASSERT(ptsX.size() == ptsY.size() && ptsY.size() == ptsZ.size());
951 ASSERT(ptsX.size() %3 == 0);
956 vector<Point3D> ptVec;
957 ptVec.resize(ptsX.size());
958 #pragma omp parallel for 959 for(
size_t ui=0;ui<ptsX.size();ui++)
960 ptVec[ui]=
Point3D(ptsX[ui],ptsY[ui],ptsZ[ui]);
963 const float MAX_SQR_RAD=0.001f;
964 std::list<std::pair<size_t,vector<size_t> > > clusterList;
972 vector<size_t > triangleMapping;
974 triangleMapping.resize(ptVec.size());
975 #pragma omp parallel for 976 for(
size_t ui=0;ui<ptVec.size(); ui++)
977 triangleMapping[ui]=ui;
981 for(std::list<std::pair<
size_t, vector<size_t> > >::iterator it=clusterList.begin();it!=clusterList.end();++it)
983 for(
size_t uj=0;uj<it->second.size();uj++)
984 triangleMapping[it->second[uj]]=it->first;
993 vector<size_t> refCount;
994 refCount.resize(ptVec.size(),0);
995 for(
size_t ui=0;ui<triangleMapping.size();ui++)
996 refCount[triangleMapping[ui]]++;
1000 vector<size_t> numPtsDropped;
1001 for(
size_t ui=0;ui<refCount.size();ui++)
1003 numPtsDropped.push_back(delta);
1009 nodes.push_back(ptVec[ui]);
1014 for(
size_t ui=0;ui<triangleMapping.size()/3; ui++)
1018 for(
size_t uj=0;uj<3;uj++)
1024 t.
p[0]=triangleMapping[offset]-numPtsDropped[triangleMapping[offset]] ;
1025 t.
p[1]=triangleMapping[offset+1] - numPtsDropped[triangleMapping[offset+1]];
1026 t.
p[2]=triangleMapping[offset+2]- numPtsDropped[triangleMapping[offset+2]];
1031 std::cerr <<
"Input size of " << ptVec.size() << std::endl;
1032 std::cerr <<
"found " << clusterList.size() <<
" shared nodes" << std::endl;
1036 std::cerr <<
"Appears to be sane?? " << std::endl;
1042 vector<string> strVec;
1051 std::ifstream f(meshFile);
1066 if(line !=
"$MeshFormat")
1077 if(strVec.size() != 3)
1081 if(!(strVec[0] ==
"2.1" || strVec[0] ==
"2" || strVec[0] ==
"2.2"))
1086 if(strVec[1] !=
"0")
1093 if(line !=
"$EndMeshFormat")
1103 if(line !=
"$Nodes")
1111 unsigned int nodeCount;
1115 std::cerr <<
"reading node coords " << std::endl;
1125 if(line ==
"$EndNodes")
1130 if(strVec.size() < 4)
1144 nodes.push_back(pt);
1157 if(line !=
"$Elements")
1170 std::cerr <<
"Reading Element data" << std::endl;
1180 if(line ==
"$EndElements")
1185 if(strVec.size() < 3)
1188 unsigned int numTags,elemType;
1199 if(strVec.size() - numTags < 4)
1210 if(strVec.size()-numTags < 5)
1222 if( l.
p[0] == l.
p[1])
1227 std::cerr <<
"WARNING: Bad mesh line element at file line " << curLine << std::endl;
1240 if(strVec.size()-numTags < 6)
1253 if( t.
p[0] == t.
p[1] || t.
p[1] == t.
p[2] ||
1259 std::cerr <<
"WARNING: Bad mesh triangle at line " << curLine << std::endl;
1276 if(strVec.size()-numTags < 7)
1291 for(
unsigned int ui=0;ui<4; ui++)
1293 for(
unsigned int uj=0;uj<4;uj++)
1298 if( t.
p[ui] == t.
p[uj])
1302 std::cerr <<
"WARNING: Bad mesh tetrahedron at line " << curLine << std::endl;
1340 if(nodeCount !=
nodes.size())
1352 vector<size_t> touchedNodes;
1354 touchedNodes.resize(
triangles.size()*3);
1356 #pragma omp parallel for 1357 for(
size_t ui=0;ui<
triangles.size(); ui++)
1360 touchedNodes[ui*3+1]=
triangles[ui].p[1];
1361 touchedNodes[ui*3+2]=
triangles[ui].p[2];
1365 vector<size_t>::iterator it;
1366 std::sort(touchedNodes.begin(),touchedNodes.end());
1367 it=std::unique(touchedNodes.begin(),touchedNodes.end());
1370 touchedNodes.resize(it-touchedNodes.begin());
1372 return touchedNodes.size();
1377 #pragma omp parallel for 1381 #pragma omp parallel for 1382 for(
size_t ui=0;ui<
triangles.size();ui++)
1385 #pragma omp parallel for 1386 for(
size_t ui=0;ui<
lines.size();ui++)
1387 lines[ui].physGroup = newPhys;
1395 using std::ofstream;
1397 ofstream f(meshFile);
1402 f <<
"$MeshFormat" << endl;
1403 f <<
"2.1 0 8" << endl;
1404 f <<
"$EndMeshFormat" << endl;
1407 f <<
"$Nodes" << endl;
1409 f <<
nodes.size() << endl;
1411 for(
size_t ui=0;ui<
nodes.size();ui++)
1413 f << ui+1 <<
" " <<
nodes[ui][0] <<
" " <<
nodes[ui][1]
1414 <<
" " <<
nodes[ui][2] << std::endl;
1417 f <<
"$EndNodes" << endl;
1419 f <<
"$Elements" << endl;
1429 for(
size_t ui=0;ui<
triangles.size();ui++)
1436 for(
size_t ui=0;ui<
lines.size();ui++)
1439 lines[ui].p[0]+1 <<
" " <<
lines[ui].p[1]+1 << endl;
1442 for(
size_t ui=0;ui<
points.size();ui++)
1447 f <<
"$EndElements" << endl;
1462 #pragma omp parallel shared(nodes,qR) 1466 for(
size_t ui=0; ui<
nodes.size();ui++)
1474 for(
unsigned int ui=0;ui<
nodes.size();ui++)
1488 for(
size_t ui=0; ui<
nodes.size();ui++)
1499 for(
size_t ui=0;ui<
nodes.size();ui++)
1502 origin*=1.0f/(float)
nodes.size();
1509 #pragma omp parallel for 1510 for(
size_t ui=0;ui<
nodes.size();ui++)
1516 #pragma omp parallel for 1517 for(
size_t ui=0;ui<
nodes.size();ui++)
1519 nodes[ui][0]=(
nodes[ui][0]-origin[0])*scaleFactor + origin[0];
1520 nodes[ui][1]=(
nodes[ui][1]-origin[1])*scaleFactor + origin[1];
1521 nodes[ui][2]=(
nodes[ui][2]-origin[2])*scaleFactor + origin[2];
1527 #pragma omp parallel for 1528 for(
size_t ui=0;ui<
nodes.size();ui++)
1529 nodes[ui]*=scaleFactor;
1537 void Mesh::getTriEdgeAdjacencyMap(std::vector<std::list<size_t> > &adj)
const 1545 vector<list<size_t> > triLookup;
1546 triLookup.resize(
nodes.size());
1547 for(
size_t ui=0; ui<
triangles.size();ui++)
1549 for(
unsigned int uj=0;uj<3;uj++)
1550 triLookup[
triangles[ui].p[uj]].push_back(ui);
1555 list<size_t> connectedMap;
1556 for(
size_t ui=0; ui<
triangles.size();ui++)
1559 for(
unsigned int uj=0;uj<3;uj++)
1566 ASSERT(triLookup[v1].size());
1567 ASSERT(triLookup[v2].size());
1570 list<size_t> intersect;
1571 intersect=triLookup[v1];
1572 for(list<size_t>::iterator it=intersect.begin();it!=intersect.end();)
1574 if( find(triLookup[v2].begin(),triLookup[v2].end(),*it) == triLookup[v2].end())
1576 it=intersect.erase(it);
1584 for(list<size_t>::iterator it=intersect.begin();it!=intersect.end();++it)
1588 adj[ui].push_back(*it);
1598 const vector<size_t> &physGroupsToSplit)
1602 unsigned int origStart=newPhysGroupStart;
1604 vector<list<size_t> > adjacencyMap;
1605 vector<bool> touchedTris;
1606 vector<size_t> boundaryTris;
1607 getTriEdgeAdjacencyMap(adjacencyMap);
1608 touchedTris.resize(adjacencyMap.size(),
false);
1624 for(
size_t ui=0;ui<adjacencyMap.size();ui++)
1626 ASSERT(adjacencyMap[ui].size());
1629 if(find(physGroupsToSplit.begin(),physGroupsToSplit.end(),
1630 triangles[ui].physGroup) == physGroupsToSplit.end())
1633 adjacencyMap[ui].clear();
1634 touchedTris[ui]=
true;
1639 for(list<size_t>::iterator it=adjacencyMap[ui].begin(); it!=adjacencyMap[ui].end(); ++it)
1641 if(find(physGroupsToSplit.begin(),physGroupsToSplit.end(),
1642 triangles[*it].physGroup) == physGroupsToSplit.end())
1644 it=adjacencyMap[ui].erase(it);
1663 curTri= find(touchedTris.begin(),touchedTris.end(),
false) - touchedTris.begin();
1667 if(curTri == touchedTris.size())
1674 list<size_t> boundary,moreBoundary;
1676 boundary.push_back(curTri);
1678 std::cerr <<
"Seeded with triangle # " << curTri << std::endl;
1679 touchedTris[curTri]=
true;
1680 triangles[curTri].physGroup=newPhysGroupStart;
1687 for(list<size_t>::iterator bIt=boundary.begin();bIt!=boundary.end();++bIt)
1689 ASSERT(adjacencyMap[*bIt].size());
1691 for(list<size_t>::iterator it=adjacencyMap[*bIt].begin();it!=adjacencyMap[*bIt].end();++it)
1693 if(!touchedTris[*it] &&
1694 (normalAngle(*bIt,*it) < divisionAngle || fabs(normalAngle(*bIt,*it,
true)) < divisionAngle) )
1699 moreBoundary.push_back(*it);
1700 touchedTris[*it]=
true;
1701 triangles[*it].physGroup=newPhysGroupStart;
1707 debugBounds.
expand(dbgTmp);
1715 boundary.swap(moreBoundary);
1717 moreBoundary.clear();
1720 while(!boundary.empty());
1724 std::cerr <<
"Group size: "<< groupSize << std::endl;
1725 std::cerr << debugBounds << std::endl;
1728 newPhysGroupStart++;
1734 return newPhysGroupStart-origStart+1;
1739 float Mesh::normalAngle(
size_t t1,
size_t t2,
bool flip)
const 1748 return nA.
angle(-nB);
1750 return nA.
angle(nB);
1764 for(
size_t ui=0;ui<
nodes.size();ui++)
1773 std::vector<size_t> &lineRes,
1774 std::vector<size_t> &triangleRes,
1775 std::vector<size_t> &tetrahedraRes )
const 1778 std::sort(searchNodes.begin(),searchNodes.end());
1781 ASSERT(lineRes.size() == triangleRes.size() && tetrahedraRes.size() == lineRes.size() &&
1782 !tetrahedraRes.size());
1783 for(
size_t ui=0;ui<
lines.size();ui++)
1786 for(
size_t uj=0;uj<2;uj++)
1788 searchFound=std::binary_search(searchNodes.begin(),searchNodes.end(),
lines[ui].p[uj]);
1794 lineRes.push_back(ui);
1797 for(
size_t ui=0;ui<
triangles.size();ui++)
1800 for(
size_t uj=0;uj<3;uj++)
1802 searchFound=std::binary_search(searchNodes.begin(),searchNodes.end(),
triangles[ui].p[uj]);
1808 triangleRes.push_back(ui);
1815 for(
size_t uj=0;uj<4;uj++)
1817 searchFound=std::binary_search(searchNodes.begin(),searchNodes.end(),
tetrahedra[ui].p[uj]);
1823 tetrahedraRes.push_back(ui);
1835 for(
unsigned int ui=0;ui<
triangles.size();ui++)
1838 for(
unsigned int uj=0;uj<curPhys.size();uj++)
1840 if(curPhys[uj].first==
triangles[ui].physGroup)
1843 curPhys[uj].second++;
1851 curPhys.push_back(make_pair(
triangles[ui].physGroup,1));
1852 std::sort(curPhys.begin(),curPhys.end(),cmp);
1857 for(
unsigned int ui=0;ui<
tetrahedra.size();ui++)
1860 for(
unsigned int uj=0;uj<curPhys.size();uj++)
1862 if(curPhys[uj].first==
tetrahedra[ui].physGroup)
1865 curPhys[uj].second++;
1873 curPhys.push_back(make_pair(
tetrahedra[ui].physGroup,1));
1874 std::sort(curPhys.begin(),curPhys.end(),cmp);
1882 std::cerr <<
"Erasing..." << typeMask << std::endl;
1883 unsigned int eraseCount;
1888 for(
size_t ui=
triangles.size()-1;ui!=0; ui--)
1897 std::cerr <<
"Erasing " << eraseCount << std::endl;
1906 for(
size_t ui=
tetrahedra.size()-1;ui!=0; ui--)
1923 for(
size_t ui=
tetrahedra.size()-1;ui!=0; ui++)
1956 for(
size_t ui=0;ui<
triangles.size();ui++)
1962 for(
size_t uj=0;uj<3;uj++)
1973 std::cerr <<
"Signed volume :" << vol << std::endl;
1990 vector<bool> &meshResults,
unsigned int &prog)
const 1998 for(
size_t ui=0;ui<
triangles.size();ui++)
2006 centre=centre*1.0/(3.0f*(float)
triangles.size());
2011 float maxSqrDistance;
2016 #pragma omp parallel for reduction(max:maxSqrDistance) 2017 for(
size_t ui=0;ui<
triangles.size();ui++)
2019 maxSqrDistance=std::max(maxSqrDistance,
2021 maxSqrDistance=std::max(maxSqrDistance,
2023 maxSqrDistance=std::max(maxSqrDistance,
2031 outsideMesh[0] = centre +
Point3D(0,0,1.1)*maxSqrDistance;
2032 outsideMesh[1] = centre -
Point3D(3,1,1.1)*maxSqrDistance;
2033 meshResults.resize(p.size(),
false);
2038 size_t actualProg=0;
2039 size_t reportedProg=0;
2043 #pragma omp parallel for firstprivate(progReduce) 2044 for(
unsigned int ui=0;ui<p.size();ui++)
2050 sqrDist=p[ui].sqrDist(centre);
2051 if(sqrDist <= maxSqrDistance &&
2057 unsigned int intersectionCount;
2058 intersectionCount=0;
2062 if(p[ui].sqrDist(outsideMesh[0])<
2063 p[ui].sqrDist(outsideMesh[1]))
2065 externPt=outsideMesh;
2066 rayBound.
setBounds(p[ui],outsideMesh[0]);
2070 externPt=outsideMesh+1;
2071 rayBound.
setBounds(p[ui],outsideMesh[1]);
2077 for(
size_t uj=0;uj<
triangles.size();uj++)
2086 unsigned int intersectType;
2088 p[ui],triangle,dummy);
2089 if(intersectType == 1)
2090 intersectionCount++;
2094 meshResults[ui]=intersectionCount%2;
2100 if(!omp_get_thread_num())
2104 prog= (
unsigned int)(((
float)curProg*100.0f)/(float)p.size());
2110 #pragma omp critical 2120 vector<bool> &meshResults)
const 2122 unsigned int dummyProg;
2129 size_t nearTri = (size_t)-1;
2130 float distance=std::numeric_limits<float>::max();
2131 for(
size_t ui=0;ui<
triangles.size();ui++)
2140 if(fabs(newDist) < distance)
2143 distance= fabs(newDist);
2144 signedDistance=newDist;
2159 vector<bool> seenTri;
2162 deque<size_t> triQueue;
2164 std::vector<std::list<size_t> > adjacency;
2165 getTriEdgeAdjacencyMap(adjacency);
2167 for(
size_t ui=0;ui<
triangles.size();ui++)
2172 triQueue.push_back(ui);
2177 while(triQueue.size())
2180 tri = triQueue.front();
2181 triQueue.pop_front();
2183 list<size_t> *curAdjT;
2184 curAdjT= &(adjacency[tri]);
2186 for(list<size_t>::const_iterator it=curAdjT->begin(); it !=curAdjT->end();++it)
2188 if(*it == tri || seenTri[*it])
2195 triQueue.push_back(*it);
2209 for(
size_t ui=0;ui<3;ui++)
2211 if ( p[ui] == p[(ui+1)%3])
2215 if(nMax != (
size_t) -1 && p[ui] > nMax )
2228 vector<size_t> commonV;
2229 for(
size_t ui=0;ui<3;ui++)
2231 for(
size_t uj=0;uj<3;uj++)
2233 if ( other.
p[uj] == p[ui])
2235 commonV.push_back(p[ui]);
2241 ASSERT(commonV.size() <=3);
2245 if(commonV.size() < 2)
2249 unsigned int pA[3],pB[3];
2251 for(
size_t ui=0;ui<3;ui++)
2254 if(std::find(commonV.begin(),commonV.end(),p[ui]) == commonV.end())
2260 if(std::find(commonV.begin(),commonV.end(),other.
p[ui]) == commonV.end())
2266 if (commonV.size() == 3)
2288 bool coherencyTests()
2329 bool nearestTriTest()
2365 TEST(coherencyTests(),
"Mesh coherency checks");
2366 TEST(nearestTriTest(),
"Mesh nearest tri");
bool containsPt(const Point3D &pt) const
Check to see if the point is contained in, or part of the walls of the cube.
std::vector< std::string > physGroupNames
Physical group storage.
void setInverseLimits()
Set the cube to be "inside out" at the limits of numeric results;.
void getTriNormal(size_t tri, Point3D &normal) const
float Determinant(float **a, int n)
bool isSane(bool output=false, std::ostream &outStream=std::cerr) const
Perform various sanity tests on mesh. Should return true if your mesh is sane.
float signedDistanceToFacet(const Point3D &fA, const Point3D &fB, const Point3D &fC, const Point3D &normal, const Point3D &p)
Find the distance between a point, and a triangular facet – may be positive or negative.
unsigned int saveGmshMesh(const char *meshfile) const
void resizeNodes(unsigned int newSize)
Resize the node vector.
bool isOrientedCoherently() const
Returns true if the mesh is coherently oriented.
Point3D crossProd(const Point3D &pt) const
Calculate the cross product of this and another point.
bool rotateMatch(const unsigned int *a, const unsigned int *b, size_t n, bool directionForwards=true)
unsigned int numDupVertices(float tolerance) const
obtain the number of duplicate vertices in the mesh
std::vector< TETRAHEDRON > tetrahedra
Storage for node connectivity in tetrahedral form.
int intersect_RayTriangle(const Point3D &rayStart, const Point3D &rayEnd, Point3D *tri, Point3D &I)
void getCurPhysGroups(std::vector< std::pair< unsigned int, size_t > > &curPhys) const
bool edgesMismatch(const TRIANGLE &tOther) const
float fourDeterminant(const Point3D &a, const Point3D &b, const Point3D &c, const Point3D &d)
const char * MESH_LOAD_ERRS[]
void reassignGroups(unsigned int i)
reassign the physical groups to a single number
void quat_get_rot_quat(const Point3f *rotVec, float angle, Quaternion *rotQuat)
Compute the quaternion for specified rotation.
std::vector< LINE > lines
Storage for line segments. .size()%2 should always==0.
Simple mesh class for storing and manipulating meshes consisting of 2 and 3D simplexes (triangles or ...
const unsigned int ELEM_FOUR_NODE_TETRAHEDRON
unsigned int divideMeshSurface(float divisionAngle, unsigned int newPhysGroupStart, const std::vector< size_t > &physGroupsToSplit)
Point3D getNodes(unsigned int index)
Retrieve an object.
const unsigned int ELEM_SINGLE_NODE_POINT
void killOrphanNodes()
Kill specified orphan nodes within this dataset.
void removeDuplicateTris()
Remove exact duplicate triangles.
float sqrMag() const
Returns magnitude^2, taking this as a position vector.
unsigned int loadGmshMesh(const char *meshfile, unsigned int &curLine, bool allowBadMeshes=true)
size_t getNearestTri(const Point3D &p, float &distance) const
Find the nearest triangle to a particular point.
const unsigned int ELEM_THREE_NODE_TRIANGLE
bool antiRotateMatch(const unsigned int *a, const unsigned int *b, size_t n)
void quat_rot_apply_quat(Point3f *point, const Quaternion *rotQuat)
Use previously generated quats from quat_get_rot_quats to rotate a point.
void rotate(const Point3D &axis, const Point3D &origin, float angle)
Rotate mesh.
void splitStrsRef(const char *cpStr, const char delim, std::vector< std::string > &v)
Split string references using a single delimiter.
A 3D point data class storage.
void getContainedNodes(const BoundCube &b, std::vector< size_t > &nodes) const
Return all the nodes that are contained within specified bounding box.
Data storage structure for points.
float signVal(unsigned int val)
void clear()
Clear the mesh.
std::vector< Point3D > nodes
Point storage for 3D Data (nodes/coords/vertices..)
const unsigned int ELEM_TWO_NODE_LINE
size_t findMaxLessThanOrEq(const vector< std::pair< size_t, size_t > > &v, size_t value)
float angle(const Point3D &pt) const
Calculate the angle between two position vectors in radians.
size_t elementCount() const
void scale(const Point3D &origin, float scaleFactor)
Scale the mesh around a specified origin.
Data storage structure for quaternions.
unsigned int edgeIdx(unsigned int i, unsigned int j)
const size_t PROGRESS_REDUCE
bool isSane(size_t pLimit=(size_t) -1) const
void translate()
Translate mesh around node centroid.
void print(std::ostream &o) const
Print some statistics about the mesh data.
Helper class to define a bounding cube.
void normalise()
Make point unit magnitude, maintaining direction.
void findNearVerticies(float tolerance, const vector< Point3D > &ptVec, vector< std::pair< size_t, vector< size_t > > > &clusterList)
void mergeDuplicateVertices(float tolerance)
void setTriangleMesh(const std::vector< float > &ptsA, const std::vector< float > &ptsB, const std::vector< float > &ptsC)
bool stream_cast(T1 &result, const T2 &obj)
Template function to cast and object to another by the stringstream.
void setNode(unsigned int index, Point3D node)
Set the nodes value.
std::vector< unsigned long long > points
points
float dotProd(const Point3D &pt) const
Calculate the dot product of this and another point.
void erasePhysGroup(unsigned int group, unsigned int typeMask)
void pointsInside(const std::vector< Point3D > &p, std::vector< bool > &meshResults, unsigned int &prog) const
Find the points that lie inside a this mesh.
std::vector< TRIANGLE > triangles
Storage for node connectivity in triangle form (take in groups of 3)
unsigned int numDupTris() const
Obtain the number of duplicate triangles in the mesh.
void getIntersectingPrimitives(std::vector< size_t > &searchNodes, std::vector< size_t > &lines, std::vector< size_t > &triangles, std::vector< size_t > &tetrahedra) const
Return all primitives that are WHOLLY contained withing bounding box.
void setBounds(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax)
Set the bounds by passing in minima and maxima of each dimension.
void getBounds(BoundCube &b) const
Get the Axis aligned bounding box for this mesh.
void expand(const BoundCube &b)
Expand (as needed) volume such that the argument bounding cube is enclosed by this one...
float getVolume() const
Obtain the volume of the triangulated space.
unsigned int countTriNodes() const
Count the number of unique nodes shared by triangles.