TexGen
TextileLayerToLayer.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2011 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 "TextileLayerToLayer.h"
22
23
24using namespace TexGen;
25
26// Build a weave unit cell of given width, height, yarn spacing and fabric thickness
27CTextileLayerToLayer::CTextileLayerToLayer(int iNumXYarns, int iNumYYarns, double dXSpacing, double dYSpacing, double dXHeight, double dYHeight, int iNumBinderLayers, bool bShapeBinders)
28: CTextile3DWeave( iNumXYarns, iNumYYarns, dXSpacing, dYSpacing, dXHeight, dYHeight)
29{
30 m_iNumBinderLayers = iNumBinderLayers;
31 m_bShapeBinders = bShapeBinders;
32}
33
35: CTextile3DWeave(Element)
36{
37 Element.Attribute("BinderLayers", &m_iNumBinderLayers);
38}
39
41{
42}
43
44void CTextileLayerToLayer::PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
45{
46 CTextile3DWeave::PopulateTiXmlElement(Element, OutputType);
47 Element.SetAttribute("BinderLayers", m_iNumBinderLayers);
48}
49
50void CTextileLayerToLayer::SetBinderPosition( int x, int y, int zOffset )
51{
52 vector<PATTERN3D> &Cell = GetCell(x, y);
53 int size = Cell.size();
54 int MaxBinderPos = (size - 1) - (zOffset * 2); // *2 because each offset shifts by two cell positions
55 int MinBinderPos = (size - 1) - (zOffset + m_iNumBinderLayers-1)*2;
56 if ( MinBinderPos < 0 )
57 {
58 TGERROR("Unable to set binder positions, lowest binder position too low for number of weft yarns");
59 return;
60 }
61 if ( MaxBinderPos > size - 1 )
62 {
63 TGERROR("Unable to set binder positions, upper binder position too high for number of weft yarns");
64 return;
65 }
66
67 // Set x yarn in each of positions between Max and Min binder pos
68 for ( int j = 0; j < size; j+=2 )
69 {
70 if ( j >= MinBinderPos && j <= MaxBinderPos )
71 {
72 Cell[j] = PATTERN3D_XYARN;
73 }
74 else
75 {
76 Cell[j] = PATTERN3D_NOYARN;
77 }
78 }
79}
80
81void CTextileLayerToLayer::MoveBinderYarns( int x, int y, int iLevel1, int iLevel2 )
82{
83 vector<PATTERN3D> &Cell = GetCell(x, y);
84 int iTopBinder = FindTopBinderYarn( Cell );
85 int iOffset = ((Cell.size()-1) - iTopBinder) / 2;
86 // Only allow to move by one level
87 if ( iLevel1 < iLevel2 ) // Moving up
88 {
89 SetBinderPosition( x, y, iOffset - 1 );
90 }
91 else // moving down
92 {
93 SetBinderPosition( x, y, iOffset + 1 );
94 }
95}
96
97int CTextileLayerToLayer::FindTopBinderYarn( vector<PATTERN3D>& Cell )
98{
99 int i = Cell.size() - 1;
100 while( i > 0 )
101 {
102 if ( Cell[i] == PATTERN3D_XYARN )
103 return i;
104 --i;
105 }
106 return i;
107}
108
110{
111 // Offset is the number of binder positions away from top of fabric
112 vector<PATTERN3D> &Cell = GetCell(x, y);
113 int iTopBinder = FindTopBinderYarn( Cell );
114 int iOffset = ((Cell.size()-1) - iTopBinder) / 2;
115 return iOffset;
116}
117
118void CTextileLayerToLayer::SetupLayers( int iNumWarpLayers, int iNumWeftLayers, int iNumBinderLayers )
119{
120 if ( iNumWarpLayers != iNumWeftLayers-1 )
121 {
122 TGERROR("Unable to set up layers, number of warp layers should be one less than weft layers: warp layers " << iNumWarpLayers << ", weft layers " << iNumWeftLayers);
123 return;
124 }
126 int iWarpOnlyLayers = iNumWarpLayers - iNumBinderLayers + 1;
127
128 // Add alternating layers
129 while( iNumWeftLayers > 0 )
130 {
131 AddYLayers();
132 if ( iNumWarpLayers > 0 )
133 {
134 if ( iWarpOnlyLayers > 0 )
135 {
136 AddWarpLayer();
137 iWarpOnlyLayers--;
138 }
139 else
140 AddXLayers(); // Add both warp and binder yarns
141 iNumWarpLayers--;
142 }
143 iNumWeftLayers--;
144 }
145
147}
148
150{
151 m_Yarns.clear();
152 m_YYarns.clear();
153 m_XYarns.clear();
154
155 m_YYarns.resize(m_iNumYYarns);
156 m_XYarns.resize(m_iNumXYarns);
157
158 m_dMinZ = 0.0;
159 m_dMaxZ = 0.0;
160
161 if (!Valid() || !CheckCells())
162 {
163 TGERROR("Cannot build textile - incorrect yarn setup");
164 return false;
165 }
166
167 TGLOGINDENT("Building textile weave \"" << GetName() << "\"");
168 m_bNeedsBuilding = false;
169
170 vector<int> Yarns;
171
172 double x, y, z;
173
174 // Add x yarns (yarns parallel to the x axis)
175 int i, j, k, iYarn;
176 y = 0;
177 for (i = 0; i < m_iNumXYarns; ++i)
178 {
179 y += m_XYarnData[i].dSpacing / 2.0;
180 x = 0;
181 Yarns.clear();
182 for (j = 0; j <= m_iNumYYarns; ++j)
183 {
184 const vector<PATTERN3D> &Cell = GetCell(j%m_iNumYYarns, i);
185 int NextCellIndex;
186 NextCellIndex = FindNextCellIndex(i);
187 const vector<PATTERN3D> &NextCell = GetCell(j%m_iNumYYarns, NextCellIndex%m_iNumXYarns);
188 if (j == 0)
189 {
190 for (k = 0; k < (int)Cell.size(); ++k)
191 {
192 if (Cell[k] == PATTERN3D_XYARN)
193 {
194 Yarns.push_back(AddYarn(CYarn()));
195 }
196 }
197 }
198 m_XYarns[i] = Yarns;
199 iYarn = 0;
200
201 x += m_YYarnData[j%m_iNumYYarns].dSpacing / 2.0;
202
203 z = 0.0;
204 for (k = 0; k < (int)Cell.size(); ++k)
205 {
206 if (Cell[k] == PATTERN3D_XYARN)
207 {
208 double dHalfHeight = m_XYarnData[i].dHeight / 2.0;
209 if (IsBinderYarn(i))
210 {
211 if (k == 0)
212 {
213 z -= dHalfHeight + m_dGapSize;
214 if ((z - dHalfHeight) < m_dMinZ)
215 m_dMinZ = z - dHalfHeight;
216 }
217 else
218 {
219 if (NextCell[k] == PATTERN3D_XYARN)
220 {
221 dHalfHeight = m_XYarnData[NextCellIndex].dHeight / 2.0;
222 }
223 else if (NextCell[k] == PATTERN3D_YYARN)
224 {
225 dHalfHeight = m_YYarnData[j%m_iNumYYarns].dHeight / 2.0;
226 }
227 else // PATTERN3D_NOYARN
228 {
229 // Does this ever happen?
230 }
231 z += dHalfHeight;
232 }
233 }
234 else
235 {
236 z += dHalfHeight;
237 }
238 m_Yarns[Yarns[iYarn]].AddNode(CNode(XYZ(x, y, z), XYZ(1, 0, 0)));
239 ++iYarn;
240 z += dHalfHeight + m_dGapSize;
241 if (z > m_dMaxZ)
242 m_dMaxZ = z;
243 }
244 else if (Cell[k] == PATTERN3D_YYARN)
245 {
246 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
247 }
248 else if (k > 0)// PATTERN3D_NOYARN and not on bottom binder layer
249 {
250 if (NextCell[k] == PATTERN3D_XYARN)
251 {
252 z += m_XYarnData[NextCellIndex].dHeight + m_dGapSize;
253 }
254 else if (NextCell[k] == PATTERN3D_YYARN)
255 {
256 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
257 }
258 else // PATTERN3D_NOYARN
259 {
260 // Will get here if all x yarns are binder yarns so just use binder yarn height to give spacing
261 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
262 }
263 }
264 }
265 if (j < m_iNumYYarns)
266 x += m_YYarnData[j].dSpacing / 2.0;
267 }
268 y += m_XYarnData[i].dSpacing / 2.0;
269 }
270
271 // Add y yarns (yarns parallel to the y axis)
272 x = 0;
273 for (j = 0; j < m_iNumYYarns; ++j)
274 {
275 y = 0;
276 Yarns.clear();
277 x += m_YYarnData[j].dSpacing / 2.0;
278 for (i = 0; i <= m_iNumXYarns; ++i)
279 {
280 const vector<PATTERN3D> &Cell = GetCell(j, i%m_iNumXYarns);
281
282 int NextCellIndex = FindNextCellIndex(i);
283 const vector<PATTERN3D> &NextCell = GetCell(j%m_iNumYYarns, NextCellIndex%m_iNumXYarns);
284 if (i == 0)
285 {
286 for (k = 0; k < (int)Cell.size(); ++k)
287 {
288 if (Cell[k] == PATTERN3D_YYARN)
289 {
290 Yarns.push_back(AddYarn(CYarn()));
291 }
292 }
293 }
294 m_YYarns[j] = Yarns;
295 iYarn = 0;
296 y += m_XYarnData[i%m_iNumXYarns].dSpacing / 2.0;
297 z = 0.0;
298
299 for (k = 0; k < (int)Cell.size(); ++k)
300 {
301 if (Cell[k] == PATTERN3D_YYARN)
302 {
303 double dHalfHeight = m_YYarnData[j].dHeight / 2.0;
304 z += dHalfHeight;
305 m_Yarns[Yarns[iYarn]].AddNode(CNode(XYZ(x, y, z), XYZ(0, 1, 0)));
306 ++iYarn;
307 z += dHalfHeight + m_dGapSize;
308 }
309 else if (Cell[k] == PATTERN3D_XYARN && k > 0) // Don't adjust z if it's the bottom binder yarn
310 {
312 {
313 if (NextCell[k] == PATTERN3D_XYARN)
314 {
315 z += m_XYarnData[NextCellIndex%m_iNumXYarns].dHeight + m_dGapSize;
316 }
317 else if (NextCell[k] == PATTERN3D_YYARN)
318 {
319 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
320 }
321 else // PATTERN3D_NOYARN
322 {
323 // Does this ever happen?
324 }
325 }
326 else
327 {
328 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
329 }
330 }
331 else if (k > 0) // PATTERN3D_NOYARN and not on bottom binder layer
332 {
333 if (NextCell[k] == PATTERN3D_XYARN)
334 {
335 z += m_XYarnData[NextCellIndex%m_iNumXYarns].dHeight + m_dGapSize;
336 }
337 else if (NextCell[k] == PATTERN3D_YYARN)
338 {
339 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
340 }
341 else // PATTERN3D_NOYARN
342 {
343 // Will get here if all x yarns are binder yarns so just use binder yarn height to give spacing
344 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
345 }
346 }
347 }
348 if (i < m_iNumXYarns)
349 y += m_XYarnData[i].dSpacing / 2.0;
350 }
351 x += m_YYarnData[j].dSpacing / 2.0;
352 }
353
354
355 // Assign sections to the yarns
356 vector<int>::iterator itpYarn;
357 double dWidth, dHeight;
358 for (i = 0; i < m_iNumXYarns; ++i)
359 {
360 dWidth = m_XYarnData[i].dWidth;
361 dHeight = m_XYarnData[i].dHeight;
362 CSectionPowerEllipse Section(dWidth, dHeight, IsBinderYarn(i) ? m_dBinderPower : m_dWarpPower);
363 if (m_pSectionMesh)
365 for (itpYarn = m_XYarns[i].begin(); itpYarn != m_XYarns[i].end(); ++itpYarn)
366 {
367 m_Yarns[*itpYarn].AssignSection(CYarnSectionConstant(Section));
368 }
369 }
370 for (i = 0; i < m_iNumYYarns; ++i)
371 {
372 dWidth = m_YYarnData[i].dWidth;
373 dHeight = m_YYarnData[i].dHeight;
374 CSectionPowerEllipse Section(dWidth, dHeight, m_dWeftPower);
375 if (m_pSectionMesh)
377 for (itpYarn = m_YYarns[i].begin(); itpYarn != m_YYarns[i].end(); ++itpYarn)
378 {
379 m_Yarns[*itpYarn].AssignSection(CYarnSectionConstant(Section));
380 }
381 }
382
383
384
385 // Add repeats and set interpolation
386 dWidth = GetWidth();
387 dHeight = GetHeight();
388 vector<CYarn>::iterator itYarn;
389 for (itYarn = m_Yarns.begin(); itYarn != m_Yarns.end(); ++itYarn)
390 {
391 itYarn->AssignInterpolation(CInterpolationBezier());
392 itYarn->SetResolution(m_iResolution);
393 itYarn->AddRepeat(XYZ(dWidth, 0, 0));
394 itYarn->AddRepeat(XYZ(0, dHeight, 0));
395 }
396 return true;
397}
398
400{
402 return false;
403
404 if (m_bShapeBinders)
406 return true;
407}
408
410{
411 return m_iNumBinderLayers;
412}
413
415{
416 for ( int j = 0; j < m_iNumXYarns; ++j )
417 {
418 if ( IsBinderYarn( j ) )
419 {
420 for ( int Height = 0; Height < m_iNumBinderLayers; ++Height )
421 {
422 int CurrentNode = 0;
423 for ( int i = 0; i < m_iNumYYarns; ++i )
424 {
425 CurrentNode = AddBinderNodes( CurrentNode, i, j, Height );
426 CurrentNode++;
427 }
429 }
430 }
431 }
432}
433
434int CTextileLayerToLayer::AddBinderNodes( int CurrentNode, int i, int j, int Height ) const
435{
436 const vector<PATTERN3D> &Cell = GetCell(i,j);
437
438 int NextCellIndex = (i+1)%m_iNumYYarns;
439 int PrevCellIndex = (i+m_iNumYYarns-1)%m_iNumYYarns;
440 const vector<PATTERN3D> &NextCell = GetCell( (i+1)%m_iNumYYarns, j );
441 const vector<PATTERN3D> &PrevCell = GetCell( (i+m_iNumYYarns-1)%m_iNumYYarns, j );
442
443 int iIndex = FindBinderHeight( Cell, Height );
444 int iPrevIndex = FindBinderHeight( PrevCell, Height );
445 int iNextIndex = FindBinderHeight( NextCell, Height );
446 int iMaxIndex = Cell.size() - 1;
447
448 XY SectionPoint;
449 XYZ WeftBelowNode, WeftAboveNode;
450 int iStartNode = CurrentNode;
451
452 if ( iIndex < 0 )
453 return CurrentNode;
454
455 double dBinderOffset = m_XYarnData[j].dHeight/2.0;
456
457 int BinderYarnIndex = GetYarnIndex( i, j, iIndex );
458 if ( BinderYarnIndex == -1 )
459 return CurrentNode;
460
461 int WeftAboveIndex, WeftBelowIndex;
462
463 // Get indices of weft yarns above and below binder
464 if ( iIndex < (int)Cell.size() - 1 )
465 {
466 WeftAboveIndex = GetYarnIndex( i, j, iIndex + 1 );
467 WeftAboveNode = m_Yarns[WeftAboveIndex].GetNode( j )->GetPosition();
468 }
469 else
470 WeftAboveIndex = -1;
471
472 if ( iIndex > 0 )
473 {
474 WeftBelowIndex = GetYarnIndex( i, j, iIndex - 1 );
475 WeftBelowNode = m_Yarns[WeftBelowIndex].GetNode( j )->GetPosition();
476 }
477 else
478 WeftBelowIndex = -1;
479
480 XYZ BinderNode = m_Yarns[BinderYarnIndex].GetNode( CurrentNode )->GetPosition();
481
482 if ( iIndex > 0 && iPrevIndex < iIndex && PrevCell[iPrevIndex] == PATTERN3D_XYARN
483 && GetYarnIndex( PrevCellIndex, j, iPrevIndex ) == BinderYarnIndex)
484 {
485 // Get cross section of weft yarn below
486 CSectionPowerEllipse* YarnSection = GetWeftCrossSection( WeftBelowIndex );
487 if ( YarnSection == NULL )
488 return CurrentNode;
489
490 // Insert points around Top left quadrant of weft yarn
491 XYZ NewNode = WeftBelowNode;
492
493
494 int PrevWeftAboveIndex = GetYarnIndex( PrevCellIndex, j, iPrevIndex+1 );
495 XYZ PrevWeftAboveNode = m_Yarns[PrevWeftAboveIndex].GetNode(j)->GetPosition();
496 CSectionPowerEllipse* PrevYarnSection = GetWeftCrossSection( PrevWeftAboveIndex );
497 XY PrevSectionPoint = PrevYarnSection->GetPoint(0.0);
498
499 // Check whether need to add node at the end of the section.
500 // Compare the angles between the two end nodes and the nodes inserted at 0.45 and 0.95 of the current weft position and the previous one
501 if ( i == 0 )
502 PrevWeftAboveNode.x -= GetWidth(); // Need position of the yarn before the current node
503 XYZ PrevEndPoint = PrevWeftAboveNode;
504 PrevEndPoint.x = PrevWeftAboveNode.x + PrevSectionPoint.x + dBinderOffset + m_dGapSize;
505 XYZ PrevPoint = PrevWeftAboveNode;
506 PrevSectionPoint = PrevYarnSection->GetPoint(0.95);
507 PrevPoint.x = PrevWeftAboveNode.x + PrevSectionPoint.x;
508 PrevPoint.z = PrevWeftAboveNode.z + PrevSectionPoint.y - (dBinderOffset + m_dGapSize);
509
510 SectionPoint = YarnSection->GetPoint(0.5);
511 NewNode.x = NewNode.x + SectionPoint.x - dBinderOffset - m_dGapSize;
512 NewNode.z = NewNode.z + SectionPoint.y;
513 SectionPoint = YarnSection->GetPoint(0.45);
514 XYZ NewNodePoint = WeftBelowNode;
515 NewNodePoint.x = NewNodePoint.x + SectionPoint.x;
516 NewNodePoint.z = NewNodePoint.z + SectionPoint.y + dBinderOffset + m_dGapSize;
517
518 double EndBinderAngle = atan2( NewNode.z - PrevEndPoint.z, NewNode.x - PrevEndPoint.x );
519 double dBinderAngle = atan2( NewNodePoint.z - PrevPoint.z, NewNodePoint.x - PrevPoint.x );
520
521 if ( EndBinderAngle > dBinderAngle )
522 {
523 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode); // Add node at position 0.5
524 CurrentNode++;
525 }
526
527 InsertBinderNode( YarnSection, 0.45, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
528 InsertBinderNode( YarnSection, 0.4, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
529 if( !( iIndex < iMaxIndex && iNextIndex > iIndex && NextCell[iNextIndex] == PATTERN3D_XYARN
530 && GetYarnIndex( NextCellIndex, j, iNextIndex ) == BinderYarnIndex ) )
531 {
532 InsertBinderNode( YarnSection, 0.35, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
533 InsertBinderNode( YarnSection, 0.3, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
534 }
535
536 if ( iNextIndex <= iIndex && NextCell[iNextIndex] == PATTERN3D_XYARN
537 && GetYarnIndex( NextCellIndex, j, iNextIndex ) == BinderYarnIndex)
538 {
539 InsertBinderNode( YarnSection, 0.25, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize, false );
540 }
541 delete YarnSection;
542 }
543 else if ( iIndex < iMaxIndex && iPrevIndex > iIndex && PrevCell[iPrevIndex] == PATTERN3D_XYARN
544 && GetYarnIndex( PrevCellIndex, j, iPrevIndex ) == BinderYarnIndex )
545 {
546 // Get cross section of weft yarn below
547 CSectionPowerEllipse* YarnSection = GetWeftCrossSection( WeftAboveIndex );
548 if ( YarnSection == NULL )
549 return CurrentNode;
550 // Insert points around lower left quadrant of weft yarn
551 XYZ NewNode = WeftAboveNode;
552
553 int PrevWeftBelowIndex = GetYarnIndex( PrevCellIndex, j, iPrevIndex-1 );
554 XYZ PrevWeftBelowNode = m_Yarns[PrevWeftBelowIndex].GetNode(j)->GetPosition();
555 CSectionPowerEllipse* PrevYarnSection = GetWeftCrossSection( PrevWeftBelowIndex );
556 XY PrevSectionPoint = PrevYarnSection->GetPoint(0.0);
557
558 // Check whether need to add node at the end of the section.
559 // Compare the angles between the two end nodes and the nodes inserted at 0.45 and 0.95 of the current weft position and the previous one
560 if ( i == 0 )
561 PrevWeftBelowNode.x -= GetWidth(); // Need position of the yarn before the current node
562 XYZ PrevEndPoint = PrevWeftBelowNode;
563 PrevEndPoint.x = PrevWeftBelowNode.x + PrevSectionPoint.x + dBinderOffset + m_dGapSize;
564 XYZ PrevPoint = PrevWeftBelowNode;
565 PrevSectionPoint = PrevYarnSection->GetPoint(0.05);
566 PrevPoint.x = PrevWeftBelowNode.x + PrevSectionPoint.x;
567 PrevPoint.z = PrevWeftBelowNode.z + PrevSectionPoint.y + dBinderOffset + m_dGapSize;
568
569 SectionPoint = YarnSection->GetPoint(0.5);
570 NewNode.x = NewNode.x + SectionPoint.x - dBinderOffset - m_dGapSize;
571 NewNode.z = NewNode.z + SectionPoint.y;
572 SectionPoint = YarnSection->GetPoint(0.55);
573 XYZ NewNodePoint = WeftAboveNode;
574 NewNodePoint.x = NewNodePoint.x + SectionPoint.x;
575 NewNodePoint.z = NewNodePoint.z + SectionPoint.y - (dBinderOffset + m_dGapSize);
576
577 double EndBinderAngle = atan2( NewNode.z - PrevEndPoint.z, NewNode.x - PrevEndPoint.x );
578 double dBinderAngle = atan2( NewNodePoint.z - PrevPoint.z, NewNodePoint.x - PrevPoint.x );
579
580 if ( EndBinderAngle < dBinderAngle )
581 {
582 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode); // Add node at position 0.5
583 CurrentNode++;
584 }
585
586
587 NewNode = WeftAboveNode;
588
589 InsertBinderNode( YarnSection, 0.55, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
590 InsertBinderNode( YarnSection, 0.6, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
591
592 if ( !( iIndex > 0 && iNextIndex < iIndex && NextCell[iNextIndex] == PATTERN3D_XYARN
593 && GetYarnIndex( NextCellIndex, j, iNextIndex ) == BinderYarnIndex ) )
594 {
595 InsertBinderNode( YarnSection, 0.65, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
596 InsertBinderNode( YarnSection, 0.7, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
597 }
598
599 if ( iNextIndex >= iIndex && NextCell[iNextIndex] == PATTERN3D_XYARN
600 && GetYarnIndex( NextCellIndex, j, iNextIndex ) == BinderYarnIndex )
601 {
602 InsertBinderNode( YarnSection, 0.75, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize), false );
603 }
604 delete YarnSection;
605 }
606
607
608
609 if ( iIndex > 0 && iNextIndex < iIndex && NextCell[iNextIndex] == PATTERN3D_XYARN
610 && GetYarnIndex( NextCellIndex, j, iNextIndex ) == BinderYarnIndex )
611 {
612
613 // Get cross section of weft yarn below
614 CSectionPowerEllipse* YarnSection = GetWeftCrossSection( WeftBelowIndex );
615 if ( YarnSection == NULL )
616 return CurrentNode;
617
618 if ( iPrevIndex <= iIndex && PrevCell[iPrevIndex] == PATTERN3D_XYARN
619 && GetYarnIndex( PrevCellIndex, j, iPrevIndex ) == BinderYarnIndex )
620 {
621 InsertBinderNode( YarnSection, 0.25, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize, false );
622 }
623 // Insert points around upper right quadrant of weft
624
625 XYZ NewNode = WeftBelowNode;
626 CurrentNode++; // Need to insert after node (ie before next node)
627 if ( !(iIndex < iMaxIndex && iPrevIndex > iIndex && PrevCell[iPrevIndex] == PATTERN3D_XYARN
628 && GetYarnIndex( PrevCellIndex, j, iPrevIndex ) == BinderYarnIndex ) )
629 {
630 InsertBinderNode( YarnSection, 0.2, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
631 InsertBinderNode( YarnSection, 0.15, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
632 }
633 InsertBinderNode( YarnSection, 0.1, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
634 InsertBinderNode( YarnSection, 0.05, WeftBelowNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
635 CurrentNode--;
636
637 int NextWeftAboveIndex = GetYarnIndex( NextCellIndex, j, iNextIndex+1 );
638 XYZ NextWeftAboveNode = m_Yarns[NextWeftAboveIndex].GetNode(j)->GetPosition();
639 CSectionPowerEllipse* NextYarnSection = GetWeftCrossSection( NextWeftAboveIndex );
640 XY NextSectionPoint = NextYarnSection->GetPoint(0.5);
641
642 // Check whether need to add node at the end of the section.
643 // Compare the angles between the two end nodes and the nodes inserted at 0.45 and 0.95 of the current weft position and the previous one
644 if ( i == m_iNumYYarns-1 )
645 NextWeftAboveNode.x += GetWidth(); // Need position of the yarn before the current node
646 XYZ NextEndPoint = NextWeftAboveNode;
647 NextEndPoint.x = NextWeftAboveNode.x + NextSectionPoint.x - (dBinderOffset + m_dGapSize);
648 XYZ NextPoint = NextWeftAboveNode;
649 NextSectionPoint = NextYarnSection->GetPoint(0.55);
650 NextPoint.x = NextWeftAboveNode.x + NextSectionPoint.x;
651 NextPoint.z = NextWeftAboveNode.z + NextSectionPoint.y - (dBinderOffset + m_dGapSize);
652
653 SectionPoint = YarnSection->GetPoint(0.0);
654 NewNode.x = NewNode.x + SectionPoint.x + dBinderOffset + m_dGapSize;
655 NewNode.z = NewNode.z + SectionPoint.y;
656 SectionPoint = YarnSection->GetPoint(0.05);
657 XYZ NewNodePoint = WeftBelowNode;
658 NewNodePoint.x = NewNodePoint.x + SectionPoint.x;
659 NewNodePoint.z = NewNodePoint.z + SectionPoint.y + dBinderOffset + m_dGapSize;
660
661 double EndBinderAngle = atan2( NewNode.z - NextEndPoint.z, NewNode.x - NextEndPoint.x );
662 double dBinderAngle = atan2( NewNodePoint.z - NextPoint.z, NewNodePoint.x - NextPoint.x );
663
664 if ( EndBinderAngle < dBinderAngle )
665 {
666 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode+1); // Add node at position 0.5
667 CurrentNode++;
668 }
669
670 delete YarnSection;
671 }
672 else if( iIndex < iMaxIndex && iNextIndex > iIndex && NextCell[iNextIndex] == PATTERN3D_XYARN
673 && GetYarnIndex( NextCellIndex, j, iNextIndex ) == BinderYarnIndex )
674 {
675 // Get cross section of weft yarn below
676 CSectionPowerEllipse* YarnSection = GetWeftCrossSection( WeftAboveIndex );
677 if ( YarnSection == NULL )
678 return CurrentNode;
679
680 if ( iPrevIndex >= iIndex && PrevCell[iPrevIndex] == PATTERN3D_XYARN
681 && GetYarnIndex( PrevCellIndex, j, iPrevIndex ) == BinderYarnIndex )
682 {
683 InsertBinderNode( YarnSection, 0.75, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize), false );
684 }
685 // Insert points around lower right quadrant of weft yarn
686 {
687 XYZ NewNode = WeftAboveNode;
688 CurrentNode++; // Need to insert after node (ie before next node)
689 if ( !(iIndex > 0 && iPrevIndex < iIndex && PrevCell[iPrevIndex] == PATTERN3D_XYARN
690 && GetYarnIndex( PrevCellIndex, j, iPrevIndex ) == BinderYarnIndex) )
691 {
692 InsertBinderNode( YarnSection, 0.8, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
693 InsertBinderNode( YarnSection, 0.85, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
694 }
695 InsertBinderNode( YarnSection, 0.9, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
696 InsertBinderNode( YarnSection, 0.95, WeftAboveNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
697 CurrentNode--;
698
699 int NextWeftBelowIndex = GetYarnIndex( NextCellIndex, j, iNextIndex-1 );
700 XYZ NextWeftBelowNode = m_Yarns[NextWeftBelowIndex].GetNode(j)->GetPosition();
701 CSectionPowerEllipse* NextYarnSection = GetWeftCrossSection( NextWeftBelowIndex );
702 XY NextSectionPoint = NextYarnSection->GetPoint(0.5);
703
704 // Check whether need to add node at the end of the section.
705 // Compare the angles between the two end nodes and the nodes inserted at 0.45 and 0.95 of the current weft position and the previous one
706 if ( i == m_iNumYYarns-1 )
707 NextWeftBelowNode.x += GetWidth(); // Need position of the yarn before the current node
708 XYZ NextEndPoint = NextWeftBelowNode;
709 NextEndPoint.x = NextWeftBelowNode.x + NextSectionPoint.x - (dBinderOffset + m_dGapSize);
710 XYZ NextPoint = NextWeftBelowNode;
711 NextSectionPoint = NextYarnSection->GetPoint(0.45);
712 NextPoint.x = NextWeftBelowNode.x + NextSectionPoint.x;
713 NextPoint.z = NextWeftBelowNode.z + NextSectionPoint.y + dBinderOffset + m_dGapSize;
714
715 SectionPoint = YarnSection->GetPoint(0.0);
716 NewNode.x = NewNode.x + SectionPoint.x + dBinderOffset + m_dGapSize;
717 NewNode.z = NewNode.z + SectionPoint.y;
718 SectionPoint = YarnSection->GetPoint(0.95);
719 XYZ NewNodePoint = WeftAboveNode;
720 NewNodePoint.x = NewNodePoint.x + SectionPoint.x;
721 NewNodePoint.z = NewNodePoint.z + SectionPoint.y - (dBinderOffset + m_dGapSize);
722
723 double EndBinderAngle = atan2( NextEndPoint.z - NewNode.z, NextEndPoint.x - NewNode.x );
724 double dBinderAngle = atan2( NextPoint.z - NewNodePoint.z, NextPoint.x - NewNodePoint.x );
725
726 if ( EndBinderAngle > dBinderAngle )
727 {
728 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode+1); // Add node at position 0.5
729 CurrentNode++;
730 }
731 }
732
733 delete YarnSection;
734 }
735
736 if ( iStartNode == 0 )
737 {
738 XYZ NewNode = m_Yarns[BinderYarnIndex].GetNode(0)->GetPosition();
739 ReplaceLastNode( BinderYarnIndex, NewNode, BinderNode );
740 }
741
742 return CurrentNode;
743}
744
745int CTextileLayerToLayer::FindBinderHeight( const vector<PATTERN3D>& Cell, int Height ) const
746{
747 int i = Cell.size() - 1;
748 while( i > 0 )
749 {
750 if ( Cell[i] == PATTERN3D_XYARN )
751 return i - Height*2;
752 --i;
753 }
754 return i;
755}
756
758{
760 for ( int i = m_iNumYYarns-1; i >=0; --i )
761 {
762 int iNumWefts = (int)m_YYarns[i].size();
763 vector<string> Rows;
764 Rows.resize(iNumWefts);
765
766 for ( int j = m_iNumXYarns-1; j >= 0 ; --j )
767 {
768 vector<PATTERN3D> &Cell = GetCell(i, j);
769 if ( NoYarnCell( Cell ) )
770 continue;
771 vector<bool> bWeftSet(iNumWefts, false);
772 int iWeft = iNumWefts-1;
773
774 for ( int k = (int)Cell.size()-1; k >= 0; --k )
775 {
776 switch (Cell[k])
777 {
778 case PATTERN3D_XYARN:
779 for ( int iW = 0; iW < iNumWefts; ++iW )
780 {
781 if ( !bWeftSet[iW] )
782 Rows[iW].push_back('1');
783 else
784 Rows[iW].push_back('0');
785 }
786 break;
787 case PATTERN3D_YYARN:
788 bWeftSet[iWeft] = true;
789 iWeft--;
790 break;
791 case PATTERN3D_NOYARN:
792 break;
793 }
794
795 }
796 }
797
798 if ( iWeftOrder == BOTTOM_TO_TOP || (iWeftOrder == ALTERNATE_WEFT_STACK && i%2))
799 {
800 // Add wefts from bottom to top
801 for ( int iW = iNumWefts-1 ; iW >=0; --iW )
802 m_PatternDraft.AddRow( Rows[iW] );
803 }
804 else
805 {
806 // Add wefts from top to bottom
807 for ( int iW = 0 ; iW < iNumWefts; ++iW )
808 m_PatternDraft.AddRow( Rows[iW] );
809 }
810 }
811}
812
#define TGLOGINDENT(MESSAGE)
Combines the TGLOG macro and TGLOGAUTOINDENT macro in one.
Definition: Logger.h:68
#define TGERROR(MESSAGE)
Macros used to report the file name and line number to the TexGenError and TexGenLog functions.
Definition: Logger.h:29
#define NULL
Definition: ShinyConfig.h:50
Bezier interpolation for yarn paths.
Represents a point on the centreline of a yarn.
Definition: Node.h:28
void AddRow(string Row)
Add a row representing one weft insertion '1' indicates warp up, '0' warp down and '2' no yarn.
void AssignSectionMesh(const CSectionMesh &SectionMesh)
Assign a mesh to the section.
Definition: Section.cpp:227
XY GetPoint(double t) const
Get a point lying on the perimeter correspending to parametric value t.
Represents a 3D woven textile.
void AddNoYarnLayer()
Add empty layer.
void ReplaceLastNode(int BinderYarnIndex, XYZ &NewNode, XYZ &BinderNode) const
Replace last node with node offset to match node 0.
vector< YARNDATA > m_XYarnData
vector< vector< int > > m_XYarns
int GetYarnIndex(int x, int y, int z) const
void CheckUpVectors(int WarpIndex, bool Yarn=PATTERN3D_XYARN, bool bYarnsIndex=false) const
bool CheckCells() const
Check that all cells are populated.
bool Valid() const
Check that the weave pattern contained in m_Pattern is valid.
double GetHeight() const
Get the height of the unit cell.
CSectionPowerEllipse * GetWeftCrossSection(int WeftYarnIndex) const
Adjust cross section shapes to correct interference.
int FindNextCellIndex(int index) const
Find next cell in y direction which isn't a binder yarn.
bool NoYarnCell(vector< PATTERN3D > &Cell)
bool IsBinderYarn(int index) const
Check if X yarn is binder or warp. Returns true if binder.
vector< YARNDATA > m_YYarnData
void AddBinderLayer()
Add yarns parallel to the X axis in binder yarn positions, no yarns in warp positions.
void AddWarpLayer()
Add yarns parallel to the X axis in warp yarn positions, no yarns in binder positions.
void AddXLayers(int y, int iNumberLayers)
Add given number of yarns parallel to the X axis, with given index y.
vector< vector< int > > m_YYarns
virtual double GetWidth() const
Get the width of the unit cell.
void AddYLayers(int x, int iNumberLayers)
Add given number of yarns parallel to the Y axis, with given index x.
void InsertBinderNode(CSectionPowerEllipse *YarnSection, double t, XYZ &WeftNode, int &CurrentNode, int BinderYarnIndex, double Offset, bool bInsert=true) const
Calculates a point at given point on power ellipse cross section and inserts into binder yarn.
virtual void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
Used for saving data to XML.
CPatternDraft m_PatternDraft
Class for generating pattern draft from weave pattern.
const vector< PATTERN3D > & GetCell(int x, int y) const
CObjectContainer< CSectionMesh > m_pSectionMesh
vector< CYarn > m_Yarns
Vector of yarns contained within this cell.
Definition: Textile.h:323
string GetName() const
Get the name associated with this textile.
Definition: Textile.cpp:355
int AddYarn(const CYarn &Yarn)
Add a Yarn to the textile.
Definition: Textile.cpp:122
bool m_bNeedsBuilding
Variable which keeps track of wether the textile needs building or not.
Definition: Textile.h:330
virtual void SetupLayers(int iNumWarpLayers, int iNumWeftLayers, int iNumBinderLayers=1)
Set up the sequence of layers in the textile for the required number of warp, weft and binder yarn la...
virtual void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
Used for saving data to XML.
CTextileLayerToLayer(int iNumXYarns, int iNumYYarns, double dXSpacing, double dYSpacing, double dXHeight, double dYHeight, int iNumBinderLayers, bool bShapeBinders=true)
Build a weave unit cell of given width, height, yarn spacing and fabric thickness.
int FindTopBinderYarn(vector< PATTERN3D > &Cell)
Finds cell index of the top binder yarn.
virtual void ConvertToPatternDraft(int iWeftOrder=BOTTOM_TO_TOP)
int AddBinderNodes(int CurrentNode, int i, int j, int Height) const
Add extra nodes to binder yarns to match shape of adjacent weft yarns.
virtual bool BuildTextile() const
Build the textile.
virtual int FindBinderHeight(const vector< PATTERN3D > &Cell, int Height) const
void ShapeBinderYarns() const
Shape the binder yarns around the adjacent weft yarns.
virtual int GetNumBinderLayers() const
Returns number of binder layers in textile.
int GetBinderOffset(int x, int y)
Finds the offset position of the top binder yarn at the given x,y position.
void SetBinderPosition(int x, int y, int zOffset)
Sets the vertical positions of the binder yarns.
void MoveBinderYarns(int x, int y, int iLevel1, int iLevel2)
Move the stack of binder yarns by one position.
Represents a yarn consisting of master nodes, section and interpolation function.
Definition: Yarn.h:49
Creates a section which is constant all along the yarn.
Namespace containing a series of customised math operations not found in the standard c++ library.
@ BOTTOM_TO_TOP
@ ALTERNATE_WEFT_STACK
OUTPUT_TYPE
Definition: Misc.h:105
@ PATTERN3D_NOYARN
@ PATTERN3D_XYARN
@ PATTERN3D_YYARN
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