30#include "../Triangle/triangle.h"
45 m_Nodes.push_back(valueify<XYZ>(pNode->Attribute(
"value")));
52 m_Indices[iType].push_back(valueify<int>(pIndex->Attribute(
"value")));
59 vector<XYZ>::const_iterator itNode;
62 TiXmlElement Node(
"Node");
63 Node.SetAttribute(
"value",
stringify(*itNode));
64 Element.InsertEndChild(Node);
67 list<int>::const_iterator itIndex;
70 TiXmlElement Indices(
"Element");
71 Indices.SetAttribute(
"type", i);
74 TiXmlElement Index(
"Index");
75 Index.SetAttribute(
"value", *itIndex);
76 Indices.InsertEndChild(Index);
78 Element.InsertEndChild(Indices);
84 int iOffset = (int)
m_Nodes.size();
85 vector<XYZ>::const_iterator itNode;
86 for (itNode = Mesh.
m_Nodes.begin(); itNode != Mesh.
m_Nodes.end(); ++itNode)
88 m_Nodes.push_back(*itNode+Offset);
97 list<int>::const_iterator itIndex;
100 for (itIndex = Mesh.
m_Indices[i].begin(); itIndex != Mesh.
m_Indices[i].end(); ++itIndex)
102 m_Indices[i].push_back(*itIndex + iOffset);
110 list<int>::iterator itIndex;
115 if (*itIndex == iChangeFrom)
117 *itIndex = iChangeTo;
125 vector<int*>::iterator itIntPointer;
126 vector<int*> &ChangeFromPointers = References[iChangeFrom];
127 vector<int*> &ChangeToPointers = References[iChangeTo];
128 for (itIntPointer = ChangeFromPointers.begin(); itIntPointer != ChangeFromPointers.end(); ++itIntPointer)
130 **itIntPointer = iChangeTo;
131 ChangeToPointers.push_back(*itIntPointer);
133 ChangeFromPointers.clear();
141 list<int>::iterator itIter1, itIter2;
142 list<int>::iterator itTriStart1, itTriStart2;
145 for (itIter1 = TriangleIndices.begin(); itIter1 != TriangleIndices.end(); )
147 itTriStart1 = itIter1;
148 i1[0] = *(itIter1++);
149 i1[1] = *(itIter1++);
150 i1[2] = *(itIter1++);
151 for (itIter2 = itIter1; itIter2 != TriangleIndices.end(); )
153 itTriStart2 = itIter2;
154 i2[0] = *(itIter2++);
155 i2[1] = *(itIter2++);
156 i2[2] = *(itIter2++);
158 if (i1[0] == i2[0] && i1[1] == i2[2] && i1[2] == i2[1] ||
159 i1[0] == i2[1] && i1[1] == i2[0] && i1[2] == i2[2] ||
160 i1[0] == i2[2] && i1[1] == i2[1] && i1[2] == i2[0])
162 TriangleIndices.erase(itTriStart1, itIter1);
163 if (itIter1 == itTriStart2)
164 itIter1 = TriangleIndices.erase(itTriStart2, itIter2);
166 TriangleIndices.erase(itTriStart2, itIter2);
179 list<int>::iterator itIter1, itIter2;
180 list<int>::iterator itQuadStart1, itQuadStart2;
183 for (itIter1 = QuadIndices.begin(); itIter1 != QuadIndices.end(); )
185 itQuadStart1 = itIter1;
186 i1[0] = *(itIter1++);
187 i1[1] = *(itIter1++);
188 i1[2] = *(itIter1++);
189 i1[3] = *(itIter1++);
190 for (itIter2 = itIter1; itIter2 != QuadIndices.end(); )
192 itQuadStart2 = itIter2;
193 i2[0] = *(itIter2++);
194 i2[1] = *(itIter2++);
195 i2[2] = *(itIter2++);
196 i2[3] = *(itIter2++);
198 if (i1[0] == i2[0] && i1[1] == i2[3] && i1[2] == i2[2] && i1[3] == i2[1] ||
199 i1[0] == i2[1] && i1[1] == i2[0] && i1[2] == i2[3] && i1[3] == i2[2] ||
200 i1[0] == i2[2] && i1[1] == i2[1] && i1[2] == i2[0] && i1[3] == i2[3] ||
201 i1[0] == i2[3] && i1[1] == i2[2] && i1[2] == i2[1] && i1[3] == i2[0])
203 QuadIndices.erase(itQuadStart1, itIter1);
204 if (itIter1 == itQuadStart2)
205 itIter1 = QuadIndices.erase(itQuadStart2, itIter2);
207 QuadIndices.erase(itQuadStart2, itIter2);
217 list<int>::iterator itIter, itTriStart;
221 for (itIter = TriangleIndices.begin(); itIter != TriangleIndices.end(); )
227 if (i1 == i2 || i2 == i3 || i3 == i1)
229 itIter = TriangleIndices.erase(itTriStart, itIter);
236 list<int> &ElementIndices =
m_Indices[ElementType];
239 list<int>::iterator itIter1, itIter2;
240 list<int>::iterator itStart1, itStart2;
242 for (itIter1 = ElementIndices.begin(); itIter1 != ElementIndices.end(); )
248 Index1.push_back( *(itIter1++));
250 sort( Index1.begin(), Index1.end() );
251 for (itIter2 = itIter1; itIter2 != ElementIndices.end(); )
257 Index2.push_back( *(itIter2++));
259 sort( Index2.begin(), Index2.end() );
261 if ( equal( Index1.begin(), Index1.end(), Index2.begin() ) )
263 if (itIter1 == itStart2)
265 itIter1 = ElementIndices.erase(itStart2, itIter2);
269 itIter2 = ElementIndices.erase(itStart2, itIter2);
281 list<int>::iterator itIter1, itIter2;
282 list<int>::iterator itTriStart1, itTriStart2;
285 for (itIter1 = TriangleIndices.begin(); itIter1 != TriangleIndices.end(); )
287 itTriStart1 = itIter1;
288 i1[0] = *(itIter1++);
289 i1[1] = *(itIter1++);
290 i1[2] = *(itIter1++);
291 for (itIter2 = itIter1; itIter2 != TriangleIndices.end(); )
293 itTriStart2 = itIter2;
294 i2[0] = *(itIter2++);
295 i2[1] = *(itIter2++);
296 i2[2] = *(itIter2++);
298 if ( i1[0] == i2[0] && i1[1] == i2[1] && i1[2] == i2[2] )
301 if (itIter1 == itTriStart2)
303 itIter1 = TriangleIndices.erase(itTriStart2, itIter2);
307 itIter2 = TriangleIndices.erase(itTriStart2, itIter2);
317 list<int>::iterator itIter, itLineStart;
318 list<int>::iterator itCompare;
321 for (itIter = LineIndices.begin(); itIter != LineIndices.end(); )
323 itLineStart = itIter;
326 for (itCompare = itIter; itCompare != LineIndices.end(); )
330 if ((i1 == j1 && i2 == j2) ||
331 (i1 == j2 && i2 == j1))
333 itIter = LineIndices.erase(itLineStart, itIter);
344 vector<XYZ>::const_iterator itNode;
346 for (itNode =
m_Nodes.begin(), iNode=0; itNode !=
m_Nodes.end(); ++itNode, ++iNode)
350 AABB.first = AABB.second = *itNode;
354 AABB.first =
Min(AABB.first, *itNode);
355 AABB.second =
Max(AABB.second, *itNode);
371 AABB.first.x -= dGrowDistance;
372 AABB.first.y -= dGrowDistance;
373 AABB.first.z -= dGrowDistance;
374 AABB.second.x += dGrowDistance;
375 AABB.second.y += dGrowDistance;
376 AABB.second.z += dGrowDistance;
392 double dSize = AABB.second.x - AABB.first.x;
393 if (dSize < AABB.second.y - AABB.first.y)
394 dSize = AABB.second.y - AABB.first.y;
395 if (dSize < AABB.second.z - AABB.first.z)
396 dSize = AABB.second.z - AABB.first.z;
399 dSize = max(dSize, 1e-3);
403 XYZ Avg = 0.5*(AABB.second + AABB.first);
405 Octree<pair<int, XYZ> > Octree(Vector3f(
float(Avg.
x-0.5*dSize),
float(Avg.
y-0.5*dSize),
float(Avg.
z-0.5*dSize)), (
float)dSize, 10, 10);
411 vector<pair<int, XYZ> > NodesWithIndices;
412 NodesWithIndices.resize(
m_Nodes.size());
414 vector<XYZ>::iterator itNode;
416 for (itNode =
m_Nodes.begin(), iNode=0; itNode !=
m_Nodes.end(); ++itNode, ++iNode)
418 NodesWithIndices[iNode] = pair<int, XYZ>(iNode, *itNode);
419 Octree.insertItem(NodesWithIndices[iNode], Agent);
426 Octree.visit(Visitor);
465 vector<pair<int, int> > NodePairs;
466 vector<XYZ>::const_iterator itNode1;
467 vector<XYZ>::const_iterator itNode2;
469 double dTolSquared =
TOL*
TOL;
470 for (itNode1 =
m_Nodes.begin(), iNode1=0; itNode1 !=
m_Nodes.end(); ++itNode1, ++iNode1)
472 for (itNode2 =
m_Nodes.begin(), iNode2=0; itNode2 !=
m_Nodes.end(); ++itNode2, ++iNode2)
476 NodePairs.push_back(make_pair(iNode1, iNode2));
486 vector<XYZ>::const_iterator itNode1;
487 vector<XYZ>::const_iterator itNode2;
489 vector<XYZ> OffsetNodes;
490 for ( itNode2 =
m_Nodes.begin(); itNode2 !=
m_Nodes.end(); ++itNode2 )
492 OffsetNodes.push_back( *itNode2 - Vector );
495 bool bProgress =
m_Nodes.size() > 10000;
496 int iProgressInc =
m_Nodes.size()/10;
499 double dTolSquared =
TOL*
TOL;
501 for (itNode1 =
m_Nodes.begin(), iNode1=0; itNode1 !=
m_Nodes.end(); ++itNode1, ++iNode1)
503 if ( bProgress && !(iNode1 % iProgressInc) )
505 TGLOG(
"GetNodePairs " << iNode1/iProgressInc*10 <<
"% complete");
508 for ( iNode2 = iNode1; iNode2 < OffsetNodes.size(); ++ iNode2 )
512 NodePairs.push_back(make_pair(iNode1, iNode2));
519 for ( iNode2 = 0; iNode2 < iNode1; ++iNode2 )
523 NodePairs.push_back(make_pair(iNode1, iNode2));
534 vector<XYZ>::const_iterator itNode;
535 double dClosestDistSqrd = -1;
537 int iClosestNode = -1, i;
538 for (itNode =
m_Nodes.begin(), i=0; itNode !=
m_Nodes.end(); ++itNode, ++i)
541 if ( dDistSqrd < dClosestDistSqrd || dClosestDistSqrd == -1 )
543 dClosestDistSqrd = dDistSqrd;
552 vector<XYZ>::const_iterator itNode;
553 double dClosestDistSqrd = -1;
555 int iClosestNode = -1, i;
556 for (itNode =
m_Nodes.begin(), i=0; itNode !=
m_Nodes.end(); ++itNode, ++i)
559 if ( dDistSqrd < dClosestDistSqrd || dClosestDistSqrd == -1 )
561 dClosestDistSqrd = dDistSqrd;
562 if ( dClosestDistSqrd <= dTol )
611 list<int>::iterator itIter1, itIter2;
612 list<int>::iterator itTriStart1, itTriStart2;
613 vector<int>::iterator iti1;
616 for (itIter1 = TriangleIndices.begin(); itIter1 != TriangleIndices.end(); )
618 itTriStart1 = itIter1;
620 i1.push_back(*(itIter1++));
621 i1.push_back(*(itIter1++));
622 i1.push_back(*(itIter1++));
623 for ( itIter2 = itIter1; itIter2 != TriangleIndices.end(); )
625 itTriStart2 = itIter2;
627 i2[0] = *(itIter2++);
628 RemInd.push_back(i2[0]);
629 i2[1] = *(itIter2++);
630 RemInd.push_back(i2[1]);
631 i2[2] = *(itIter2++);
632 RemInd.push_back(i2[2]);
633 vector<int> CommonInd;
636 for ( iti1 = i1.begin(), i = 0; iti1 != i1.end(); iti1++, ++i )
639 for (
int j = 0; j < iNumNodes; ++j )
641 if ( *iti1 == i2[j] )
643 CommonInd.push_back(i);
644 RemInd.remove(i2[j]);
649 if ( CommonInd.size() == 2 )
664 if ( Normal1 == Normal2 || Normal1 == -Normal2 )
666 if ( CommonInd[0] == 0 && CommonInd[1] == 2 )
667 i1.push_back( *(RemInd.begin()) );
669 i1.insert( i1.begin()+CommonInd[1],*(RemInd.begin()));
671 if ( itIter1 == itTriStart2 )
672 itIter1 = TriangleIndices.erase( itTriStart1, itIter2 );
675 TriangleIndices.erase( itTriStart2, itIter2 );
676 itIter1 = TriangleIndices.erase( itTriStart1, itIter1 );
691 set<int> UnreferencedNodes;
693 for (i=0; i<(int)
m_Nodes.size(); ++i)
695 UnreferencedNodes.insert(i);
698 list<int>::iterator itIndex;
704 UnreferencedNodes.erase(*itIndex);
730 vector<int> NewIndices;
731 NewIndices.resize(
m_Nodes.size(), 0);
733 int iNumNodesDeleted = 0;
734 for (i=0, j=0; i<(int)NewIndices.size(); ++i)
743 list<int>::iterator itIndex;
748 *itIndex = NewIndices[*itIndex];
752 vector<XYZ>::iterator itNode;
753 vector<XYZ> NewNodes;
755 for (itNode =
m_Nodes.begin(), iNodeIndex=0; itNode !=
m_Nodes.end(); ++itNode, ++iNodeIndex)
757 if (!Nodes.count(iNodeIndex))
758 NewNodes.push_back(*itNode);
762 return iNumNodesDeleted;
767 list<int>::iterator itIter;
768 int i1, i2, i3, i4, i5, i6, i7, i8;
815 list<int>::iterator itIter;
816 int i1, i2, i3, i4, i5, i6;
854 list<int>::iterator itIter;
884 list<int>::iterator itIter;
885 int i0, i1, i2, i3, i4, i5, i6, i7;
920 list<int>::iterator itIter;
921 int i0, i1, i2, i3, i4, i5;
951 list<int>::iterator itIter;
952 int i0, i1, i2, i3, i4;
961 double d1 = 0, d2 = 0;
1010 list<int>::iterator itIter;
1011 int i0, i1, i2, i3, i4;
1048 list<int>::iterator itEnd = itQuad;
1068 list<int>::iterator itIter;
1090 list<int>::iterator itIter;
1141 vector<XYZ>::iterator itNode;
1142 for (itNode =
m_Nodes.begin(); itNode !=
m_Nodes.end(); ++itNode)
1150 vector<XYZ>::iterator itNode;
1151 for (itNode =
m_Nodes.begin(); itNode !=
m_Nodes.end(); ++itNode)
1153 (*itNode) = Rotation * (*itNode-Origin) + Origin;
1168 list<int>::iterator itIter;
1169 list<int>::iterator it0, it1, it2, it3;
1204 const double TOL = 1e-10;
1206 list<int> ClosedLoop(ClosedLoopVector.begin(), ClosedLoopVector.end());
1210 list<int>::iterator itPrev;
1211 list<int>::iterator itCurrent;
1212 list<int>::iterator itNext;
1213 list<int>::iterator itCompare;
1214 list<int>::iterator itBest;
1219 PLANE PL1, PL2, PL3;
1228 while (ClosedLoop.size() >= 3)
1232 itPrev = ClosedLoop.end(); --itPrev;
1233 itCurrent = ClosedLoop.begin();
1234 itNext = ClosedLoop.begin(); ++itNext;
1236 while (itCurrent != ClosedLoop.end())
1266 for (itCompare = ClosedLoop.begin(); itCompare != ClosedLoop.end(); ++itCompare)
1268 if (itCompare == itPrev || itCompare == itCurrent || itCompare == itNext)
1283 if (itCompare == ClosedLoop.end())
1293 if (!bFound || dAngle > dBestAngle)
1295 dBestAngle = dAngle;
1308 if (itPrev == ClosedLoop.end())
1309 itPrev = ClosedLoop.begin();
1310 if (itNext == ClosedLoop.end())
1311 itNext = ClosedLoop.begin();
1319 TGERROR(
"Couldn't mesh closed loop on domain edge" );
1328 if (itBest == ClosedLoop.begin())
1329 {itPrev = ClosedLoop.end(); --itPrev;}
1331 {itPrev = itBest; --itPrev;}
1333 itNext = itBest; ++itNext;
1334 if (itNext == ClosedLoop.end())
1335 itNext = ClosedLoop.begin();
1336 TriIndices.push_back(*itPrev);
1337 TriIndices.push_back(*itCurrent);
1338 TriIndices.push_back(*itNext);
1339 ClosedLoop.erase(itCurrent);
1439 CMesh Original = *
this;
1442 for (i=iLowerLimit; i<=iUpperLimit; ++i)
1466 vector<XYZ>::const_iterator itNode;
1469 Output <<
m_Nodes.size() << endl;
1471 for (itNode =
m_Nodes.begin(), iNodeIndex=0; itNode !=
m_Nodes.end(); ++itNode, ++iNodeIndex)
1473 if (iStartIndex >= 0 && !bSCIRun)
1474 Output << iNodeIndex+iStartIndex << Seperator;
1475 Output << *itNode << endl;
1477 return iNodeIndex+iStartIndex;
1484 int iElementNumber = 0;
1485 list<int>::const_iterator itIndex;
1489 for (itIndex =
m_Indices[ElementType].begin(); itIndex !=
m_Indices[ElementType].end(); ++iElementNumber)
1491 if (iStartIndex >= 0 && !bSCIRun)
1492 Output << iElementNumber+iStartIndex << Seperator;
1493 for (i=0; i<
GetNumNodes(ElementType); ++i, ++itIndex)
1496 Output << Seperator;
1497 Output << (*itIndex)+iIndexOffset;
1501 return iElementNumber+iStartIndex;
1507 References.resize(
m_Nodes.size());
1509 list<int>::iterator itIndex;
1514 References[*itIndex].push_back(&(*itIndex));
1526 CMesh TriMesh(*
this);
1536 list<int>::const_iterator itIter;
1537 for (itIter = TriangleIndices.begin(); itIter != TriangleIndices.end(); )
1543 dVolume += ((P2.y-P1.
y)*(P3.z-P1.
z)-(P2.z-P1.
z)*(P3.y-P1.
y)) * (P1.
x+P2.x+P3.x);
1551 TGLOG(
"Get Element Centres");
1552 vector<XYZ> ElementCenters;
1553 int i, j, iNumNodes;
1554 list<int>::const_iterator itIndex;
1558 if ( iNumNodes != -1 )
1563 for (j=0; j<iNumNodes; ++j)
1568 Center /= iNumNodes;
1569 ElementCenters.push_back(Center);
1573 return ElementCenters;
1578 vector<XYZ> ElementCentres;
1580 list<int>::const_iterator itIndex;
1584 for (
int i=0; i<iNumNodes; ++i)
1589 Centre /= iNumNodes;
1590 ElementCentres.push_back(Centre);
1592 return ElementCentres;
1598 int iNumInvertedElements = 0;
1603 return iNumInvertedElements;
1608 if (ElementType !=
TET && ElementType !=
PYRAMID && ElementType !=
WEDGE)
1612 list<int>::const_iterator itIter;
1613 int i, iNumInvertedElements = 0;
1616 const list<int> &Indices =
m_Indices[ElementType];
1618 for (itIter = Indices.begin(); itIter != Indices.end(); )
1620 CopiedMesh.
m_Indices[ElementType].clear();
1621 for (i=0; i<iNumNodes; ++i)
1623 CopiedMesh.
m_Indices[ElementType].push_back(*(itIter++));
1627 ++iNumInvertedElements;
1630 return iNumInvertedElements;
1633int CMesh::IntersectLine(
const XYZ &P1,
const XYZ &P2, vector<pair<double, XYZ> > &IntersectionPoints, pair<bool, bool> TrimResults,
bool bForceFind)
const
1640 TGERROR(
"Warning: IntersectLine only works for triangle mesh, mesh contains other element types");
1645 IntersectionPoints.clear();
1648 XYZ Normal, Intersection;
1650 const double dTolerance = 1e-9;
1691 list<int>::const_iterator itIter;
1692 for (itIter = TriangleIndices.begin(); itIter != TriangleIndices.end(); )
1705 if (TrimResults.first && dU < 0)
1707 if(TrimResults.second && dU > 1)
1710 if (dMin >= -dTolerance)
1712 IntersectionPoints.push_back(pair<double, XYZ>(dU, Normal));
1714 if (bFirst || dMin > dAccuracy)
1719 BestNormal = Normal;
1730 if (bForceFind && IntersectionPoints.empty())
1732 IntersectionPoints.push_back(pair<double, XYZ>(dBestU, BestNormal));
1735 sort(IntersectionPoints.begin(), IntersectionPoints.end(),
LessPairDoubleXYZ());
1737 return IntersectionPoints.size();
1742 list<pair<int, int> >::iterator FindResult;
1743 FindResult = find(EdgeStack.begin(), EdgeStack.end(), Edge);
1744 if (FindResult != EdgeStack.end())
1746 EdgeStack.erase(FindResult);
1749 FindResult = find(EdgeStack.begin(), EdgeStack.end(), pair<int, int>(Edge.second, Edge.first));
1750 if (FindResult != EdgeStack.end())
1752 EdgeStack.erase(FindResult);
1755 EdgeStack.push_back(Edge);
1766 const double TOL = 1e-7;
1768 list<pair<int, int> > EdgeStack;
1769 list<pair<int, int> >::iterator itEdge;
1784 list<PLANE> TrianglePlanes;
1789 for (i=0; i+2<(int)
m_Nodes.size(); ++i)
1800 if (i+2 == (
int)
m_Nodes.size())
1802 TGERROR(
"Unable to create convex hull, all points are collinear");
1807 TriangleIndices.push_back(i+0);
1808 TriangleIndices.push_back(i+1);
1809 TriangleIndices.push_back(i+2);
1812 TrianglePlanes.push_back(Plane);
1814 TriangleIndices.push_back(i+0);
1815 TriangleIndices.push_back(i+2);
1816 TriangleIndices.push_back(i+1);
1819 TrianglePlanes.push_back(Plane);
1821 list<int>::iterator itIter, itTriStart;
1822 list<PLANE>::iterator itPlane;
1829 bFacesAdded =
false;
1830 for (i=0; i<(int)
m_Nodes.size(); ++i)
1834 for (itIter = TriangleIndices.begin(), itPlane = TrianglePlanes.begin(); itIter != TriangleIndices.end(); )
1836 itTriStart = itIter;
1850 itIter = TriangleIndices.erase(itTriStart, itIter);
1851 itPlane = TrianglePlanes.erase(itPlane);
1859 for (itEdge = EdgeStack.begin(); itEdge != EdgeStack.end(); ++itEdge)
1862 i2 = itEdge->second;
1864 TriangleIndices.push_back(i1);
1865 TriangleIndices.push_back(i2);
1866 TriangleIndices.push_back(i3);
1873 TrianglePlanes.push_back(Plane);
1878 }
while (bFacesAdded);
1885 for (i=0; i<iNumX; ++i)
1887 for (j=0; j<iNumY; ++j)
1889 for (k=0; k<iNumZ; ++k)
1891 P.
x = i/double(iNumX-1);
1892 P.
y = j/double(iNumY-1);
1893 P.
z = k/double(iNumZ-1);
1897 if (i < iNumX-1 && j < iNumY-1 && k < iNumZ-1)
1899 m_Indices[
HEX].push_back((k+0) + (j+0)*iNumZ + (i+0)*iNumZ*iNumY);
1900 m_Indices[
HEX].push_back((k+0) + (j+0)*iNumZ + (i+1)*iNumZ*iNumY);
1901 m_Indices[
HEX].push_back((k+0) + (j+1)*iNumZ + (i+1)*iNumZ*iNumY);
1902 m_Indices[
HEX].push_back((k+0) + (j+1)*iNumZ + (i+0)*iNumZ*iNumY);
1903 m_Indices[
HEX].push_back((k+1) + (j+0)*iNumZ + (i+0)*iNumZ*iNumY);
1904 m_Indices[
HEX].push_back((k+1) + (j+0)*iNumZ + (i+1)*iNumZ*iNumY);
1905 m_Indices[
HEX].push_back((k+1) + (j+1)*iNumZ + (i+1)*iNumZ*iNumY);
1906 m_Indices[
HEX].push_back((k+1) + (j+1)*iNumZ + (i+0)*iNumZ*iNumY);
1915 int iNumX, iNumY, iNumZ;
1928 val = (float)Vector[i];
1929 Output.write((
char*)&val, 4);
1942 CMesh TriMesh(*
this);
1944 return TriMesh.
SaveToSTL(Filename, bBinary);
1950 Output.open(Filename.c_str(), ios::out|ios::binary);
1952 Output.open(Filename.c_str(), ios::out);
1961 int iNumFacets = TriangleIndices.size()/3;
1962 strncpy(szHeader, Filename.c_str(), 80);
1963 Output.write(szHeader, 80);
1964 Output.write((
char*)&iNumFacets, 4);
1967 Output <<
"solid " << Filename << endl;
1969 XYZ T1, T2, T3, Normal;
1970 list<int>::const_iterator itIndex;
1971 short int Padding = 0;
1972 for (itIndex = TriangleIndices.begin(); itIndex != TriangleIndices.end(); )
1987 Output.write((
char*)&Padding, 2);
1991 Output <<
" facet normal " << Normal.x <<
" " << Normal.y <<
" " << Normal.z << endl;
1992 Output <<
" outer loop" << endl;
1993 Output <<
" vertex " << T1.
x <<
" " << T1.
y <<
" " << T1.
z << endl;
1994 Output <<
" vertex " << T2.x <<
" " << T2.y <<
" " << T2.z << endl;
1995 Output <<
" vertex " << T3.x <<
" " << T3.y <<
" " << T3.z << endl;
1996 Output <<
" endloop" << endl;
1997 Output <<
" endfacet" << endl;
2002 Output <<
"endsolid " << Filename << endl;
2013 ofstream Output(Filename.c_str(), ios::out);
2016 Output <<
"# node count, 3 dim, no attribute, no boundary marker" << endl;
2017 Output <<
m_Nodes.size() <<
" 3 0 0" << endl;
2019 Output <<
"# node index, node coordinates" << endl;
2021 vector<XYZ>::const_iterator itNode;
2022 for (itNode =
m_Nodes.begin(), iNodeIndex=0; itNode !=
m_Nodes.end(); ++itNode, ++iNodeIndex)
2024 Output << iNodeIndex <<
" " << itNode->x <<
" " << itNode->y <<
" " << itNode->z << endl;
2030 Output <<
"# facet count, no boundary marker" << endl;
2031 Output << iNumTriangles+iNumQuads <<
" 0" << endl;
2032 Output <<
"# facets" << endl;
2033 list<int>::const_iterator itIndex;
2034 int iNumNodesPerElement;
2046 Output << iNumNodesPerElement <<
" ";
2047 for (i=0; i<iNumNodesPerElement; ++i, ++itIndex)
2051 Output << (*itIndex);
2056 Output <<
"# Part 3 - hole list" << endl;
2057 Output <<
"0 # no hole" << endl;
2058 Output <<
"# Part 4 - region list" << endl;
2059 Output <<
"0 # no region" << endl;
2089bool CMesh::SaveToABAQUS(
string Filename,
const vector<POINT_INFO> *pElementInfo,
bool bCreateStep,
bool bCreateMaterial,
int iElementType)
2093 ofstream Output(Filename.c_str());
2097 TGERROR(
"Unable to output mesh to ABAQUS file format, could not open file: " << Filename);
2101 TGLOG(
"Saving mesh data to " << Filename);
2103 Output <<
"*Heading" << endl;
2104 Output <<
"File generated by TexGen v" <<
TEXGEN.GetVersion() << endl;
2106 Output <<
"************" << endl;
2107 Output <<
"*** MESH ***" << endl;
2108 Output <<
"************" << endl;
2109 Output <<
"*Node" << endl;
2112 int iStartIndex = 1;
2117 Output <<
"*Element, Type=C3D4" << endl;
2123 Output <<
"*Element, Type=C3D6" << endl;
2129 int i1, i2, i3, i4, i5, i6;
2130 int iElementNumber = 0;
2131 list<int>::const_iterator itIndex;
2134 i1 = *(itIndex++)+1;
2135 i2 = *(itIndex++)+1;
2136 i3 = *(itIndex++)+1;
2137 i4 = *(itIndex++)+1;
2138 i5 = *(itIndex++)+1;
2139 i6 = *(itIndex++)+1;
2140 Output << iElementNumber+iStartIndex
2141 <<
", " << i4 <<
", " << i5 <<
", " << i6
2142 <<
", " << i1 <<
", " << i2 <<
", " << i3
2145 iStartIndex += iElementNumber;
2150 if ( !iElementType )
2152 Output <<
"*Element, Type=C3D8R" << endl;
2156 Output <<
"*Element, Type=C3D8" << endl;
2164 Output <<
"*Element, Type=C3D10" << endl;
2171 Output <<
"*Element, Type=S4R" << endl;
2177 string OrientationsFilename = Filename;
2178 OrientationsFilename.replace(OrientationsFilename.end()-4, OrientationsFilename.end(),
".ori");
2179 ofstream OriOutput(OrientationsFilename.c_str());
2180 string ElementDataFilename = Filename;
2181 ElementDataFilename.replace(ElementDataFilename.end()-4, ElementDataFilename.end(),
".eld");
2182 ofstream DataOutput(ElementDataFilename.c_str());
2186 TGERROR(
"Unable to output orientations, could not open file: " << OrientationsFilename);
2191 TGERROR(
"Unable to output additional element data, could not open file: " << ElementDataFilename);
2195 TGLOG(
"Saving element orientations data to " << OrientationsFilename);
2196 TGLOG(
"Saving additional element data to " << ElementDataFilename);
2199 Output <<
"*Distribution Table, Name=TexGenOrientationVectors" << endl;
2200 Output <<
"COORD3D,COORD3D" << endl;
2201 Output <<
"*Distribution, Location=Element, Table=TexGenOrientationVectors, Name=TexGenOrientationVectors, Input=" <<
StripPath(OrientationsFilename) << endl;
2202 Output <<
"*Orientation, Name=TexGenOrientations, Definition=coordinates" << endl;
2203 Output <<
"TexGenOrientationVectors" << endl;
2204 Output <<
"1, 0" << endl;
2208 OriOutput <<
", 1.0, 0.0, 0.0, 0.0, 1.0, 0.0" << endl;
2214 map<int, vector<int> > ElementSets;
2215 vector<POINT_INFO>::const_iterator itData;
2216 for (itData = pElementInfo->begin(), i=1; itData != pElementInfo->end(); ++itData, ++i)
2218 if (itData->iYarnIndex != -1)
2222 XYZ Up = itData->Up;
2223 XYZ Dir = itData->Orientation;
2227 OriOutput << i <<
", " << Dir <<
", " << Perp << endl;
2232 OriOutput << i <<
", 1.0, 0.0, 0.0, 0.0, 1.0, 0.0" << endl;
2238 OriOutput << i <<
", 1.0, 0.0, 0.0, 0.0, 1.0, 0.0" << endl;
2241 DataOutput <<
", " << itData->iYarnIndex;
2242 DataOutput <<
", " << itData->Location;
2243 DataOutput <<
", " << itData->dVolumeFraction;
2244 DataOutput <<
", " << itData->dSurfaceDistance;
2246 ElementSets[itData->iYarnIndex].push_back(i);
2250 Output <<
"********************" << endl;
2251 Output <<
"*** ELEMENT SETS ***" << endl;
2252 Output <<
"********************" << endl;
2253 Output <<
"** TexGen generates a number of element sets:" << endl;
2254 Output <<
"** All - Contains all elements" << endl;
2255 Output <<
"** Matrix - Contains all elements belonging to the matrix" << endl;
2256 Output <<
"** YarnX - Where X represents the yarn index" << endl;
2257 Output <<
"*ElSet, ElSet=All, Generate" << endl;
2259 vector<int>::iterator itIndices;
2260 map<int, vector<int> >::iterator itElementSet;
2261 for (itElementSet = ElementSets.begin(); itElementSet != ElementSets.end(); ++itElementSet)
2263 if (itElementSet->first == -1)
2264 Output <<
"*ElSet, ElSet=Matrix" << endl;
2266 Output <<
"*ElSet, ElSet=Yarn" << itElementSet->first << endl;
2268 for (itIndices = itElementSet->second.begin(); itIndices != itElementSet->second.end(); ++itIndices)
2274 else if (iLinePos < 16)
2283 Output << *itIndices;
2292 if (bCreateMaterial)
2294 Output <<
"*****************" << endl;
2295 Output <<
"*** MATERIALS ***" << endl;
2296 Output <<
"*****************" << endl;
2297 Output <<
"*Material, Name=TexGenGenerated" << endl;
2298 Output <<
"*Elastic" << endl;
2299 Output <<
"1.0, 0.0" << endl;
2300 Output <<
"*DepVar" << endl;
2301 Output <<
"5" << endl;
2304 for (itElementSet = ElementSets.begin(); itElementSet != ElementSets.end(); ++itElementSet)
2308 ostringstream SetName;
2309 if (itElementSet->first == -1)
2311 SetName <<
"Matrix";
2315 SetName <<
"Yarn" << itElementSet->first;
2317 Output <<
"*Solid Section, ElSet=" << SetName.str() <<
", Material=TexGenGenerated, Orientation=TexGenOrientations" << endl;
2318 Output <<
"1.0," << endl;
2320 Output <<
"** Note: Additional element data are stored as a depvars:" << endl;
2321 Output <<
"** 1 - Yarn Index (-1 for matrix, first yarn starting at 0)" << endl;
2322 Output <<
"** 2/3 - Location (x and y cross-section coordinates of element relative to yarn centerline)" << endl;
2323 Output <<
"** 4 - Volume fraction" << endl;
2324 Output <<
"** 5 - Distance of element from the surface of the yarn (for yarn elements only, distance is negative)" << endl;
2325 Output <<
"*Initial Conditions, Type=Solution, Input=" <<
StripPath(ElementDataFilename) << endl;
2330 Output <<
"************" << endl;
2331 Output <<
"*** STEP ***" << endl;
2332 Output <<
"************" << endl;
2333 Output <<
"*Step, Name=TexGenGenerated" << endl;
2334 Output <<
"*Static" << endl;
2335 Output <<
"*Output, Field, Variable=PRESELECT" << endl;
2337 Output <<
"*Element Output" << endl;
2338 Output <<
"SDV" << endl;
2339 Output <<
"*Node Print" << endl;
2340 Output <<
"U" << endl;
2341 Output <<
"*End Step" << endl;
2353 TiXmlDeclaration decl(
"1.0",
"",
"");
2354 doc.InsertEndChild(decl);
2355 TiXmlElement VTKFile(
"VTKFile");
2357 VTKFile.SetAttribute(
"type",
"UnstructuredGrid");
2358 VTKFile.SetAttribute(
"version",
"0.1");
2359 VTKFile.SetAttribute(
"byte_order",
"LittleEndian");
2360 TiXmlElement UnstructuredGrid(
"UnstructuredGrid");
2362 TiXmlElement Piece(
"Piece");
2364 TiXmlElement Points(
"Points");
2366 Piece.InsertEndChild(Points);
2368 TiXmlElement Cells(
"Cells");
2370 Piece.InsertEndChild(Cells);
2374 TiXmlElement PointData(
"PointData");
2375 TiXmlElement CellData(
"CellData");
2376 vector<CMeshDataBase*>::const_iterator itData;
2377 for (itData = pMeshData->begin(); itData != pMeshData->end(); ++itData)
2380 (*itData)->InsertVTKData(PointData);
2382 (*itData)->InsertVTKData(CellData);
2384 TGLOG(
"Finished iterator");
2385 Piece.InsertEndChild(PointData);
2386 Piece.InsertEndChild(CellData);
2387 TGLOG(
"End InsertVTKData");
2390 Piece.SetAttribute(
"NumberOfPoints",
stringify(iNumPoints));
2391 Piece.SetAttribute(
"NumberOfCells",
stringify(iNumCells));
2393 UnstructuredGrid.InsertEndChild(Piece);
2395 VTKFile.InsertEndChild(UnstructuredGrid);
2398 doc.InsertEndChild(VTKFile);
2399 TGLOG(
"Return call SaveFile");
2400 return doc.SaveFile(Filename);
2449 TGLOG(
"FillVTKPointData");
2450 ostringstream PointsData;
2451 vector<XYZ>::const_iterator itNode;
2452 for (itNode =
m_Nodes.begin(); itNode !=
m_Nodes.end(); ++itNode)
2454 PointsData << itNode->x <<
" " << itNode->y <<
" " << itNode->z <<
" ";
2457 TiXmlElement DataArray(
"DataArray");
2459 DataArray.SetAttribute(
"type",
"Float32");
2460 DataArray.SetAttribute(
"NumberOfComponents",
"3");
2461 DataArray.SetAttribute(
"format",
"ascii");
2462 DataArray.InsertEndChild(TiXmlText(PointsData.str()));
2464 Points.InsertEndChild(DataArray);
2471 TGLOG(
"FillVTKCellData");
2472 ostringstream ConnectivityData;
2473 ostringstream OffsetsData;
2474 ostringstream TypesData;
2477 int iTotalNumCells = 0;
2478 list<int>::const_iterator itIndex;
2516 int iNumElements =
m_Indices[j].size()/iNumNodesPerElement;
2517 for (itIndex =
m_Indices[j].begin(), i=0; itIndex !=
m_Indices[j].end(); ++itIndex, ++i)
2519 ConnectivityData << *itIndex <<
" ";
2521 for (i=0; i<iNumElements; ++i)
2523 TypesData << iVTKType <<
" ";
2525 for (i=0; i<iNumElements; ++i)
2527 iOffset += iNumNodesPerElement;
2528 OffsetsData << iOffset <<
" ";
2530 iTotalNumCells += iNumElements;
2535 TiXmlElement Connectivity(
"DataArray");
2537 Connectivity.SetAttribute(
"type",
"Int32");
2538 Connectivity.SetAttribute(
"Name",
"connectivity");
2539 Connectivity.SetAttribute(
"format",
"ascii");
2540 Connectivity.InsertEndChild(TiXmlText(ConnectivityData.str()));
2542 Cells.InsertEndChild(Connectivity);
2544 TiXmlElement Offsets(
"DataArray");
2546 Offsets.SetAttribute(
"type",
"Int32");
2547 Offsets.SetAttribute(
"Name",
"offsets");
2548 Offsets.SetAttribute(
"format",
"ascii");
2549 Offsets.InsertEndChild(TiXmlText(OffsetsData.str()));
2551 Cells.InsertEndChild(Offsets);
2553 TiXmlElement Types(
"DataArray");
2555 Types.SetAttribute(
"type",
"Int32");
2556 Types.SetAttribute(
"Name",
"types");
2557 Types.SetAttribute(
"format",
"ascii");
2558 Types.InsertEndChild(TiXmlText(TypesData.str()));
2560 Cells.InsertEndChild(Types);
2562 return iTotalNumCells;
2569 TGERROR(
"Tried to add element of invalid type: " << Type);
2574 TGERROR(
"Tried to add element of type " << Type <<
" with invalid number of indices: " << Indices.size());
2577 if ( Type ==
CMesh::POLYGON && *(Indices.begin()) != *(Indices.end()-1) )
2579 TGERROR(
"Tried to add unclosed POLYGON to mesh" );
2594 int iNumElements = 0;
2601 return iNumElements;
2632 assert(iIndex >= 0 && iIndex<(
int)
m_Nodes.size());
2687 Indices.insert( Indices.begin(),
m_Indices[ElementType].begin(),
m_Indices[ElementType].end() );
2695 ofstream Output(Filename.c_str());
2699 TGERROR(
"Unable to output mesh to SCIRun .pts file format, could not open file: " << Filename);
2703 TGLOG(
"Saving mesh data to " << Filename);
2708 int iStartIndex = 1;
2713 ofstream ElementOutput( Filename.c_str());
2717 TGERROR(
"Unable to output mesh to SCIRun .fac file format, could not open file: " << Filename);
2721 TGLOG(
"Saving mesh data to " << Filename);
#define TGERROR(MESSAGE)
Macros used to report the file name and line number to the TexGenError and TexGenLog functions.
#define FOR_EACH_TIXMLELEMENT(CHILDELEMENT, PARENTELEMENT, ELEMENTNAME)
Macro to enable looping over tinyxml easier.
#define TEXGEN
Helper macro to get the texgen instance.
Defines the nodes and elements of a surface or volume mesh.
void RemoveOpposingQuads()
Remove quads that have the same indices but opposite normals.
int FillVTKPointData(TiXmlElement &Points) const
bool AddElement(ELEMENT_TYPE Type, const vector< int > &Indices)
Add an element to the mesh of given type with node number checking.
void ConvertHextoWedge(bool bQuality=true)
Convert Hexahedral elements to Wedge elements.
int GetNumNodes() const
Return the number of nodes.
int GetNumElements() const
Get the total number of elements in the mesh.
void RemoveAllElementsExcept(ELEMENT_TYPE Type)
Remove all elements except those of given type.
void ChangeNodeIndices(int iChangeTo, int iChangeFrom)
Change all the indices from one number to another.
int MergeNodes(const double Tolerance=1e-8)
If any nodes share the same coordinates merge the nodes together and adjust indices accordingly.
void GetNodeElementReferences(vector< vector< int * > > &References)
Get a list of elements which reference each node.
void RemoveDuplicateSegments()
Remove segments which have the same indices.
void InsertMesh(const CMesh &Mesh, XYZ Offset=XYZ(0, 0, 0))
Add the contents of Mesh to this mesh.
void ConvertQuadstoTriangles(bool bQuality=true)
Convert the quad elements to triangles.
void RemoveDegenerateTriangles()
Remove triangles which have two equal corner indices.
vector< pair< int, int > > GetNodePairs(XYZ Vector, const double Tolerance=1e-6) const
Return a list of node pairs (A, B) where A == B + Vector.
void ConvertHextoQuad()
Convert Hex elements to Quad elements representing their surface.
const vector< XYZ > & GetNodes() const
Get a const reference to the nodes.
void RemoveDuplicateTriangles()
bool SaveToSMESH(string Filename) const
Save the mesh to a .smesh file to be used in conjunction with tetgen.
void Convert3Dto2D()
Convert all 3D elements to 2D elements representing their surface.
bool SaveToABAQUS(string Filename, const vector< POINT_INFO > *pElementInfo=NULL, bool bCreateStep=true, bool bCreateMaterial=true, int iElementType=0)
Save the mesh to ABAQUS input file format with information such as yarn tangents.
static void WriteBinaryXYZ(ostream &Output, XYZ Vector)
const int AddNode(XYZ Node)
Append a node to the list of nodes, the integer returns the index of the node
void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType) const
Used for saving data to XML.
const XYZ & GetNode(int iIndex) const
Get the node with given ID.
int RemoveUnreferencedNodes()
Remove nodes that are not referenced by any elements.
vector< XYZ > GetElementCenters() const
Get a vector of element centers, one entry for each element.
list< int >::iterator ConvertQuadtoTriangles(list< int >::iterator itQuad)
Convert a specific quad element to two triangles.
void ConvertPyramidto2D()
Convert Pyramid elements to Quad and Triangle elements representing their surface.
void ConvertTriToQuad(double Tolerance=1e-6)
Convert Triangel elements to Quads.
int OutputElements(ostream &Output, ELEMENT_TYPE ElementType, int iStartIndex=1, int iIndexOffset=1, string Seperator=", ", bool bSCIRun=false) const
Output the element indices in the mesh each on a new line, indices seperated by commas.
list< int > m_Indices[NUM_ELEMENT_TYPES]
Map of indices into the nodes.
void MeshConvexHull()
Create a triangular convex hull of the nodes contained within the mesh.
bool SaveToVTK(string Filename, const vector< CMeshDataBase * > *pMeshData=NULL) const
Save the mesh to VTK unstructured grid file format (.vtu)
void ConvertTrianglestoSegments()
Convert triangle elements to segments.
void Translate(XYZ Vector)
Translate whole mesh by given vector.
bool SaveToSCIRun(string Filename)
Save the mesh to SCIRun format.
bool SaveToSTL(string Filename, bool bBinary=true) const
Save the mesh to STL file.
void ConvertHextoTet(bool bQuality=true)
Convert Hexahedral elements to Tetrahedral elements.
int GetClosestNode(XYZ Position) const
Get the index of the node closest to the given position space.
void RemoveElementType(ELEMENT_TYPE Type)
Remove elements of given type.
const list< int > & GetIndices(ELEMENT_TYPE ElemType) const
Get the element indices of a given element type.
void RemoveOpposingTriangles()
Remove triangles that have the same indices but opposite normals.
int DeleteNodes(const set< int > &Nodes)
Delete nodes and adjust node indices.
ELEMENT_TYPE
Each element type is represented by a unique integer value.
void ConvertPyramidtoTet(bool bQuality=true)
Convert Pyramid elements to Tetrahedral elements.
int OutputNodes(ostream &Output, int iStartIndex=1, string Seperator=", ", bool bSCIRun=false) const
Output the node coordinates in the mesh each on a new line, components seperated by commas.
void SetNode(int iIndex, XYZ Node)
Set the node at given index.
void MeshClosedLoop(const XYZ &Normal, const vector< int > &ClosedLoopVector, bool bQuality=false)
void CopySelfToRange(XYZ Vector, int iLowerLimit, int iUpperLimit)
Copy the mesh to the range given by the lower limit and upper limit with the given repeat vector.
void ConvertWedgetoTetandPyramid(bool bQuality=true)
Convert Wedge elements to a combination of Tetrahedral and Pyramid elements.
void ConvertToTriangleMesh()
void ConvertWedgeto2D()
Convert Wedge elements to Quad and Triangle elements representing their surface.
vector< XYZ > m_Nodes
List of nodes.
void BuildGrid(XYZ Min, XYZ Max, int iNumX, int iNumY, int iNumZ)
Build grid of points.
void ConvertWedgetoTet(bool bQuality=true)
Convert Wedge elements to Tetrahedral elements.
void SetNumNodes(int NumNodes)
Resize the vector size.
void FlipNormals()
Flip the normals of the mesh for triangles and quads.
void ConvertElementListToVector(ELEMENT_TYPE ElementType, vector< int > &Indices)
Convert element index list to vector so can access by index.
double CalculateVolume() const
Calculate the volume of the mesh.
int GetClosestNodeDistance(XYZ Position, double dTol) const
Get the index of the node within a given tolerance distance to the given position space.
pair< XYZ, XYZ > GetAABB(double dGrowDistance=0) const
Get an axis aligned bounding box for the mesh.
void Clear()
Empty mesh nodes and indices.
void Rotate(WXYZ Rotation, XYZ Origin=XYZ(0, 0, 0))
Rotate the whole mesh by given quaternion.
static void AddOrCancel(list< pair< int, int > > &EdgeStack, pair< int, int > Edge)
Add an edge to the stack of edges if it doesn't already exist otherwise if it exists delete it.
int FillVTKCellData(TiXmlElement &Cells) const
void ConvertToSegmentMesh()
Convert all elements to segments.
vector< XYZ >::const_iterator NodesBegin() const
const bool NodesEmpty() const
Returns true if the nodes array is empty.
vector< XYZ >::iterator DeleteNode(vector< XYZ >::iterator it)
Delete a node given iterator.
int CountInvertedElements() const
Check and count if any of the elements are inverted.
int InsertNodes(const CMesh &Mesh, XYZ Offset=XYZ(0, 0, 0))
Add the nodes of Mesh to this mesh.
void ConvertToSurfaceMesh()
Convert a volume mesh into a surface mesh (interior surfaces are elliminated)
vector< XYZ >::const_iterator NodesEnd() const
void RemoveDuplicateElements(CMesh::ELEMENT_TYPE ElementType)
Remove duplicate elements which have the same indices (leaves one copy of element)
int IntersectLine(const XYZ &P1, const XYZ &P2, vector< pair< double, XYZ > > &IntersectionPoints, pair< bool, bool > TrimResults=make_pair(false, false), bool bForceFind=false) const
Find the points where a line intersects the mesh.
void ConvertTettoTriangle()
Convert Tet elements to Triangle elements representing their surface.
Octree agent used to add indexed nodes to an octree.
Octree visitor used to merge nodes together within a given tolerance.
Namespace containing a series of customised math operations not found in the standard c++ library.
double PointInsideTriangleAccuracy(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, const XYZ &N)
P1, P2, P3 are the three triangle corners, P is the points to be tested, N is the normal to the trian...
std::string RemoveExtension(std::string &Filename, std::string Extension)
Strip the extension from the filename.
std::string StripPath(std::string Filename)
Strip the path from the filename (e.g. "c:\folder\file.ext -> file.ext")
double GetLengthSquared(const XYZ &Point1, const XYZ &Point2)
Get the length squared between two points.
void WriteElementsHeader(std::ostream &Output)
Write elements header for ABAQUS .eld files.
void WriteOrientationsHeader(std::ostream &Output)
Write orientations header for ABAQUS .ori files.
bool GetIntersectionLinePlane(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &N, XYZ &Intersection, double *pdU=NULL)
P1 and P2 are two points on the line, P3 is a point on the plane, N is the plane normal,...
double Max(XYZ &Vector)
Get maximum element of vector and return it.
double GetLength(const XYZ &Point1, const XYZ &Point2)
Get the length between two points.
std::string stringify(const T &x, int iPrecision=12, bool bScientific=true)
Function to convert a value (e.g. int, double, etc...) to a string.
XYZ Min(const XYZ &P1, const XYZ &P2)
Given two points, return a new point who's coordinates are the smaller of the two.
WXYZ & Normalise(WXYZ &Quaternion)
Normalise the quaternion and return it.
void AddExtensionIfMissing(std::string &Filename, std::string Extension)
Adds an extension to the filename if it is missing otherwise do nothing (e.g. picture -> picture....
double DotProduct(const XYZ &left, const XYZ &right)
Get the dot product of two vectors.
XYZ CrossProduct(const XYZ &left, const XYZ &right)
Get the cross product of two vectors.
Used to sort double-XYZ pairs.
Struct for representing a Plane.
Struct for representing a quaternion.
Struct for representing points in 3D space.