TexGen
TextileLayered.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2014 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"
21#include "TextileLayered.h"
22
23using namespace TexGen;
24
25#define START_DIST -1.0e+6
26
27CTextileLayered::CTextileLayered()
28: m_iResolution(40)
29{
30}
31
33{
34}
35
37: CTextile(Element)
38{
39 Element.Attribute("Resolution", &m_iResolution);
40 FOR_EACH_TIXMLELEMENT(pLayer, Element, "Layer")
41 {
42 vector<int> Indices;
43 FOR_EACH_TIXMLELEMENT(pYarn, *pLayer, "Yarn")
44 {
45 Indices.push_back(valueify<int>(pYarn->Attribute("yarnindex")));
46 }
47 m_LayerYarnIndices.push_back(Indices);
48 }
49 FOR_EACH_TIXMLELEMENT(pOffset, Element, "Offset")
50 {
51 m_LayerOffset.push_back(valueify<XY>(pOffset->Attribute("value")));
52 }
53}
54
55void CTextileLayered::PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
56{
57 CTextile::PopulateTiXmlElement(Element, OutputType);
58
59 Element.SetAttribute("Resolution", m_iResolution);
60
61 for (int i=0; i<(int)m_LayerYarnIndices.size(); ++i)
62 {
63 TiXmlElement Layer("Layer");
64 //YYarns.SetAttribute("index", i);
65 for (int j=0; j<(int)m_LayerYarnIndices[i].size(); ++j)
66 {
67 TiXmlElement Yarn("Yarn");
68 Yarn.SetAttribute("yarnindex", m_LayerYarnIndices[i][j]);
69 Layer.InsertEndChild(Yarn);
70 }
71 Element.InsertEndChild(Layer);
72 }
73 vector<XY>::iterator itXY;
74 for (itXY = m_LayerOffset.begin(); itXY!=m_LayerOffset.end(); ++itXY)
75 {
76 TiXmlElement Offset("Offset");
77 Offset.SetAttribute("value", stringify(*itXY));
78 Element.InsertEndChild(Offset);
79 }
80}
81
82void CTextileLayered::AddLayer(CTextile& Textile, XYZ& Offset)
83{
84 if ( Textile.GetType() == "CTextileLayered" )
85 {
86 const vector< vector<int> > YarnIndices = dynamic_cast<CTextileLayered*>(&Textile)->GetLayerYarnIndices();
87 vector<XY> Offsets = dynamic_cast<CTextileLayered*>(&Textile)->GetOffsets();
88 vector< vector<int> >::const_iterator itYarnIndices;
89 int i;
90
91 // Add each layer in turn to the new layered textile
92 for( itYarnIndices = YarnIndices.begin(), i = 0; itYarnIndices != YarnIndices.end(); ++itYarnIndices, ++i )
93 {
94 vector<int>::const_iterator itIndex;
95 vector<CYarn> Yarns;
96 for ( itIndex = itYarnIndices->begin(); itIndex != itYarnIndices->end(); ++itIndex )
97 {
98 CYarn* pYarn = Textile.GetYarn( *itIndex );
99 Yarns.push_back( *pYarn );
100 }
101 XY LayerOffset(Offsets[i].x, Offsets[i].y);
102 AddLayer( Yarns, Offset );
103 m_LayerOffset.push_back( LayerOffset );
104 }
105 }
106 else
107 {
108 vector<CYarn> &Yarns = Textile.GetYarns();
109 AddLayer( Yarns, Offset );
110 m_LayerOffset.push_back( XY(Offset.x, Offset.y) );
111 }
112}
113
114void CTextileLayered::AddLayer( vector<CYarn> &Yarns, XYZ& Offset )
115{
116 vector<CYarn>::iterator itYarn;
117 vector<int> YarnIndices; // Vector of yarn indices (within the textile) for the layer
118 XY LayerOffset(Offset.x, Offset.y);
119
120 // Add each yarn with specified offset
121 for ( itYarn = Yarns.begin(); itYarn != Yarns.end(); ++itYarn )
122 {
123 CYarn Yarn = *itYarn;
124 Yarn.Translate( Offset );
125
126 int index = AddYarn( Yarn );
127 YarnIndices.push_back( index );
128 }
129 m_LayerYarnIndices.push_back( YarnIndices );
130}
131
133{
134 return "LayeredTextile(Layers:" + stringify(m_LayerYarnIndices.size()) + ")";
135}
136
137void CTextileLayered::SetOffsets( vector<XY> &Offsets )
138{
139 int size = m_LayerYarnIndices.size();
140 if ( Offsets.size() != size )
141 {
142 TGERROR("Can't assign offsets: number of offsets does not match number of layers");
143 return;
144 }
145
146 if ( m_LayerOffset.empty() )
147 {
148 m_LayerOffset.assign( Offsets.begin(), Offsets.end() );
150 }
151 else
152 {
153 vector<XY> MoveOffset;
154 // Calculate relative offset and translate yarns by that offset
155 for ( int i = 0; i < size; ++i )
156 {
157 MoveOffset.push_back( Offsets[i] - m_LayerOffset[i] );
158 }
159 ApplyOffsets( MoveOffset );
160 // Set offsets to new values
161 m_LayerOffset.assign( Offsets.begin(), Offsets.end() );
162 }
163}
164
165void CTextileLayered::SetRelativeOffsets( vector<XY> &Offsets )
166{
167 int size = m_LayerYarnIndices.size();
168 if ( Offsets.size() != size )
169 {
170 TGERROR("Can't assign offsets: number of offsets does not match number of layers");
171 return;
172 }
173
174 if ( m_LayerOffset.empty() )
175 {
176 m_LayerOffset.assign( Offsets.begin(), Offsets.end() );
178 }
179 else
180 {
181 vector<XY> TotalOffset;
182 // Calculate relative offset and translate yarns by
183 for ( int i = 0; i < size; ++i )
184 {
185 TotalOffset.push_back( Offsets[i] + m_LayerOffset[i] );
186 }
187 ApplyOffsets( Offsets );
188 // Set offsets to new values
189 m_LayerOffset.assign( TotalOffset.begin(), TotalOffset.end() );
190 }
191}
192
194{
195 int size = m_LayerYarnIndices.size();
196 vector<XY> Offsets;
197 XY SumOffset;
198
199 for( int i = 0; i < size; ++i )
200 {
201 Offsets.push_back( SumOffset );
202 SumOffset += Offset;
203 }
204
205 SetOffsets( Offsets );
206}
207
208void CTextileLayered::ApplyOffsets( vector<XY> &Offsets )
209{
210 int iNumLayers = m_LayerYarnIndices.size();
211 if ( Offsets.size() != iNumLayers )
212 {
213 TGERROR("Can't apply offsets: number of offsets does not match number of layers");
214 }
215
216 for ( int i = 0; i < iNumLayers; ++i )
217 {
218 vector<int>::iterator itIndices;
219 XYZ Offset( Offsets[i].x, Offsets[i].y, 0 );
220 ApplyLayerOffset( Offset, i );
221 }
222}
223
224void CTextileLayered::ApplyLayerOffset( XYZ &Offset, int iLayer )
225{
226 if ( iLayer < 0 || iLayer >= m_LayerYarnIndices.size() )
227 return;
228
229 vector<int>::iterator itIndices;
230
231 for ( itIndices = m_LayerYarnIndices[iLayer].begin(); itIndices != m_LayerYarnIndices[iLayer].end(); ++itIndices )
232 {
233 CYarn* Yarn = GetYarn( *itIndices );
234 Yarn->Translate( Offset );
235 }
236}
237
239{
240 return (int)m_LayerYarnIndices.size();
241}
242
244{
245 if ( !m_pDomain )
246 {
247 TGERROR( "Cannot nest layers: no domain specified" );
248 return;
249 }
250 int iNumLayers = (int)m_LayerYarnIndices.size();
251 vector<CMesh> LayerMeshes;
252 int iNumX, iNumY;
253 // Create mesh for each layer
254 iNumX = GetLayerMeshes( LayerMeshes );
255 iNumY = iNumX;
256
257#ifdef _DEBUG
258 int i = 0;
259 vector<CMesh>::iterator itMeshes;
260 for ( itMeshes = LayerMeshes.begin(); itMeshes != LayerMeshes.end(); ++itMeshes )
261 {
262 string str = "LayerMeshes" + stringify(i++);
263 itMeshes->SaveToVTK(str.c_str() );
264 }
265#endif
266
267 pair<XYZ,XYZ> AABB = m_pDomain->GetMesh().GetAABB();
268 double XInc = (AABB.second.x - AABB.first.x) / iNumX;
269 double YInc = (AABB.second.y - AABB.first.y) / iNumY;
270
271 vector< vector<pair<double,double> > > LayerIntersections;
272 LayerIntersections.resize((iNumX+1) * (iNumY+1));
273 XY Pos(AABB.first.x, AABB.first.y);
274 double Height = GetLength( XYZ(Pos.x, Pos.y, AABB.first.z), XYZ(Pos.x, Pos.y, AABB.second.z) );
275
276 // Find intersections of grid of vertical lines with yarn meshes
277 for ( int j = 0; j <= iNumY; ++j )
278 {
279 for ( int i = 0; i <= iNumX; ++i )
280 {
281 vector<CMesh>::iterator itMeshes;
282 XYZ P1(Pos.x,Pos.y,AABB.first.z);
283 XYZ P2(Pos.x,Pos.y,AABB.second.z);
284 for ( itMeshes = LayerMeshes.begin(); itMeshes != LayerMeshes.end(); ++itMeshes )
285 {
286 vector<pair<double,XYZ> > IntersectionPoints;
287 int iNum = itMeshes->IntersectLine(P1, P2, IntersectionPoints, make_pair(true,true));
288 if ( iNum >= 2 )
289 {
290 pair<double,double> Intersects;
291 Intersects.first = IntersectionPoints[0].first * Height; // Bottom mesh intersection for layer
292 Intersects.second = IntersectionPoints[iNum-1].first * Height; // Top mesh intersection for layer
293 LayerIntersections[j*(iNumX+1)+i].push_back(Intersects);
294 }
295 else
296 {
297 LayerIntersections[j*(iNumX+1)+i].push_back(make_pair(START_DIST,START_DIST)); // Set to -1 if no intersections in layer
298 }
299 }
300 Pos.x += XInc;
301 }
302 Pos.y += YInc;
303 Pos.x = AABB.first.x;
304 }
305
306 vector<double> MinDist(iNumLayers-1,START_DIST);
307
308 // Find the smallest distance between adjacent layers
309 for ( int j = 0; j < LayerIntersections.size(); ++j )
310 {
311 for ( int i = 0; i < LayerIntersections[j].size()-1; ++i )
312 {
313 if ( LayerIntersections[j][i].first > 0.0 && LayerIntersections[j][i+1].second > 0.0 )
314 {
315 double dist = LayerIntersections[j][i+1].first - LayerIntersections[j][i].second;
316 /*if ( MinDist[i] < 0.0 )
317 {
318 MinDist[i] = dist;
319 }*/
320 //else if ( dist < MinDist[i] )
321 if ( MinDist[i] == START_DIST || dist < MinDist[i] )
322 {
323 MinDist[i] = dist;
324 }
325 }
326 }
327 }
328
329 // Move layers together by smallest distances between layers
330 XYZ Offset;
331 for ( int i = 1; i < iNumLayers; ++i )
332 {
333 Offset.z -= MinDist[i-1];
334 ApplyLayerOffset( Offset, i );
335 }
336
337 // Resize domain
338 PLANE Plane;
339 CDomainPlanes *DomainPlanes = (CDomainPlanes*)&(*m_pDomain); // Convoluted - need to see if better way of doing this
340 XYZ RefPlane(0,0,-1);
341 int index = DomainPlanes->GetPlane( RefPlane, Plane );
342 Plane.d -= Offset.z;
343 DomainPlanes->SetPlane( index, Plane );
344 m_bNeedsBuilding = true;
345}
346
348{
349 if ( !m_pDomain )
350 {
351 TGERROR( "Cannot nest layers: no domain specified" );
352 return;
353 }
354 int iNumLayers = (int)m_LayerYarnIndices.size();
355 vector<CMesh> LayerMeshes;
356 int iNumX, iNumY;
357 // Initial grid resolution is based on number of slave nodes
358 int iGridRes = GetLayerMeshes( LayerMeshes );
359
360#ifdef _DEBUG
361 int i = 0;
362 vector<CMesh>::iterator itMeshes;
363 for ( itMeshes = LayerMeshes.begin(); itMeshes != LayerMeshes.end(); ++itMeshes )
364 {
365 string str = "LayerMeshes" + stringify(i++);
366 itMeshes->SaveToVTK(str.c_str() );
367 }
368#endif
369
370 pair<XYZ,XYZ> AABB = m_pDomain->GetMesh().GetAABB();
371
372 vector<XY> Repeats;
373 GetLayerRepeats( Repeats );
374
375 vector<XY> Offsets;
376 XY Offset;
377 Offsets.push_back( Offset );
378
379 // Store the offset position which gives the minimum distance between each pair of layers
380 vector<pair<int,double> > MinDist(iNumLayers-1,make_pair(-1,START_DIST));
381
382 // Find min dist for each pair of layers
383 for ( int iLayer = 0; iLayer < LayerMeshes.size()-1; ++iLayer )
384 {
385
386 double X1 = Repeats[iLayer].x;
387 double X2 = Repeats[iLayer+1].x;
388 double Y1 = Repeats[iLayer].y;
389 double Y2 = Repeats[iLayer+1].y;
390
391 // Need to have integer number of offsets for the algorithm to work
392 double gcd = GreatestCommonDenominator( X1, X2 );
393 int fact = (int)(iGridRes/((AABB.second.x - AABB.first.x)/gcd));
394 double XInc = gcd/fact;
395
396 gcd = GreatestCommonDenominator( Y1, Y2 );
397 fact = (int)(iGridRes/((AABB.second.y - AABB.first.y)/gcd));
398 double YInc = gcd/fact;
399
400 iNumX = (AABB.second.x - AABB.first.x)/XInc;
401 iNumY = (AABB.second.y - AABB.first.y)/YInc;
402
403 // Set the upper and lower intersection points of the mesh with a grid of vertical lines for each of the pair of meshes
404 vector< vector<pair<double,double> > > LayerIntersections;
405 LayerIntersections.resize((iNumX+1) * (iNumY+1));
406 XY Pos(AABB.first.x, AABB.first.y);
407 double Height = GetLength( XYZ(Pos.x, Pos.y, AABB.first.z), XYZ(Pos.x, Pos.y, AABB.second.z) );
408
409 for ( int j = 0; j <= iNumY; ++j )
410 {
411 for ( int i = 0; i <= iNumX; ++i )
412 {
413 vector<CMesh>::iterator itMeshes;
414 XYZ P1(Pos.x,Pos.y,AABB.first.z);
415 XYZ P2(Pos.x,Pos.y,AABB.second.z);
416
417 for ( int k = 0; k < 2; ++k )
418 {
419 vector<pair<double,XYZ> > IntersectionPoints;
420 int iNum = LayerMeshes[iLayer+k].IntersectLine(P1, P2, IntersectionPoints, make_pair(true,true));
421 if ( iNum >= 2 )
422 {
423 pair<double,double> Intersects;
424 Intersects.first = IntersectionPoints[0].first * Height;
425 Intersects.second = IntersectionPoints[iNum-1].first * Height;
426 LayerIntersections[j*(iNumX+1)+i].push_back(Intersects);
427 }
428 else
429 {
430 LayerIntersections[j*(iNumX+1)+i].push_back(make_pair(START_DIST,START_DIST));
431 }
432 }
433 Pos.x += XInc;
434 }
435 Pos.y += YInc;
436 Pos.x = AABB.first.x;
437 }
438
439 // Which mesh is offset depends on which has the larger repeat
440 int XSize = (int)(min(Repeats[iLayer].x, Repeats[iLayer+1].x)/XInc);
441 int YSize = (int)(min(Repeats[iLayer].y, Repeats[iLayer+1].y)/YInc);
442 bool bOffsetTop = Repeats[iLayer].x < Repeats[iLayer+1].x ? true : false;
443
444 // Move the layers relative to each other for each of the set of grid positions and find minimum distance between the meshes
445 for ( int j = 0; j < (int)YSize; ++j )
446 {
447 for ( int i = 0; i < (int)XSize; ++i )
448 {
449 GetOffsetMinDist(i, j, iLayer, LayerIntersections, MinDist, iNumX+1, iNumY+1, XSize, YSize, bOffsetTop);
450 }
451 }
452
453 int X = MinDist[iLayer].first % (iNumX+1);
454 int Y = (MinDist[iLayer].first - X) / (iNumX+1);
455
456 if ( bOffsetTop )
457 {
458 X *= -1.0;
459 Y *= -1.0;
460 }
461 Offset.x += X * XInc;
462 Offset.y += Y * YInc;
463 Offsets.push_back( Offset );
464 }
465
466 SetRelativeOffsets( Offsets );
467
468 // Move layers together by smallest distances between layers
469 XYZ ZOffset;
470 for ( int i = 1; i < iNumLayers; ++i )
471 {
472 TGLOG("Mindist = " << MinDist[i-1].second );
473 ZOffset.z -= MinDist[i-1].second;
474 ApplyLayerOffset( ZOffset, i );
475 }
476
477 PLANE Plane;
478 CDomainPlanes *DomainPlanes = (CDomainPlanes*)&(*m_pDomain); // Convoluted - need to see if better way of doing this
479 XYZ RefPlane(0,0,-1);
480 int index = DomainPlanes->GetPlane( RefPlane, Plane );
481 Plane.d -= ZOffset.z;
482 DomainPlanes->SetPlane( index, Plane );
483 m_bNeedsBuilding = true;
484}
485
486void CTextileLayered::GetOffsetMinDist( int iOffset, vector< vector<pair<double,double> > >& LayerIntersections, vector<pair<int,double> >& MinDist, int iNumX, int iNumY)
487{
488 vector<double> OffsetMinDist(MinDist.size(),START_DIST);
489
490 int incX = iOffset % iNumX;
491 int incY = (iOffset - incX) / iNumX;
492 for ( int j = 0; j < iNumY; ++j )
493 {
494 for ( int i = 0; i < iNumX; ++i )
495 {
496 int iInd = j*iNumX+i;
497 int iOffsetInd = ((j+incY)%iNumY)*iNumX + ((i+incX)%iNumX);
498 for ( int LayerInd = 0; LayerInd < LayerIntersections[iInd].size()-1; ++LayerInd )
499 {
500 if ( LayerIntersections[iInd][LayerInd].second > 0.0 && LayerIntersections[iOffsetInd][LayerInd+1].first > 0.0 )
501 {
502 double dist = LayerIntersections[iOffsetInd][LayerInd+1].first - LayerIntersections[iInd][LayerInd].second;
503 if ( OffsetMinDist[LayerInd] == START_DIST || dist < OffsetMinDist[LayerInd] )
504 {
505 OffsetMinDist[LayerInd] = dist;
506 }
507 }
508 }
509 }
510 }
511
512 // Check if min dist for this offset is greater than previous stored for each inter layer gap (ie will give greater nesting)
513 for ( int index = 0; index < MinDist.size(); ++index ) // size of MinDist = number of layers - 1
514 {
515 if ( MinDist[index].second == START_DIST || OffsetMinDist[index] > MinDist[index].second )
516 {
517 MinDist[index].second = OffsetMinDist[index];
518 MinDist[index].first = iOffset;
519 }
520 }
521}
522
523void CTextileLayered::GetOffsetMinDist( int x, int y, int iLayer, vector< vector<pair<double,double> > >& LayerIntersections, vector<pair<int,double> >& MinDist, int iNumX, int iNumY, int XSize, int YSize, bool bOffsetTop)
524{
525 //vector<double> OffsetMinDist(MinDist.size(),START_DIST);
526 double OffsetMinDist = START_DIST;
527
528 //int incX = x % iNumX;
529 //int incY = y % iNumY;
530 /*for ( int j = 0; j < iNumY; ++j )
531 {
532 for ( int i = 0; i < iNumX; ++i )
533 {
534 int iInd = j*iNumX+i;
535 int iOffsetInd = ((j+y)%iNumY)*iNumX + ((i+x)%iNumX);
536
537 if ( LayerIntersections[iInd][Layer].second > 0.0 && LayerIntersections[iOffsetInd][Layer+1].first > 0.0 )
538 {
539 double dist = LayerIntersections[iOffsetInd][Layer+1].first - LayerIntersections[iInd][Layer].second;
540 if ( OffsetMinDist[Layer] == START_DIST || dist < OffsetMinDist[Layer] )
541 {
542 OffsetMinDist[Layer] = dist;
543 }
544 }
545
546 }
547 }*/
548 for ( int j = 0; j < iNumY; ++j )
549 {
550 for ( int i = 0; i < iNumX; ++i )
551 {
552 int iTopInd, iBottomInd;
553 if ( bOffsetTop )
554 {
555 iBottomInd = j*iNumX+i;
556 iTopInd = ((j+y)%iNumY)*iNumX + ((i+x)%iNumX);
557 }
558 else
559 {
560 iTopInd = j*iNumX+i;
561 iBottomInd = ((j+y)%iNumY)*iNumX + ((i+x)%iNumX);
562 }
563
564 if ( LayerIntersections[iBottomInd][0].second > 0.0 && LayerIntersections[iTopInd][1].first > 0.0 )
565 {
566 double dist = LayerIntersections[iTopInd][1].first - LayerIntersections[iBottomInd][0].second;
567 if ( OffsetMinDist == START_DIST || dist < OffsetMinDist )
568 {
569 OffsetMinDist = dist;
570 }
571 }
572
573 }
574 }
575
576 // Check if min dist for this offset is greater than previous stored for this inter layer gap (ie will give greater nesting)
577
578 if ( MinDist[iLayer].second == START_DIST || OffsetMinDist > MinDist[iLayer].second )
579 {
580 MinDist[iLayer].second = OffsetMinDist;
581 MinDist[iLayer].first = y*iNumX + x;
582 }
583
584}
585
586int CTextileLayered::GetLayerMeshes( vector<CMesh>& LayerMeshes )
587{
588 int iNumSlaveNodes = 0;
589 for ( int i = 0; i < m_LayerYarnIndices.size(); ++i )
590 {
591 vector<int>::iterator itIndices;
592 CMesh Mesh;
593 for ( itIndices = m_LayerYarnIndices[i].begin(); itIndices != m_LayerYarnIndices[i].end(); ++itIndices )
594 {
595 CYarn* Yarn = GetYarn( *itIndices );
596 int Num = Yarn->GetNumSlaveNodes(); // Use the number of slave nodes to give resolution for grid
597 if ( Num > iNumSlaveNodes )
598 {
599 iNumSlaveNodes = Num;
600 }
601 Yarn->AddSurfaceToMesh( Mesh, *m_pDomain, false, false );
602 }
604 LayerMeshes.push_back( Mesh );
605 }
606 return iNumSlaveNodes;
607}
608
609void CTextileLayered::GetLayerRepeats( vector< XY >& Repeats )
610{
611 for ( int i = 0; i < m_LayerYarnIndices.size(); ++i )
612 {
613 XY Repeat;
614 CYarn* Yarn = GetYarn( m_LayerYarnIndices[i][0] ); // Just get first - assume repeats for all yarns in layer are the same (valid??)
615 vector<XYZ> YarnRepeats;
616 vector<XYZ>::iterator itYarnRepeats;
617 YarnRepeats = Yarn->GetRepeats();
618 for ( itYarnRepeats = YarnRepeats.begin(); itYarnRepeats != YarnRepeats.end(); ++itYarnRepeats )
619 {
620 if ( itYarnRepeats->x > Repeat.x )
621 {
622 Repeat.x = itYarnRepeats->x;
623 }
624 if ( itYarnRepeats->y > Repeat.y )
625 {
626 Repeat.y = itYarnRepeats->y;
627 }
628 }
629 Repeats.push_back( Repeat );
630 }
631}
632
633double CTextileLayered::GreatestCommonDenominator( double X1, double X2 )
634{
635 int iX1 = (int)(X1 * 1e+6);
636 int iX2 = (int)(X2 * 1e+6);
637
638 if ( iX2 > iX1 )
639 {
640 int temp = iX1;
641 iX1 = iX2;
642 iX2 = temp;
643 }
644
645 while ( iX2 != 0 )
646 {
647 int temp = iX2;
648 iX2 = iX1 % iX2;
649 iX1 = temp;
650 }
651 return( (double)(iX1/1e+6) );
652}
#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
#define FOR_EACH_TIXMLELEMENT(CHILDELEMENT, PARENTELEMENT, ELEMENTNAME)
Macro to enable looping over tinyxml easier.
Definition: Misc.h:45
#define START_DIST
Domain implementation described using planes, the simplest of which would be a box.
Definition: DomainPlanes.h:37
void SetPlane(int index, PLANE &Plane)
Set plane at given index.
int GetPlane(XYZ &Normal, PLANE &Plane)
Get plane with given normal. Returns both the plane and its index.
Defines the nodes and elements of a surface or volume mesh.
Definition: Mesh.h:58
void ConvertQuadstoTriangles(bool bQuality=true)
Convert the quad elements to triangles.
Definition: Mesh.cpp:1088
Represents a textile cell containing yarns.
Definition: Textile.h:39
virtual string GetType() const
Derived class should return the class name.
Definition: Textile.h:51
virtual void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
Used for saving data to XML.
Definition: Textile.cpp:87
int AddYarn(const CYarn &Yarn)
Add a Yarn to the textile.
Definition: Textile.cpp:122
const vector< CYarn > & GetYarns() const
Definition: Textile.cpp:676
bool m_bNeedsBuilding
Variable which keeps track of wether the textile needs building or not.
Definition: Textile.h:330
CObjectContainer< CDomain > m_pDomain
Definition: Textile.h:332
const CYarn * GetYarn(int iIndex) const
Definition: Textile.cpp:693
Represents a textile made up from several layers of weaves.
virtual void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
Used for saving data to XML.
CTextileLayered()
Build a weave unit cell of given width, height, yarn spacing and fabric thickness.
void ApplyOffsets(vector< XY > &Offsets)
const vector< XY > & GetOffsets() const
void GetLayerRepeats(vector< XY > &Repeats)
void ApplyLayerOffset(XYZ &Offset, int iLayer)
void AddLayer(CTextile &Textile, XYZ &Offset)
Adds the layers from the textile passed, maintaining the existing offset of each layer.
string GetDefaultName() const
Get the default name to assign to a textile.
int GetLayerMeshes(vector< CMesh > &LayerMeshes)
const vector< vector< int > > GetLayerYarnIndices()
void SetOffsets(vector< XY > &Offsets)
Sets an xy offset for each layer.
void GetOffsetMinDist(int iOffset, vector< vector< pair< double, double > > > &LayerIntersections, vector< pair< int, double > > &MinDist, int iNumX, int iNumY)
vector< XY > m_LayerOffset
double GreatestCommonDenominator(double X1, double X2)
vector< vector< int > > m_LayerYarnIndices
virtual ~CTextileLayered(void)
void SetRelativeOffsets(vector< XY > &Offsets)
Sets an xy offset for the layer, relative to the existing offset.
Represents a yarn consisting of master nodes, section and interpolation function.
Definition: Yarn.h:49
bool AddSurfaceToMesh(CMesh &Mesh, bool bAddEndCaps=true) const
Create surface mesh for this yarn and add it to the surface mesh object.
Definition: Yarn.cpp:860
int GetNumSlaveNodes() const
Get number of slave nodes.
Definition: Yarn.h:440
const vector< XYZ > & GetRepeats() const
Definition: Yarn.h:448
void Translate(XYZ Vector)
Translate the Yarn by given vector.
Definition: Yarn.cpp:684
Namespace containing a series of customised math operations not found in the standard c++ library.
OUTPUT_TYPE
Definition: Misc.h:105
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
Struct for representing a Plane.
Definition: Plane.h:25
double d
Definition: Plane.h:31
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