TexGen
AdjustMeshInterference.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2010 Louise Brown
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18=============================================================================*/
19
20#include "PrecompiledHeaders.h"
22#include "TexGen.h"
23#include <time.h>
24
25#define FIRST_HALF 0
26#define SECOND_HALF 1
27#define TOL 1e-6
28
29using namespace TexGen;
30
31CAdjustMeshInterference::CAdjustMeshInterference(void)
32{
33}
34
36{
37}
38
40{
41 // Check if domain exists
42 const CDomain* pDomain = Textile.GetDomain();
43 if (!pDomain)
44 {
45 TGERROR("Unable to correct intersections: No domain specified");
46 return;
47 }
48
49 vector<CMesh> YarnMeshes;
50 Textile.AddVolumeToMesh( YarnMeshes, true); // check correct number of yarn meshes
51 if (YarnMeshes.size() != Textile.GetNumYarns())
52 {
53 TGERROR(" Unable to continue interference correction: failed to create yarn meshes");
54 return;
55 }
56
57 TGLOG("Adjusting mesh");
58 if (!AdjustMesh(Textile, YarnMeshes, Tolerance))
59 return;
60
61 TGLOG("Regenerating mesh using adjusted points");
62 AdjustSectionMeshes(Textile, YarnMeshes);
63 Textile.AddVolumeToMesh(YarnMeshes, true);
64}
65
66bool CAdjustMeshInterference::AdjustMesh( CTextile &Textile, vector<CMesh> &YarnMeshes, double Tolerance )
67{
68
69 int iNumYarns = Textile.GetNumYarns();
71 m_IntersectionMeshes.resize( iNumYarns );
72 m_Tolerance = Tolerance;
73 vector<CMesh>::iterator itMesh;
74
75 // Mesh.CalculateVolume() before & after gives change in total yarn volume. May need to use if output to format where
76 // using Vf = 1 and just need to know how much mass has been removed
77 for ( int i = 0; i < iNumYarns; ++i )
78 {
79 TGLOG( "Volume of yarn mesh " << i << " = " << YarnMeshes[i].CalculateVolume() << "\n" );
80 }
81
82 m_TempYarnMeshes.clear();
83 for ( itMesh = YarnMeshes.begin(); itMesh != YarnMeshes.end(); ++itMesh )
84 {
85 CMesh Mesh = *itMesh;
86 m_TempYarnMeshes.push_back( Mesh );
87 }
88
89 if (!CheckInitialIntersections(Textile, YarnMeshes)) // Returns false if any outside tolerence so adjustement needed
90 {
91 if (AdjustInitialIntersections(YarnMeshes)) // Returns false any of intersections larger than element intersecting with
92 {
93#ifdef _DEBUG
94 for (int i = 0; i < (int)YarnMeshes.size(); ++i)
95 {
96 YarnMeshes[i].SaveToVTK("c:\\Program Files\\TexGen\\InitialAdjustedMesh" + stringify(i));
97 }
98#endif
99 if (!AdjustIntersections(YarnMeshes))
100 {
101 TGERROR("Unable to adjust mesh: Intersection depths too large");
102 return false;
103 }
104 }
105 else
106 {
107 TGERROR("Unable to adjust mesh: Intersection depths too large");
108 return false;
109 }
110 }
111
112 return true;
113
114}
115
116
117bool CAdjustMeshInterference::CheckInitialIntersections( CTextile &Textile, vector<CMesh> &YarnMeshes )
118{
119 vector<float> InterferenceDepths;
120 vector<int> YarnIndices;
121 CMesh InterferencePoints;
122 double dMinDist, dDist, dMaxDist = 0.0;
123 int iIndex;
124
125 TGLOG("Checking initial intersections");
126 Textile.DetectInterference( InterferenceDepths, YarnIndices, true, &InterferencePoints );
127
128 const vector<XYZ> &Repeats = Textile.GetYarn(0)->GetRepeats(); // Simulation Abaqus only uses repeats from yarn 0 to get surface.
129 // Makes assumption that repeats are same for all yarns (valid?...)
130
131 for ( int i=0; i< (int)InterferenceDepths.size(); ++i )
132 {
133 dMinDist = -1.0;
134
135 dDist = fabs(InterferenceDepths[i]);
136 if ( dDist > dMaxDist ) // Find max interference depth
137 dMaxDist = dDist;
138
139 iIndex = YarnMeshes[YarnIndices[i]].GetClosestNode( InterferencePoints.GetNode( i ) );
140
141 if ( iIndex != -1 )
142 {
143 CMeshIntersectionData PointInfo;
144 int iPairIndex = -1;
145 PointInfo.SetYarn( YarnIndices[i] );
146 PointInfo.SetIndex( iIndex );
147 PointInfo.SetDepth( InterferenceDepths[i] );
148 PointInfo.SetPoint( InterferencePoints.GetNode(i) );
149 PointInfo.SetStartPoint( InterferencePoints.GetNode(i) );
150
151 // Check for corresponding point on opposite boundary
152 vector<XYZ>::const_iterator itRepeat;
153 for (itRepeat=Repeats.begin(); itRepeat!=Repeats.end(); ++itRepeat)
154 {
155 iPairIndex = YarnMeshes[YarnIndices[i]].GetClosestNodeDistance( InterferencePoints.GetNode(i) + (*itRepeat), TOL);
156 if ( iPairIndex != -1 )
157 break;
158 iPairIndex = YarnMeshes[YarnIndices[i]].GetClosestNodeDistance( InterferencePoints.GetNode(i) - (*itRepeat), TOL );
159 if ( iPairIndex != -1 )
160 break;
161 }
162 PointInfo.SetBoundaryPairIndex( iPairIndex );
163 m_Intersections.push_back( PointInfo );
164 }
165 else
166 {
167 TGERROR("Index = -1");
168 }
169 }
170
171 if ( dMaxDist < m_Tolerance )
172 return true; // Intersections all within tolerance
173 return false;
174}
175
177{
178
179 vector<CMeshIntersectionData>::iterator itIntersections;
180 vector<CMesh>::iterator itMesh;
181
182 // Convert element lists to vectors so that have random access into data
183 vector< vector<int> > WedgeElementIndices;
184 vector< vector<int> > HexElementIndices;
185
186 TGLOG("Adjusting initial intersections");
187 for ( itMesh = YarnMeshes.begin(); itMesh != YarnMeshes.end(); ++itMesh )
188 {
189 vector<int> ElementIndices;
190 ElementIndices.clear();
191
192 itMesh->ConvertElementListToVector( CMesh::WEDGE, ElementIndices );
193 WedgeElementIndices.push_back( ElementIndices );
194 ElementIndices.clear();
195 itMesh->ConvertElementListToVector( CMesh::HEX, ElementIndices );
196 HexElementIndices.push_back( ElementIndices );
197 }
198
199 for ( itIntersections = m_Intersections.begin(); itIntersections != m_Intersections.end(); ++itIntersections )
200 {
201 // Find all the elements in the mesh containing the intersection point
202
203 int iYarn = itIntersections->GetYarn();
204 bool bFoundNode;
205 itIntersections->FindElements( WedgeElementIndices[iYarn], CMesh::WEDGE);
206 itIntersections->FindElements( HexElementIndices[iYarn], CMesh::HEX );
207 itIntersections->FindPolygonPoints( YarnMeshes[iYarn].GetIndices(CMesh::POLYGON) );
208 bFoundNode = itIntersections->FindInterpolationNode( YarnMeshes[iYarn]);
209
210 if ( bFoundNode )
211 {
212 if ( !itIntersections->MoveNode( YarnMeshes[iYarn] ) ) // Adjust the point
213 return false; // Adjustment size > element size
214 }
215 }
216
217 for ( itIntersections = m_Intersections.begin(); itIntersections != m_Intersections.end(); ++itIntersections ) // Can't do this in previous loop because need to wait until all nodes adjusted
218 {
219 AddIntersectElementsToMesh( itIntersections->GetElements(), itIntersections->GetYarn(), YarnMeshes[itIntersections->GetYarn()] ); // Add the elements to a new mesh for the appropriate yarn to be used for further intersection testing
220 }
221
222 int i;
223 for ( itMesh = m_IntersectionMeshes.begin(), i=0; itMesh != m_IntersectionMeshes.end(); ++itMesh, ++i )
224 {
225#ifdef _DEBUG
226 itMesh->SaveToVTK( "c:\\Program Files\\TexGen\\IntersectionMesh" + stringify(i) );
227#endif
228 itMesh->MergeNodes();
229 itMesh->Convert3Dto2D();
230 itMesh->RemoveDuplicateElements(CMesh::QUAD);
231 itMesh->ConvertQuadstoTriangles();
232 }
233 return true;
234}
235
236// Create meshes containing just the elements with intersection points (to reduce data to check for intersections)
237void CAdjustMeshInterference::AddIntersectElementsToMesh( const vector<ELEMENT_INDICES> &Elements, int iYarn, CMesh &YarnMesh )
238{
239 vector<ELEMENT_INDICES>::const_iterator itElements;
240 int i;
241 for ( i = 0, itElements = Elements.begin(); itElements != Elements.end(); ++i, ++itElements )
242 {
243 vector<int> iNewIndices;
244 int iNumNodes = CMesh::GetNumNodes( itElements->ElementType );
245 for ( int j = 0; j < iNumNodes; ++j )
246 {
247 int iNodeIndex = m_IntersectionMeshes[iYarn].AddNode( YarnMesh.GetNode( itElements->Index[j] ));
248 iNewIndices.push_back( iNodeIndex );
249 }
250 m_IntersectionMeshes[iYarn].AddElement( itElements->ElementType, iNewIndices );
251 }
252}
253bool CAdjustMeshInterference::AdjustIntersections( vector<CMesh> &YarnMeshes )
254{
255 vector<CMeshIntersectionData>::iterator itIntersections;
256 vector<CMesh>::iterator itIntersectionMeshes;
257 int iNumIntersectPoints = 0, iIterations = 0;
258
259 // Find AABB of meshes so that can do quick initial test of whether to check for intersections
260 vector< pair<XYZ, XYZ> > MeshAABB;
261 for ( itIntersectionMeshes = m_IntersectionMeshes.begin(); itIntersectionMeshes != m_IntersectionMeshes.end(); itIntersectionMeshes++ )
262 {
263 pair<XYZ, XYZ> AABB = itIntersectionMeshes->GetAABB();
264 MeshAABB.push_back( AABB );
265 }
266
267 // Keep adjusting points until all within tolerance
268 do
269 {
270 iNumIntersectPoints = 0;
271 for ( itIntersections = m_Intersections.begin(); itIntersections != m_Intersections.end(); ++itIntersections )
272 {
273 if ( fabs(itIntersections->GetDepth()) < m_Tolerance ) // if already within tolerance move onto next point
274 continue;
275 for ( int i = 0; i < (int)m_IntersectionMeshes.size(); ++i )
276 {
277 if( itIntersections->GetYarn() == i || !BoundingBoxIntersect(MeshAABB[i].first, MeshAABB[i].second, MeshAABB[itIntersections->GetYarn()].first, MeshAABB[itIntersections->GetYarn()].second )) // Don't need to test against points in the same yarn
278 continue; // Don't need to check for intersections if AABBs don't intersect
279
280 vector< pair<double, XYZ> > IntersectionPoints;
281 int numIntersect = m_IntersectionMeshes[i].IntersectLine( itIntersections->GetPoint(), itIntersections->GetInterpPoint(), IntersectionPoints, make_pair(true,true) );
282 if ( numIntersect > 0 )
283 {
284 itIntersections->SetDepth( GetLength( itIntersections->GetPoint(), itIntersections->GetInterpPoint() )* IntersectionPoints[0].first );
285 if ( itIntersections->GetDepth() > m_Tolerance )
286 {
287 if ( !itIntersections->MoveNode(YarnMeshes[itIntersections->GetYarn()]) )
288 return false; // Intersection too large to correct
289 iNumIntersectPoints++;
290 break; // Found it - can move onto next point
291 }
292 }
293 }
294 }
295 ++iIterations;
296 TGLOG("Adjusting points: Iteration" << iIterations );
297 } while ( iNumIntersectPoints );
298 return true;
299}
300
301void CAdjustMeshInterference::SetNodeDisplacements( int iNumYarns, vector<CMesh> &YarnMeshes )
302{
303 vector<CMeshIntersectionData>::iterator itMeshData;
304 for ( int i = 0; i < iNumYarns; ++i )
305 {
306 vector<XYZ> YarnNodeDisplacements;
307 YarnNodeDisplacements.resize( YarnMeshes[i].GetNumNodes() );
308 m_NodeDisplacements.push_back( YarnNodeDisplacements );
309 }
310 for ( itMeshData = m_Intersections.begin(); itMeshData != m_Intersections.end(); ++itMeshData )
311 {
312 m_NodeDisplacements[itMeshData->GetYarn()][itMeshData->GetIndex()] = -itMeshData->GetDisplacement();
313
314 }
315}
316
318{
319 vector<CMeshIntersectionData>::iterator itIntersections;
320
321 for ( itIntersections = m_Intersections.begin(); itIntersections != m_Intersections.end(); ++itIntersections )
322 {
323 itIntersections->AdjustInterpolationNode(YarnMeshes[itIntersections->GetYarn()]);
324 }
325}
326
327void CAdjustMeshInterference::AdjustSectionMeshes( CTextile &Textile, vector<CMesh> &YarnMeshes )
328{
329 int iNumYarns = Textile.GetNumYarns();
330 const CDomain* pDomain = Textile.GetDomain();
331 vector< vector<int> > PolygonIndices;
332 vector< vector<int> > AdjustedPolygonIndices;
333
334
335 vector<CMesh>::iterator itMesh;
336 vector<CMesh>::iterator itTempMesh;
337
338
339 // Convert polygon element lists to vectors so that can use indices to access matching elements in original and adjusted meshes
340
341
342 for ( itMesh = YarnMeshes.begin(), itTempMesh = m_TempYarnMeshes.begin(); itMesh != YarnMeshes.end(), itTempMesh != m_TempYarnMeshes.end(); ++itMesh, ++itTempMesh )
343 {
344 vector<int> ElementIndices;
345 ElementIndices.clear();
346
347 itMesh->ConvertElementListToVector( CMesh::POLYGON, ElementIndices );
348 AdjustedPolygonIndices.push_back( ElementIndices );
349 ElementIndices.clear();
350 itTempMesh->ConvertElementListToVector( CMesh::POLYGON, ElementIndices );
351 PolygonIndices.push_back( ElementIndices );
352 }
353
354
355 for ( int i = 0; i < iNumYarns; ++i )
356 {
357 CYarn* Yarn = Textile.GetYarn(i);
358 vector<XYZ> Translations;
359 Translations = pDomain->GetTranslations( *Yarn );
360
361 const vector<CSlaveNode> &Nodes = Yarn->GetSlaveNodes(CYarn::SURFACE);
362 //vector<CSlaveNode> TempNodes = Nodes;
363 vector<CSlaveNode>::const_iterator itNodes;
364 CYarnSectionInterpPosition SectionInterp;
365
366 YARN_POSITION_INFORMATION YarnPositionInfo;
367 YarnPositionInfo.SectionLengths = Yarn->GetSectionLengths();
368
369 //sort( TempNodes.begin(), TempNodes.end() );
370
371 //list<int> &PolygonIndices = m_YarnMeshes[i].GetIndices( CMesh::POLYGON );
372 //list<int>::iterator itInt;
373 //for ( itNodes = TempNodes.begin(); itNodes != TempNodes.end(); ++itNodes )
374 for ( itNodes = Nodes.begin(); itNodes != Nodes.end(); ++itNodes )
375 {
376 YarnPositionInfo.iSection = itNodes->GetIndex();
377 double T = itNodes->GetT(); // Get position of slave node along section
378 YarnPositionInfo.dSectionPosition = T;
379 T = YarnPositionInfo.GetYarnPosition(); // Get position along yarn
380
381 vector<XYZ> SlaveNodePoints;
382 SlaveNodePoints = itNodes->GetSectionPoints();
383 int iPolygonIndex = -1;
384 int iOffsetIndex = -1;
385 int iTrans;
386
387 iPolygonIndex = FindMeshPolygonSection( SlaveNodePoints, m_TempYarnMeshes[i], PolygonIndices[i], Translations, iOffsetIndex, iTrans );
388 //iPolygonIndex = FindMeshPolygonSection( SlaveNodePoints, m_YarnMeshes[i], PolygonIndices[i], Translations, iOffsetIndex );
389 if ( iPolygonIndex == -1 )
390 {
391 // Add slave node section
392 SectionInterp.AddSection( T, CSectionPolygon( itNodes->Get2DSectionPoints() ));
393 }
394 else
395 {
396 vector<XYZ> SectionPoints;
397 vector<XYZ> TempPoints;
398 XYZ Point;
399
400 //vector<int> Indices = AdjustedPolygonIndices[i];
401 vector<int> Indices = PolygonIndices[i];
402 int iStartIndex = Indices[iPolygonIndex];
403 int j = 0;
404 // Get the nodes around the section at this point
405 // iOffsetIndex accounts for the difference in the start of the section mesh edge points and the points stored in the polygon
406 // sections because of the way the section meshes are generated
407 do {
408 Point = YarnMeshes[i].GetNode( Indices[iPolygonIndex++] );
409 //Point = TempMeshes[i].GetNode( Indices[iPolygonIndex++] );
410 if ( j < iOffsetIndex )
411 TempPoints.push_back(Point);
412 else
413 SectionPoints.push_back( Point );
414 j++;
415 } while ( Indices[iPolygonIndex] != iStartIndex );
416
417 /*Point = m_YarnMeshes[i].GetNode( Indices[iPolygonIndex++] );
418 if ( j < iOffsetIndex )
419 TempPoints.push_back( Point );
420 else
421 SectionPoints.push_back( Point );*/
422
423 SectionPoints.insert( SectionPoints.end(), TempPoints.begin(), TempPoints.end() );
424 //SectionPoints.push_back( SectionPoints[0] );
425
426 vector<XYZ>::iterator itSectionPoints;
427 for ( itSectionPoints = SectionPoints.begin(); itSectionPoints != SectionPoints.end(); ++itSectionPoints )
428 {
429 *(itSectionPoints) -= Translations[iTrans];
430 }
431
432 // Convert the 3D section points to local 2D ones
433 vector<XY> Points2D;
434 XYZ SlaveNodePos = itNodes->GetPosition();
435 XYZ Up = itNodes->GetUp();
436 XYZ Side = itNodes->GetSide();
437
438 for ( itSectionPoints = SectionPoints.begin(); itSectionPoints != SectionPoints.end(); ++itSectionPoints )
439 {
440 // Calculate the location of the point projected on to the cross section plane
441 XYZ Relative = *itSectionPoints - SlaveNodePos;
442 XY Point2D;
443 Point2D.x = DotProduct(Side, Relative);
444 Point2D.y = DotProduct(Up, Relative);
445 Points2D.push_back( Point2D );
446 }
447 // Create polygon section using 2D points and add to CYarnSectionInterpPosition
448 SectionInterp.AddSection( T, CSectionPolygon(Points2D) );
449 }
450 }
451
452 Yarn->AssignSection( SectionInterp );
453 }
454}
455
456int CAdjustMeshInterference::FindMeshPolygonSection( vector<XYZ> &SlaveNodePoints, CMesh &TempMesh, vector<int> &PolygonIndices, vector<XYZ> &Translations, int &OffsetIndex, int &iTrans )
457{
458 vector<XYZ>::iterator itSlavePoints;
459 vector< vector<XYZ> > TranslatedSections;
460 vector<XYZ>::iterator itTranslations;
461
462 // Create section points for each translation of section in the domain
463 for ( itTranslations = Translations.begin(); itTranslations != Translations.end(); ++itTranslations )
464 {
465 vector<XYZ> SectionPoints;
466 SectionPoints.clear();
467 for ( itSlavePoints = SlaveNodePoints.begin(); itSlavePoints != SlaveNodePoints.end(); ++itSlavePoints )
468 {
469 SectionPoints.push_back( *(itSlavePoints) + *(itTranslations) );
470 }
471 TranslatedSections.push_back( SectionPoints );
472 }
473
474
475 vector<int>::iterator itPolygonIndices;
476 vector<XYZ> PolygonPoints;
477 int iElementIndex = 0;
478
479 for ( itPolygonIndices = PolygonIndices.begin(); itPolygonIndices != PolygonIndices.end(); )
480 {
481 int StartIndex = *(itPolygonIndices);
482 int StartElementIndex = iElementIndex;
483 XYZ Point;
484 PolygonPoints.clear();
485 // Get the nodes around the section at this point
486 do {
487 int index = *(itPolygonIndices);
488 Point = TempMesh.GetNode( index );
489 //Point = TempMesh.GetNode( *(itPolygonIndices++) );
490 ++itPolygonIndices;
491 PolygonPoints.push_back( Point );
492 iElementIndex++;
493 } while ( *(itPolygonIndices)!= StartIndex );
494
495 ++itPolygonIndices;
496 ++iElementIndex;
497
498 //GetPolygonSectionPoints( itPolygonIndices, TempMesh, PolygonPoints );
499
500 OffsetIndex = CompareSections( TranslatedSections, PolygonPoints, iTrans );
501 if ( OffsetIndex >= 0 )
502 {
503 //return StartIndex;
504 return StartElementIndex;
505 }
506 }
507 return -1;
508}
509
510int CAdjustMeshInterference::CompareSections( vector< vector<XYZ> > &TranslatedSections, vector<XYZ> &PolygonPoints, int &iTrans )
511{
512 bool bMatch;
513 vector< vector<XYZ> >::iterator itTransSections;
514 double tolerance = 0.0000001; // Assign properly
515 int iStartIndex;
516 iTrans = 0;
517
518 for ( itTransSections = TranslatedSections.begin(); itTransSections != TranslatedSections.end(); ++ itTransSections )
519 {
520 vector<XYZ>::iterator itTransPoints;
521 vector<XYZ>::iterator itPolyPoints;
522 bMatch = true;
523
524 if ( itTransSections->size() != PolygonPoints.size() ) // Only try & compare sections with equal number of points
525 continue;
526 vector<XYZ> TransSection = *itTransSections;
527
528 // Find matching start point
529 iStartIndex = 0;
530 for( itPolyPoints = PolygonPoints.begin(); itPolyPoints != PolygonPoints.end(); ++itPolyPoints )
531 {
532 if( GetLength(TransSection[0] - *(itPolyPoints)) < tolerance )
533 break; // Found matching start point
534 ++iStartIndex;
535 }
536 if ( itPolyPoints == PolygonPoints.end() )
537 {
538 bMatch = false; // No matching points, go to next translation
539 ++iTrans;
540 continue;
541 }
542
543 for( itTransPoints = TransSection.begin(); itTransPoints != TransSection.end(); ++itTransPoints )
544 {
545 if ( GetLength((*itTransPoints) - (*itPolyPoints)) > tolerance )
546 {
547 bMatch = false;
548 break;
549 }
550 ++itPolyPoints;
551 if ( itPolyPoints == PolygonPoints.end() )
552 itPolyPoints = PolygonPoints.begin();
553 }
554 if ( bMatch )
555 return iStartIndex;
556 ++iTrans;
557 }
558 return -1;
559}
560
562{
563 m_Wedge = false;
564 m_InterpIndex = -1;
565}
566
568{
569}
570
572{
573 int interpNodeIndex = -1;
574 vector<int>::iterator itElementIndex;
575
576 if ( m_Elements.size() == 4 || m_Elements.size() == 3 ) // Size may be 3 where yarn has been cut at an angle on domain edge
577 {
578 // Find index to interpolate between. It's the one that occurs in all 4 elements
579
580 for( itElementIndex = m_Elements[0].Index.begin(); itElementIndex != m_Elements[0].Index.end(); ++itElementIndex )
581 {
582 if ( *itElementIndex == m_Index ) // Don't need to check for the one you're looking for!
583 continue;
584 vector<ELEMENT_INDICES>::iterator itElementArrays = m_Elements.begin()+1;
585 while ( itElementArrays != m_Elements.end() // Will drop out of loop if didn't find index in one of arrays
586 && find(itElementArrays->Index.begin(), itElementArrays->Index.end(), *itElementIndex) != itElementArrays->Index.end() )
587 {
588 itElementArrays++;
589 }
590 if ( itElementArrays == m_Elements.end() )
591 {
592 break; // If got to end of arrays then have found index in all of them - it's the one
593 }
594 }
595 interpNodeIndex = *itElementIndex;
596 }
597 else if ( m_Elements.size() == 2 || m_Elements.size() == 1 )
598 {
599 // When 2 elements need to find the common index at the same end of the element
600 // Occurs when node at end of mesh
601 bool ElementEnd[2];
602
603 for ( int i = 0; i < (int)m_Elements.size(); ++i ) // Find which end of the elements the node is
604 {
605 int j;
606 for (itElementIndex = m_Elements[i].Index.begin(), j = 0; itElementIndex != m_Elements[i].Index.end(); ++itElementIndex, ++j )
607 {
608 if ( *itElementIndex == m_Index )
609 {
610 if ( j < CMesh::GetNumNodes( m_Elements[i].ElementType )/2 )
611 ElementEnd[i] = FIRST_HALF;
612 else
613 ElementEnd[i] = SECOND_HALF;
614 break;
615 }
616 }
617 }
618
619 // Find iterator start & end for appropriate half of element
620 vector<int>::iterator itElementStart[2], itElementEnd[2];
621 for ( int i = 0; i < (int)m_Elements.size(); ++i )
622 {
623 int iNumNodes = CMesh::GetNumNodes(m_Elements[i].ElementType)/2;
624 itElementStart[i] = m_Elements[i].Index.begin() + ElementEnd[i] * iNumNodes;
625 if ( ElementEnd[i] == FIRST_HALF )
626 itElementEnd[i] = m_Elements[i].Index.begin() + iNumNodes;
627 else
628 itElementEnd[i] = m_Elements[i].Index.end();
629 }
630
631 if( m_Elements.size() == 2 )
632 {
633
634
635 // Find 2nd node which is at same end of both elements as search node
636 for ( itElementIndex = itElementStart[0]; itElementIndex != itElementEnd[0]; ++itElementIndex )
637 {
638 if ( *itElementIndex == m_Index ) // Don't search for the one already know
639 continue;
640
641 if ( find(itElementStart[1], itElementEnd[1], *itElementIndex) != itElementEnd[1] )
642 {
643 break; // Found it!
644 }
645 }
646 interpNodeIndex = *itElementIndex;
647 }
648 else if ( m_Elements.size() == 1 )
649 {
650 TGLOG( "Number of elements = 1. Need to test this code" );
651 int Index1 = -1;
652 int PolygonIndex = -1;
653 int i = 0;
654 for ( itElementIndex = itElementStart[0] ; itElementIndex != itElementEnd[0]; ++itElementIndex )
655 {
656 if ( *itElementIndex == m_Index )
657 {
658 Index1 = i;
659 continue;
660 }
661 if ( *itElementIndex == m_PolygonPoints[0] || *itElementIndex == m_PolygonPoints[2] )
662 {
663 PolygonIndex = i;
664 continue;
665 }
666 ++i;
667 }
668
669 if ( m_Wedge )
670 {
671 for ( int i = 0; i < 2; ++i )
672 {
673 if ( i != Index1 && i != PolygonIndex )
674 {
675 interpNodeIndex = *(itElementStart[0]+i);
676 break;
677 }
678 }
679 }
680 else
681 {
682 int iNumNodes = CMesh::GetNumNodes(m_Elements[0].ElementType)/2;
683 if ( PolygonIndex > Index1 )
684 {
685 interpNodeIndex = *(itElementStart[0]+((Index1+iNumNodes-1)%(iNumNodes)));
686 }
687 else
688 {
689 interpNodeIndex = *( itElementStart[0]+((Index1+1)%(iNumNodes)));
690 }
691 }
692 }
693 }
694
695
696 if ( interpNodeIndex != -1 )
697 {
698 m_InterpPoint = YarnMesh.GetNode(interpNodeIndex);
699 SetInterpIndex( interpNodeIndex );
700 return true;
701 }
702 TGERROR("Find interpolation node, number of elements = " << m_Elements.size() );
703 return false;
704}
705
707{
708 XYZ NewPoint;
709 XYZ Offset;
710 double absDepth = fabs(m_Depth);
711 double length = GetLength( m_Point, m_InterpPoint );
712 double CheckLength = length;
713 if ( m_Wedge ) // If wedge don't want to get case where two corners of element moved to same point
714 {
715 double MinLength = 0.02 * GetLength( m_StartPoint, m_InterpPoint );
716 CheckLength -= MinLength;
717 }
718 if ( (absDepth * 0.5) > CheckLength )
719 {
720 TGERROR("Intersection depth in yarn " << m_Yarn << " too large for adjustment");
721 return false;
722 }
723
724 Offset.x = ((m_InterpPoint.x - m_Point.x) * absDepth * 0.5 / length );
725 Offset.y = ((m_InterpPoint.y - m_Point.y) * absDepth * 0.5 / length );
726 Offset.z = ((m_InterpPoint.z - m_Point.z) * absDepth * 0.5 / length );
727 NewPoint = m_Point + Offset;
728 /*NewPoint.x = m_Point.x + Offset.x;
729 NewPoint.y = m_Point.y + Offset.y;
730 NewPoint.z = m_Point.z + Offset.z;*/
731
732 YarnMesh.SetNode(m_Index, NewPoint );
733 m_Point = NewPoint;
734 if ( m_BoundaryPairIndex != -1 )
735 {
736 NewPoint = YarnMesh.GetNode( m_BoundaryPairIndex );
737 NewPoint += Offset;
738 YarnMesh.SetNode( m_BoundaryPairIndex, NewPoint );
739 }
740 return true;
741}
742
743void CMeshIntersectionData::FindElements( vector<int> &IndexArray, CMesh::ELEMENT_TYPE ElementType )
744{
745 vector<int>::iterator itIndexArray = IndexArray.begin();
746 ELEMENT_INDICES Element;
747 Element.ElementType = ElementType;
748
749 while ( itIndexArray != IndexArray.end() )
750 {
751 itIndexArray = find( itIndexArray, IndexArray.end(), m_Index );
752 if ( itIndexArray != IndexArray.end() ) // Found an entry
753 {
754 int iIndex = (int)(itIndexArray - IndexArray.begin());
755
756 vector<int>::iterator itStartVertex = itIndexArray - (iIndex % CMesh::GetNumNodes(ElementType));
757 // Add the block of indices for the element
758 Element.Index.assign( itStartVertex, itStartVertex + CMesh::GetNumNodes(ElementType) );
759 m_Elements.push_back( Element );
760 if ( ElementType == CMesh::WEDGE )
761 m_Wedge = true;
762 Element.Index.clear();
763 itIndexArray++; // Move to next item to continue searching
764 }
765 }
766}
767
769{
770 list<int>::iterator itPolygons;
771 int iFoundIndex = -1;
772
773 for ( itPolygons = Polygons.begin(); itPolygons != Polygons.end(); )
774 {
775 int StartIndex = *itPolygons;
776 vector<int> Polygon;
777 int i = 0;
778 do{
779 Polygon.push_back( *itPolygons );
780 if ( *itPolygons == m_Index )
781 iFoundIndex = i;
782 ++itPolygons;
783 ++i;
784 } while ( (*itPolygons) != StartIndex );
785 ++itPolygons;
786 if ( iFoundIndex != -1 )
787 {
788 m_PolygonPoints[1] = Polygon[iFoundIndex];
789 if ( iFoundIndex == 0 )
790 m_PolygonPoints[0] = Polygon[i-1]; // Point before end
791 else
792 m_PolygonPoints[0] = Polygon[iFoundIndex-1];
793 if ( iFoundIndex == i-1 )
794 m_PolygonPoints[2] = Polygon[0];
795 else
796 m_PolygonPoints[2] = Polygon[iFoundIndex+1];
797 break;
798 }
799 }
800}
801
803{
804 XYZ Offset;
805 XYZ NewPoint;
806 if ( m_InterpIndex == -1 )
807 return;
808
809 Offset = m_StartPoint - m_Point;
810
811 NewPoint = YarnMesh.GetNode( m_InterpIndex ); // Get node rather than offsetting interpPoint to get correct offsets
812 // on points used more than once
813 NewPoint -= Offset/2.0;
814
815 YarnMesh.SetNode( m_InterpIndex, NewPoint );
816
817 // Sort out boundaries
818 /*if ( m_BoundaryPairIndex != -1 )
819 {
820 NewPoint = YarnMesh.GetNode( m_BoundaryPairIndex );
821 NewPoint += Offset;
822 YarnMesh.SetNode( m_BoundaryPairIndex, NewPoint );
823 }*/
824}
825
#define TOL
#define SECOND_HALF
#define FIRST_HALF
#define TGERROR(MESSAGE)
Macros used to report the file name and line number to the TexGenError and TexGenLog functions.
Definition: Logger.h:29
#define TGLOG(MESSAGE)
Definition: Logger.h:36
bool AdjustIntersections(vector< CMesh > &YarnMeshes)
Iteratively refines intersections until within tolerance.
void AdjustSectionMeshes(CTextile &Textile, vector< CMesh > &YarnMeshes)
Adjust yarns to interpolate between section meshes and change these to reflect intersection adjustmen...
int CompareSections(vector< vector< XYZ > > &TranslatedSections, vector< XYZ > &PolygonPoints, int &iTrans)
void AdjustInterpolationNodes(vector< CMesh > &YarnMeshes)
Final adjustment of interpolation nodes to even out mesh.
bool AdjustMesh(CTextile &Textile, vector< CMesh > &YarnMeshes, double Tolerance)
Top level function to adjust nodes on all yarns.
bool AdjustInitialIntersections(vector< CMesh > &YarnMeshes)
Takes the individual yarn meshes and corrects intersections based on Textile.DetectInterference()
void AdjustTextileMesh(CTextile &Textile, double Tolerance=0.0000001)
Adjust mesh interference for whole textile by adjusting nodes.
void SetNodeDisplacements(int iNumYarns, vector< CMesh > &YarnMeshes)
bool CheckInitialIntersections(CTextile &Textile, vector< CMesh > &YarnMeshes)
Calls Textile.DetectInterference and sets up MeshIntersectionData base on intersection depths.
int FindMeshPolygonSection(vector< XYZ > &SlaveNodePoints, CMesh &TempMesh, vector< int > &PolygonIndices, vector< XYZ > &Translations, int &OffsetIndex, int &iTrans)
Find the newly created polygon sections in the volume mesh.
vector< vector< XYZ > > m_NodeDisplacements
void AddIntersectElementsToMesh(const vector< ELEMENT_INDICES > &Elements, int iYarn, CMesh &YarnMesh)
Creates mesh for each yarn containing elements with intersection nodes.
vector< CMeshIntersectionData > m_Intersections
Abstract base class representing the domain in which a textile cell may lie.
Definition: Domain.h:34
vector< XYZ > GetTranslations(const CYarn &Yarn) const
Get the translation vectors necessary to fully fill the domain.
Definition: Domain.cpp:83
Defines the nodes and elements of a surface or volume mesh.
Definition: Mesh.h:58
int GetNumNodes() const
Return the number of nodes.
Definition: Mesh.cpp:2646
const XYZ & GetNode(int iIndex) const
Get the node with given ID.
Definition: Mesh.cpp:2636
ELEMENT_TYPE
Each element type is represented by a unique integer value.
Definition: Mesh.h:66
@ POLYGON
Definition: Mesh.h:76
void SetNode(int iIndex, XYZ Node)
Set the node at given index.
Definition: Mesh.cpp:2630
Class which holds the information related to each intersection point, used for adjusting the mesh.
bool FindInterpolationNode(CMesh &YarnMesh)
Finds the appropriate node in the elements to interpolate towards.
void FindElements(vector< int > &IndexArray, CMesh::ELEMENT_TYPE ElementType)
Given node index, find all elements containing that node.
void FindPolygonPoints(list< int > &Polygons)
Find surface point in polygon & points on either side.
void AdjustInterpolationNode(CMesh &YarnMesh)
Make final adjustments to interpolation nodes to even out elements.
vector< ELEMENT_INDICES > m_Elements
bool MoveNode(CMesh &YarnMesh)
Move node by 0.5 * intersection depth towards the interpolation node.
Creates a polygonal section, where a list of points are given to form the closed polygon.
Represents a textile cell containing yarns.
Definition: Textile.h:39
const CDomain * GetDomain() const
Definition: Textile.h:287
int GetNumYarns() const
Definition: Textile.cpp:704
void AddVolumeToMesh(vector< CMesh > &YarnMeshes, bool bTrimToDomain=false)
Create volume mesh for each yarn in this textile and add to a vector of meshes.
Definition: Textile.cpp:301
const CYarn * GetYarn(int iIndex) const
Definition: Textile.cpp:693
int DetectInterference(vector< float > &DistanceToSurface, vector< int > &YarnIndex, bool bTrimToDomain, CMesh *pInterferingPoints=NULL)
Find out if any of the yarns are interfering with each other.
Definition: Textile.cpp:577
Represents a yarn consisting of master nodes, section and interpolation function.
Definition: Yarn.h:49
void AssignSection(const CYarnSection &YarnSection)
Assign a section to the yarn.
Definition: Yarn.cpp:649
const vector< CSlaveNode > & GetSlaveNodes(BUILD_TYPE Usage) const
Get the slave nodes and build them if necessary.
Definition: Yarn.cpp:1749
@ SURFACE
Definition: Yarn.h:60
const vector< XYZ > & GetRepeats() const
Definition: Yarn.h:448
vector< double > GetSectionLengths() const
Definition: Yarn.h:453
Interpolate sections between arbritrary positions along the length of the yarn.
void AddSection(double dPosition, const CSection &Section)
Add a section at a specific point along the path of the yarn.
Namespace containing a series of customised math operations not found in the standard c++ library.
double GetLength(const XYZ &Point1, const XYZ &Point2)
Get the length between two points.
Definition: mymath.h:540
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.
Definition: Misc.h:50
bool BoundingBoxIntersect(const XYZ &BBox1Min, const XYZ &BBox1Max, const XYZ &BBox2Min, const XYZ &BBox2Max, double dTolerance=0)
Find if two AABBs intersect with given tolerance.
Definition: mymath.h:970
double DotProduct(const XYZ &left, const XYZ &right)
Get the dot product of two vectors.
Definition: mymath.h:512
CMesh::ELEMENT_TYPE ElementType
Struct for representing points in 2D space.
Definition: mymath.h:103
double x
Definition: mymath.h:104
double y
Definition: mymath.h:104
Struct for representing points in 3D space.
Definition: mymath.h:56
double z
Definition: mymath.h:57
double x
Definition: mymath.h:57
double y
Definition: mymath.h:57
Structure used to represent the position along the length of a yarn.
Definition: YarnSection.h:36
double dSectionPosition
This variables varies linearly with distance from 0 to 1 from the start to the end of the current lin...
Definition: YarnSection.h:37
int iSection
This variable represents the index of the current section (where a section is defined as the part bet...
Definition: YarnSection.h:38
vector< double > SectionLengths
This contains a list of lengths representing the length of each section.
Definition: YarnSection.h:39