TexGen
TextileOrthogonal.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
21#include "PrecompiledHeaders.h"
22#include "TextileOrthogonal.h"
23#include "SectionHybrid.h"
24#include "SectionPolygon.h"
25#include "SectionRectangle.h"
26#include "PatternDraft.h"
27//#define SHINY_PROFILER 0
28
29//#include "Shiny.h"
30
31# define TOL 0.000001
32# define MAX_VOLUME_FRACTION 0.87 //0.78
33# define TOP 1
34# define BOTTOM 0
35
36using namespace TexGen;
37
38CTextileOrthogonal::CTextileOrthogonal(int iNumXYarns, int iNumYYarns, double dXSpacing, double dYSpacing, double dXHeight, double dYHeight, bool bRefine, bool bWeavePattern)
39: CTextile3DWeave( iNumXYarns, iNumYYarns, dXSpacing, dYSpacing, dXHeight, dYHeight, bRefine)
40{
41 m_bWeavePattern = bWeavePattern;
42 m_WeftYarns.resize( iNumXYarns * iNumYYarns );
43}
44
46: CTextile3DWeave(Element)
47{
48}
49
51{
52}
53
54void CTextileOrthogonal::PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
55{
56 CTextile3DWeave::PopulateTiXmlElement(Element, OutputType);
57}
58
60{
61 if (x<0 || x>=m_iNumYYarns || y<0 || y>=m_iNumXYarns)
62 {
63 TGERROR("Unable to swap position, index out of range: " << x << ", " << y);
64 return;
65 }
66 vector<PATTERN3D> &Cell = GetCell(x, y);
67 int size = Cell.size();
68
69 // Binder yarns are at either top or bottom of cell
70 int bTemp;
71 bTemp = Cell[0];
72 Cell[0] = Cell[size-1];
73 Cell[size-1] = bTemp;
74 m_bNeedsBuilding = true;
75}
76
77void CTextileOrthogonal::SetupLayers( int iNumWarpLayers, int iNumWeftLayers, int iNumBinderLayers )
78{
80
81 // Add alternating layers
82 while( iNumWeftLayers > 1 )
83 {
84 AddYLayers();
85 if ( iNumWarpLayers > 0 )
86 {
88 iNumWarpLayers--;
89 }
90 iNumWeftLayers--;
91 }
92 // If more warp than weft layers, add remaining layers
93 while( iNumWarpLayers > 0 )
94 {
96 iNumWarpLayers--;
97 }
98 // Must have weft layer next to binders
99 AddYLayers();
100
102}
103
105{
106 if ( m_bWeavePattern )
107 {
109 }
110
111 // x yarns are parallel to the x axis - warp and binder yarns
112 // y yarns are parallel to the y axis - weft yarns
113
114 //PROFILE_BEGIN(Begin);
115 m_Yarns.clear();
116 m_YYarns.clear();
117 m_XYarns.clear();
118
119 m_YYarns.resize(m_iNumYYarns);
120 m_XYarns.resize(m_iNumXYarns);
121
122 m_dMinZ = 0.0;
123 m_dMaxZ = 0.0;
124
125 /*if (!Valid())
126 return false;*/
127 bool bSuccess = true;
128
129 TGLOGINDENT("Building textile weave \"" << GetName() << "\"");
130 m_bNeedsBuilding = false;
131
132 vector<int> Yarns;
133
134 double x, y, z;
135
136 // Add x yarns (yarns parallel to the x axis)
137 int i, j, k, iYarn;
138 y = 0;
139 for (i=0; i<m_iNumXYarns; ++i)
140 {
141 y += m_XYarnData[i].dSpacing/2.0;
142 x = 0;
143 Yarns.clear();
144 // For each stack of x yarns add a node at the crossover with each y yarn
145 // Continue until j == m_iNumYYarns so that get start and end nodes the same
146 for (j=0; j<=m_iNumYYarns; ++j)
147 {
148 // Get the cell for the
149 const vector<PATTERN3D> &Cell = GetCell(j%m_iNumYYarns, i);
150 int NextCellIndex;
151 NextCellIndex = FindNextCellIndex(i);
152 const vector<PATTERN3D> &NextCell = GetCell(j%m_iNumYYarns, NextCellIndex );
153
154 const vector<PATTERN3D> &NextYCell = GetCell((j+1)%m_iNumYYarns, i );
155 // Create the yarns
156 if (j==0)
157 {
158 for (k=0; k<(int)Cell.size(); ++k)
159 {
160 if (Cell[k] == PATTERN3D_XYARN)
161 {
162 Yarns.push_back(AddYarn(CYarn()));
163 }
164 }
165 }
166 m_XYarns[i] = Yarns;
167 iYarn = 0;
168 // Increment x coordinate to position of next y yarn
169 x += m_YYarnData[j%m_iNumYYarns].dSpacing/2.0;
170
171 // Work upwards through cell: Cell[0] and Cell[max] are always binder yarn entries
172 z = 0.0;
173 for (k=0; k<(int)Cell.size(); ++k)
174 {
175 if (Cell[k] == PATTERN3D_XYARN) // x yarn so add node
176 {
177 double dHalfHeight = m_XYarnData[i].dHeight / 2.0;
178 if ( k == 0 && IsBinderYarn(i) )
179 {
180 z -= dHalfHeight + m_dGapSize;
181 if ( (z - dHalfHeight) < m_dMinZ )
182 m_dMinZ = z - dHalfHeight;
183 }
184 else
185 z += dHalfHeight;
186 m_Yarns[Yarns[iYarn]].AddNode(CNode(XYZ(x, y, z), XYZ(1, 0, 0)));
187 ++iYarn;
188 if ( k == (int)Cell.size()-1 && IsBinderYarn(i) ) // Don't need to add gap above top binder yarn
189 z += dHalfHeight;
190 else
191 z += dHalfHeight + m_dGapSize;
192 if ( z > m_dMaxZ )
193 m_dMaxZ = z;
194 }
195 else if ( Cell[k] == PATTERN3D_YYARN ) // y yarn so add y yarn height
196 {
197 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
198 }
199 else if ( k > 0 )// PATTERN3D_NOYARN and not on bottom binder layer so add height of adjacent yarn
200 {
201 if ( NextCell[k] == PATTERN3D_XYARN )
202 {
203 z += m_XYarnData[NextCellIndex].dHeight + m_dGapSize;
204 }
205 else if ( NextCell[k] == PATTERN3D_YYARN )
206 {
207 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
208 }
209 else // PATTERN3D_NOYARN
210 {
211 if ( NextYCell[k] == PATTERN3D_YYARN )
212 {
213 z += m_YYarnData[(j+1)%m_iNumYYarns].dHeight + m_dGapSize;
214 }
215 else if ( NextYCell[k] == PATTERN3D_XYARN )
216 {
217 z += m_XYarnData[i].dHeight + m_dGapSize;
218 }
219 //else
220 //{
221 // Does this ever happen!
222 //}
223 }
224 }
225 }
226 if (j<m_iNumYYarns)
227 x += m_YYarnData[j].dSpacing/2.0;
228 }
229 y += m_XYarnData[i].dSpacing/2.0;
230 }
231
232 // Add y yarns (yarns parallel to the y axis)
233 x = 0;
234 for (j=0; j<m_iNumYYarns; ++j)
235 {
236 y = 0;
237 Yarns.clear();
238 x += m_YYarnData[j].dSpacing/2.0;
239
240 // For each stack of y yarns add a node at the crossover with each x yarn
241 // Continue until j == m_iNumXYarns so that get start and end nodes the same
242 for (i=0; i<=m_iNumXYarns; ++i)
243 {
244 const vector<PATTERN3D> &Cell = GetCell(j, i%m_iNumXYarns);
245
246 int NextCellIndex = FindNextCellIndex(i);
247 const vector<PATTERN3D> &NextCell = GetCell(j%m_iNumYYarns, NextCellIndex%m_iNumXYarns);
248
249 const vector<PATTERN3D> &NextYCell = GetCell((j+1)%m_iNumYYarns, i%m_iNumXYarns );
250 // Create the yarns
251 if (i==0)
252 {
253 for (k=0; k<(int)Cell.size(); ++k)
254 {
255 if (Cell[k] == PATTERN3D_YYARN)
256 {
257 Yarns.push_back(AddYarn(CYarn()));
258 }
259 }
260 }
261 m_YYarns[j] = Yarns;
262 iYarn = 0;
263 // Increment y coordinate to position of next x yarn
264 y += m_XYarnData[i%m_iNumXYarns].dSpacing/2.0;
265 z = 0.0;
266 // Work upwards through cell
267 for (k=0; k<(int)Cell.size(); ++k)
268 {
269 if (Cell[k] == PATTERN3D_YYARN) // y yarn so add node
270 {
271 double dHalfHeight = m_YYarnData[j].dHeight / 2.0;
272 z += dHalfHeight;
273 m_Yarns[Yarns[iYarn]].AddNode(CNode(XYZ(x, y, z), XYZ(0, 1, 0)));
274 ++iYarn;
275 z += dHalfHeight + m_dGapSize;
276 }
277 else if ( Cell[k] == PATTERN3D_XYARN && k > 0 ) // Don't adjust z if it's the binder yarn
278 {
279 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
280 }
281 else if ( k > 0 ) // PATTERN3D_NOYARN and not on bottom binder layer
282 {
283 if ( NextCell[k] == PATTERN3D_XYARN )
284 {
285 z += m_XYarnData[NextCellIndex%m_iNumXYarns].dHeight + m_dGapSize;
286 }
287 else if ( NextCell[k] == PATTERN3D_YYARN )
288 {
289 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
290 }
291 else // PATTERN3D_NOYARN
292 {
293 if ( NextYCell[k] == PATTERN3D_YYARN )
294 {
295 z += m_YYarnData[(j+1)%m_iNumYYarns].dHeight + m_dGapSize;
296 }
297 else if ( NextYCell[k] == PATTERN3D_XYARN )
298 {
299 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
300 }
301 //else
302 //{
303 // Does this ever happen!
304 //}
305 }
306 }
307 }
308 if (i<m_iNumXYarns)
309 y += m_XYarnData[i].dSpacing/2.0;
310 }
311 x += m_YYarnData[j].dSpacing/2.0;
312 }
313
314 // Assign sections and properties to the yarns
315 vector<int>::iterator itpYarn;
316 double dWidth, dHeight;
317 for (i=0; i<m_iNumXYarns; ++i)
318 {
319 dWidth = m_XYarnData[i].dWidth;
320 dHeight = m_XYarnData[i].dHeight;
321 CSectionPowerEllipse Section(dWidth, dHeight, IsBinderYarn(i) ? m_dBinderPower : m_dWarpPower );
322 if (m_pSectionMesh)
324
325 for (itpYarn = m_XYarns[i].begin(); itpYarn != m_XYarns[i].end(); ++itpYarn)
326 {
327 // If refining will be changing the sections at each node so use CYarnSectionInterpNode
328 if ( m_bRefine /*&& !IsBinderYarn(i)*/)
329 {
330 CYarnSectionInterpNode YarnSections;
331 for ( j = 0; j <= m_iNumYYarns; ++j )
332 {
333 YarnSections.AddSection( Section );
334 }
335 m_Yarns[*itpYarn].AssignSection( YarnSections );
336 }
337 else // otherwise constant section along yarn
338 {
339 m_Yarns[*itpYarn].AssignSection(CYarnSectionConstant(Section));
340 }
341
342 int iType = IsBinderYarn(i) ? BINDER : WARP;
343 SetYarnProperties( m_Yarns[*itpYarn], iType );
344 }
345 }
346 for (i=0; i<m_iNumYYarns; ++i)
347 {
348 dWidth = m_YYarnData[i].dWidth;
349 dHeight = m_YYarnData[i].dHeight;
350 CSectionPowerEllipse Section(dWidth, dHeight, m_dWeftPower );
351 if (m_pSectionMesh)
353
354 for (itpYarn = m_YYarns[i].begin(), j=0; itpYarn != m_YYarns[i].end(); ++itpYarn, ++j)
355 {
356 if ( m_bRefine )
357 {
358 CYarnSectionInterpNode YarnSections;
359 for ( k = 0; k <= m_iNumXYarns; ++k )
360 {
361 YarnSections.AddSection( Section );
362 }
363 m_Yarns[*itpYarn].AssignSection( YarnSections );
364 }
365 else
366 {
367 m_Yarns[*itpYarn].AssignSection(CYarnSectionConstant(Section));
368 }
369 SetYarnProperties( m_Yarns[*itpYarn], WEFT );
370 }
371 }
372
373 // Add repeats and set interpolation
374 dWidth = GetWidth();
375 dHeight = GetHeight();
376 vector<CYarn>::iterator itYarn;
377 for (itYarn = m_Yarns.begin(); itYarn != m_Yarns.end(); ++itYarn)
378 {
379 itYarn->AssignInterpolation(CInterpolationBezier());
380 itYarn->SetResolution(m_iResolution);
381 itYarn->AddRepeat(XYZ(dWidth, 0, 0));
382 itYarn->AddRepeat(XYZ(0, dHeight, 0));
383 }
384
385 // Refine yarns
386 if ( m_bRefine && m_dFabricThickness > 0.0 )
387 {
389
390 if ( !AdjustMidLayerHeights() ) // Try to change total thickness of layers, excluding top & bottom weft layers
391 { // May not achieve if can't stay within maximum Vf without exceeding yarn spacing
392 bSuccess = false;
393 }
394 else
395 {
396 AdjustOuterWeftYarns(); // Change outer weft yarns to hybrid section.
398 }
399 }
400
401 ShapeBinderYarns(); // Add nodes to binder yarns to follow profile of top & bottom weft yarns
402
403
404
405 //PROFILE_END();
406 //PROFILER_UPDATE();
407 //PROFILER_OUTPUT("ProfileOutput.txt");
408 return bSuccess;
409}
410
412{
413 // x yarns are parallel to the x axis - warp and binder yarns
414 // y yarns are parallel to the y axis - weft yarns
415
416 //PROFILE_BEGIN(Begin);
417 m_Yarns.clear();
418 m_YYarns.clear();
419 m_XYarns.clear();
420
421 m_YYarns.resize(m_iNumYYarns);
422 m_XYarns.resize(m_iNumXYarns);
423
424 m_dMinZ = 0.0;
425 m_dMaxZ = 0.0;
426
427 /*if (!Valid())
428 return false;*/
429 bool bSuccess = true;
430
431 TGLOGINDENT("Building textile weave \"" << GetName() << "\"");
432
433 vector<int> Yarns;
434
435 double x, y, z;
436
437 // Add x yarns (yarns parallel to the x axis)
438 int i, j, k, iYarn;
439 y = 0;
440 for (i=0; i<m_iNumXYarns; ++i)
441 {
442 y += m_XYarnData[i].dSpacing/2.0;
443 x = 0;
444 Yarns.clear();
445 // For each stack of x yarns add a node at the crossover with each y yarn
446 // Continue until j == m_iNumYYarns so that get start and end nodes the same
447 for (j=0; j<=m_iNumYYarns; ++j)
448 {
449 // Get the cell for the
450 const vector<PATTERN3D> &Cell = GetCell(j%m_iNumYYarns, i);
451 int NextCellIndex;
452 NextCellIndex = FindNextCellIndex(i);
453 const vector<PATTERN3D> &NextCell = GetCell(j%m_iNumYYarns, NextCellIndex );
454
455
456 // Create the yarns
457 if (j==0)
458 {
459 for (k=0; k<(int)Cell.size(); ++k)
460 {
461 if (Cell[k] == PATTERN3D_XYARN)
462 {
463 Yarns.push_back(AddYarn(CYarn()));
464 }
465 }
466 }
467 m_XYarns[i] = Yarns;
468 iYarn = 0;
469 // Increment x coordinate to position of next y yarn
470 x += m_YYarnData[j%m_iNumYYarns].dSpacing/2.0;
471
472 // Work upwards through cell: Cell[0] and Cell[max] are always binder yarn entries
473 z = 0.0;
474 for (k=0; k<(int)Cell.size(); ++k)
475 {
476 if (Cell[k] == PATTERN3D_XYARN) // x yarn so add node
477 {
478 double dHalfHeight = m_XYarnData[i].dHeight / 2.0;
479 if ( k == 0 && IsBinderYarn(i) )
480 {
481 z -= dHalfHeight + m_dGapSize;
482 if ( (z - dHalfHeight) < m_dMinZ )
483 m_dMinZ = z - dHalfHeight;
484 }
485 else
486 z += dHalfHeight;
487 m_Yarns[Yarns[iYarn]].AddNode(CNode(XYZ(x, y, z), XYZ(1, 0, 0)));
488 ++iYarn;
489 if ( k == (int)Cell.size()-1 && IsBinderYarn(i) ) // Don't need to add gap above top binder yarn
490 z += dHalfHeight;
491 else
492 z += dHalfHeight + m_dGapSize;
493 if ( z > m_dMaxZ )
494 m_dMaxZ = z;
495 }
496 else if ( Cell[k] == PATTERN3D_YYARN ) // y yarn so add y yarn height
497 {
498 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
499 }
500 else if ( k > 0 )// PATTERN3D_NOYARN and not on bottom binder layer so add height of adjacent yarn
501 {
502 if ( NextCell[k] == PATTERN3D_XYARN )
503 {
504 z += m_XYarnData[NextCellIndex].dHeight + m_dGapSize;
505 }
506 else if ( NextCell[k] == PATTERN3D_YYARN )
507 {
508 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
509 }
510 else // PATTERN3D_NOYARN
511 {
512 if ( k != (int)Cell.size()- 1 ) // If at top and no yarn don't need to bother adding to height
513 {
514 int NextYCellIndex = FindNextYCellIndex( j, i, k );
515 const vector<PATTERN3D> &NextYCell = GetCell(NextYCellIndex, i );
516 if ( NextYCell[k] == PATTERN3D_YYARN )
517 {
518 z += m_YYarnData[(j+1)%m_iNumYYarns].dHeight + m_dGapSize;
519 }
520 else if ( NextYCell[k] == PATTERN3D_XYARN )
521 {
522 z += m_XYarnData[i].dHeight + m_dGapSize;
523 }
524 //else
525 //{
526 // Does this ever happen!
527 //}
528 }
529 }
530 }
531 }
532 if (j<m_iNumYYarns)
533 x += m_YYarnData[j].dSpacing/2.0;
534 }
535 y += m_XYarnData[i].dSpacing/2.0;
536 }
537
538 // Add y yarns (yarns parallel to the y axis)
539 // Create yarns first so that won't cause problem if yarns cross over
540 m_iYYarnOffset = m_Yarns.size();
541 for ( j=0; j<m_iNumYYarns; ++j)
542 {
543 Yarns.clear();
544
545 const vector<PATTERN3D> &Cell = GetCell(j, 0);
546 for (k=0; k<(int)Cell.size(); ++k)
547 {
548 if (Cell[k] == PATTERN3D_YYARN)
549 {
550 Yarns.push_back(AddYarn(CYarn()));
551 }
552 }
553
554 m_YYarns[j] = Yarns;
555 }
556
557 x = 0;
558 for (j=0; j<m_iNumYYarns; ++j)
559 {
560 y = 0;
561 Yarns.clear();
562 x += m_YYarnData[j].dSpacing/2.0;
563
564 // For each stack of y yarns add a node at the crossover with each x yarn
565 // Continue until j == m_iNumXYarns so that get start and end nodes the same
566 //for (i=0; i<=m_iNumXYarns; ++i)
567 for (i=0; i<m_iNumXYarns; ++i)
568 {
569 const vector<PATTERN3D> &Cell = GetCell(j, i%m_iNumXYarns);
570 const vector<int> &YarnCell = GetYarnCell(j, i%m_iNumXYarns);
571
572 int NextCellIndex = FindNextCellIndex(i);
573 const vector<PATTERN3D> &NextCell = GetCell(j%m_iNumYYarns, NextCellIndex%m_iNumXYarns);
574
575
576
577 //iYarn = 0;
578 // Increment y coordinate to position of next x yarn
579 y += m_XYarnData[i%m_iNumXYarns].dSpacing/2.0;
580 z = 0.0;
581 // Work upwards through cell
582 for (k=0; k<(int)Cell.size(); ++k)
583 {
584 if (Cell[k] == PATTERN3D_YYARN) // y yarn so add node
585 {
586 double dHalfHeight = m_YYarnData[j].dHeight / 2.0;
587 z += dHalfHeight;
588 //m_Yarns[Yarns[iYarn]].AddNode(CNode(XYZ(x, y, z), XYZ(0, 1, 0)));
589 m_Yarns[YarnCell[k]+m_iYYarnOffset].AddNode(CNode(XYZ(x, y, z), XYZ(0, 1, 0)));
590 //++iYarn;
591 z += dHalfHeight + m_dGapSize;
592 }
593 else if ( Cell[k] == PATTERN3D_XYARN && k > 0 ) // Don't adjust z if it's the binder yarn
594 {
595 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
596 }
597 else if ( k > 0 ) // PATTERN3D_NOYARN and not on bottom binder layer
598 {
599 if ( NextCell[k] == PATTERN3D_XYARN )
600 {
601 z += m_XYarnData[NextCellIndex%m_iNumXYarns].dHeight + m_dGapSize;
602 }
603 else if ( NextCell[k] == PATTERN3D_YYARN )
604 {
605 z += m_YYarnData[j%m_iNumYYarns].dHeight + m_dGapSize;
606 }
607 else // PATTERN3D_NOYARN
608 {
609 //int NextYCellIndex = FindNextYCellIndex( j, i, k );
610 //const vector<PATTERN3D> &NextYCell = GetCell(NextYCellIndex, i%m_iNumXYarns );
611 int NextYCellIndex = FindPrevYCellIndex( j, i, k );
612 const vector<PATTERN3D> &NextYCell = GetCell(NextYCellIndex, i%m_iNumXYarns );
613 //const vector<PATTERN3D> &NextYCell = GetCell((j+1)%m_iNumYYarns, i%m_iNumXYarns );
614 if ( NextYCell[k] == PATTERN3D_YYARN )
615 {
616 z += m_YYarnData[(j+1)%m_iNumYYarns].dHeight + m_dGapSize;
617 }
618 else if ( NextYCell[k] == PATTERN3D_XYARN )
619 {
620 z += m_XYarnData[i%m_iNumXYarns].dHeight + m_dGapSize;
621 }
622 //else
623 //{
624 // Does this ever happen!
625 //}
626 }
627 }
628 }
629 if (i<m_iNumXYarns)
630 y += m_XYarnData[i].dSpacing/2.0;
631 }
632 x += m_YYarnData[j].dSpacing/2.0;
633 }
634
635 // Assign sections and properties to the yarns
636 vector<int>::iterator itpYarn;
637 double dWidth, dHeight;
638 for (i=0; i<m_iNumXYarns; ++i)
639 {
640 dWidth = m_XYarnData[i].dWidth;
641 dHeight = m_XYarnData[i].dHeight;
642 CSectionPowerEllipse Section(dWidth, dHeight, IsBinderYarn(i) ? m_dBinderPower : m_dWarpPower );
643 if (m_pSectionMesh)
645
646 for (itpYarn = m_XYarns[i].begin(); itpYarn != m_XYarns[i].end(); ++itpYarn)
647 {
648 // If refining will be changing the sections at each node so use CYarnSectionInterpNode
649 if ( m_bRefine /*&& !IsBinderYarn(i)*/)
650 {
651 CYarnSectionInterpNode YarnSections;
652 for ( j = 0; j <= m_iNumYYarns; ++j )
653 {
654 YarnSections.AddSection( Section );
655 }
656 m_Yarns[*itpYarn].AssignSection( YarnSections );
657 }
658 else // otherwise constant section along yarn
659 {
660 m_Yarns[*itpYarn].AssignSection(CYarnSectionConstant(Section));
661 }
662
663 int iType = IsBinderYarn(i) ? BINDER : WARP;
664 SetYarnProperties( m_Yarns[*itpYarn], iType );
665 }
666 }
667 for (i=0; i<m_iNumYYarns; ++i)
668 {
669 dWidth = m_YYarnData[i].dWidth;
670 dHeight = m_YYarnData[i].dHeight;
671 CSectionPowerEllipse Section(dWidth, dHeight, m_dWeftPower );
672 if (m_pSectionMesh)
674
675 for (itpYarn = m_YYarns[i].begin(), j=0; itpYarn != m_YYarns[i].end(); ++itpYarn, ++j)
676 {
677 if ( m_bRefine )
678 {
679 CYarnSectionInterpNode YarnSections;
680 for ( k = 0; k <= m_iNumXYarns; ++k )
681 {
682 YarnSections.AddSection( Section );
683 }
684 m_Yarns[*itpYarn].AssignSection( YarnSections );
685 }
686 else
687 {
688 m_Yarns[*itpYarn].AssignSection(CYarnSectionConstant(Section));
689 }
690 SetYarnProperties( m_Yarns[*itpYarn], WEFT );
691 }
692 }
693
694 // Add repeats and set interpolation
695 dWidth = GetWidth();
696 dHeight = GetHeight();
697 vector<CYarn>::iterator itYarn;
698 for (itYarn = m_Yarns.begin(); itYarn != m_Yarns.end(); ++itYarn)
699 {
700 itYarn->AssignInterpolation(CInterpolationBezier());
701 itYarn->SetResolution(m_iResolution);
702 //itYarn->AddRepeat(XYZ(dWidth, 0, 0));
703 //itYarn->AddRepeat(XYZ(0, dHeight, 0));
704 }
705
706 // Refine yarns
707 /*if ( m_bRefine && m_dFabricThickness > 0.0 )
708 {
709 CheckBinderWidths();
710
711 if ( !AdjustMidLayerHeights() ) // Try to change total thickness of layers, excluding top & bottom weft layers
712 { // May not achieve if can't stay within maximum Vf without exceeding yarn spacing
713 bSuccess = false;
714 }
715 else
716 {
717 AdjustOuterWeftYarns(); // Change outer weft yarns to hybrid section.
718 AdjustBinderYarns();
719 }
720 }*/
721
722 ShapeBinderYarns(); // Add nodes to binder yarns to follow profile of top & bottom weft yarns
723
724
725
726 //PROFILE_END();
727 //PROFILER_UPDATE();
728 //PROFILER_OUTPUT("ProfileOutput.txt");
729 return bSuccess;
730}
731
732
734{
735 //PROFILE_FUNC();
736 for ( int j = 0; j < m_iNumXYarns; ++j )
737 {
738 if ( IsBinderYarn( j ) )
739 {
740 int CurrentNode = 0;
741 for ( int i = 0; i < m_iNumYYarns; ++i )
742 {
743 CurrentNode = AddBinderNodes( CurrentNode, i, j );
744 CurrentNode++;
745 }
747 }
748 }
749}
750
751int CTextileOrthogonal::AddBinderNodes( int CurrentNode, int i, int j ) const
752{
753 //PROFILE_FUNC();
754 const vector<PATTERN3D> &Cell = GetCell(i,j);
755 const vector<PATTERN3D> &NextCell = GetCell( (i+1)%m_iNumYYarns, j );
756 const vector<PATTERN3D> &PrevCell = GetCell( (i+m_iNumYYarns-1)%m_iNumYYarns, j );
757
758 int iBinderIndex = Cell.size() - 1;
759 XY SectionPoint;
760
761 if ( iBinderIndex < 1 )
762 return CurrentNode;
763
764 double dDefaultBinderOffset = m_XYarnData[j].dHeight/2.0;
765 CSectionPowerEllipse DefaultBinderSection(m_XYarnData[j].dWidth, m_XYarnData[j].dHeight, m_dBinderPower );
766
767 if ( Cell[iBinderIndex] != PATTERN3D_XYARN )
768 {
769 iBinderIndex = FindBinderHeight( Cell );
770 }
771
772 if ( iBinderIndex == Cell.size()-1 && Cell[iBinderIndex] == PATTERN3D_XYARN && Cell[iBinderIndex-1] == PATTERN3D_YYARN ) // Binder yarn at top and yarn underneath is weft yarn
773 {
774 int BinderYarnIndex = GetYarnIndex( i, j, iBinderIndex );
775 int WeftYarnIndex;
776 if ( m_bWeavePattern )
777 WeftYarnIndex = GetWeavePatternYarnIndex( i, j, iBinderIndex-1 );
778 else
779 WeftYarnIndex = GetYarnIndex( i, j, iBinderIndex-1 );
780
781 if ( BinderYarnIndex == -1 || WeftYarnIndex == -1 )
782 return CurrentNode;
783
784 XYZ WeftNode = m_Yarns[WeftYarnIndex].GetNode( j )->GetPosition();
785 XYZ BinderNode = m_Yarns[BinderYarnIndex].GetNode( CurrentNode )->GetPosition();
786
787 // Get cross section of weft yarn
788 CSection* YarnSection = GetCrossSection( WeftYarnIndex, j );
789 if ( YarnSection == NULL )
790 return CurrentNode;
791
792 string WeftType = YarnSection->GetType();
793 if ( WeftType != "CSectionPowerEllipse" && WeftType != "CSectionHybrid" )
794 return CurrentNode;
795
796
797 CSection* BinderYarnSection = GetCrossSection( BinderYarnIndex, CurrentNode );
798 string BinderType = BinderYarnSection->GetType();
799 double dBinderOffset = dDefaultBinderOffset;
800 if ( BinderType == "CSectionHybrid" )
801 {
802 dBinderOffset = GetHybridHeight( (CSectionHybrid*)BinderYarnSection );
803 }
804
805 int PrevCellBinder = FindBinderHeight( PrevCell );
806
807 if ( PrevCellBinder < iBinderIndex ) // Insert points around Top left quadrant of weft yarn
808 {
809 // Insert point at left hand end of weft yarn.
810 XYZ NewNode = WeftNode;
811 SectionPoint = GetSectionPoint( YarnSection, 0.5 );
812 map<pair<int, int>, YARNDATA>::iterator itBinderData = m_BinderData.find( make_pair((i-1+m_iNumYYarns)%m_iNumYYarns,j) );
813
814 NewNode.x = NewNode.x + SectionPoint.x - m_dGapSize;
815 if ( m_bRefine && itBinderData != m_BinderData.end() )
816 NewNode.x -= itBinderData->second.dHeight / 2.0;
817 else
818 NewNode.x -= dDefaultBinderOffset;
819 NewNode.z = NewNode.z + SectionPoint.y;
820 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode);
821
822 if ( m_bRefine )
823 ReplaceThroughBinderSection( BinderYarnIndex, CurrentNode, DefaultBinderSection, itBinderData );
824
825 if ( CurrentNode == 0 ) // Change last node to match start
826 {
827 ReplaceLastNode( BinderYarnIndex, NewNode, BinderNode );
828 if ( m_bRefine )
829 ReplaceThroughBinderSection( BinderYarnIndex, m_Yarns[BinderYarnIndex].GetNumNodes() - 1, DefaultBinderSection, itBinderData );
830 }
831 CurrentNode++;
832
833 // Insert points between new end node and centre, top node
834 double t = m_bRefine ? 0.4 : 0.45;
835 int i = m_bRefine ? 3 : 4;
836 while( i-- > 0)
837 {
838 InsertBinderNode( YarnSection, t, WeftNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
839 t -= 0.05;
840 }
841 }
842
843 int NextCellBinder = FindBinderHeight( NextCell );
844
845 if ( NextCellBinder < iBinderIndex ) // Insert points around upper right quadrant of weft
846 {
847 XYZ NewNode = WeftNode;
848 CurrentNode++; // Need to insert after node (ie before next node)
849 double t = 0.2;
850 int k = m_bRefine ? 3 : 4;
851 while( k-- > 0 )
852 {
853 InsertBinderNode( YarnSection, t, WeftNode, CurrentNode, BinderYarnIndex, dBinderOffset + m_dGapSize );
854 if ( m_bRefine )
855 ReplaceYarnSection( BinderYarnIndex, CurrentNode-1, *BinderYarnSection );
856 t -= 0.05;
857 }
858
859 CurrentNode--;
860 SectionPoint = GetSectionPoint( YarnSection, 0.0 );
861
862 map<pair<int, int>, YARNDATA>::iterator itBinderData = m_BinderData.find( make_pair(i,j) );
863 NewNode = WeftNode;
864 NewNode.x = NewNode.x + SectionPoint.x + m_dGapSize;
865 if ( m_bRefine && itBinderData != m_BinderData.end() )
866 NewNode.x += itBinderData->second.dHeight / 2.0;
867 else
868 NewNode.x += dDefaultBinderOffset;
869 NewNode.z = NewNode.z + SectionPoint.y;
870 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode+1 );
871 CurrentNode++;
872
873 if ( m_bRefine )
874 ReplaceThroughBinderSection( BinderYarnIndex, CurrentNode, DefaultBinderSection, itBinderData );
875 }
876 delete YarnSection;
877 delete BinderYarnSection;
878 }
879 // Binder yarn at bottom and yarn above is weft yarn
880 else if ( iBinderIndex == 0 && Cell[iBinderIndex] == PATTERN3D_XYARN && Cell[iBinderIndex+1] == PATTERN3D_YYARN )
881 {
882 int BinderYarnIndex = GetYarnIndex( i, j, iBinderIndex );
883 int WeftYarnIndex;
884 if ( m_bWeavePattern )
885 WeftYarnIndex = GetWeavePatternYarnIndex( i, j, iBinderIndex+1 );
886 else
887 WeftYarnIndex = GetYarnIndex( i, j, iBinderIndex+1 );
888
889 if ( BinderYarnIndex == -1 || WeftYarnIndex == -1 )
890 return CurrentNode;
891
892 // Get cross section of weft yarn
893 CSection* YarnSection = GetCrossSection( WeftYarnIndex, j );
894 if ( YarnSection == NULL )
895 return CurrentNode;
896
897 string WeftType = YarnSection->GetType();
898 if ( WeftType != "CSectionPowerEllipse" && WeftType != "CSectionHybrid" )
899 {
900 delete YarnSection;
901 return CurrentNode;
902 }
903
904 CSection* BinderYarnSection = GetCrossSection( BinderYarnIndex, CurrentNode );
905 string BinderType = BinderYarnSection->GetType();
906 double dBinderOffset = dDefaultBinderOffset;
907 if ( BinderType == "CSectionHybrid" )
908 {
909 dBinderOffset = GetHybridHeight( (CSectionHybrid*)BinderYarnSection );
910 }
911
912 XYZ WeftNode = m_Yarns[WeftYarnIndex].GetNode( j )->GetPosition();
913 XYZ BinderNode = m_Yarns[BinderYarnIndex].GetNode( CurrentNode )->GetPosition();
914
915 int PrevCellBinder = FindBinderHeight( PrevCell );
916
917 if ( PrevCellBinder > iBinderIndex ) // Insert points around lower left quadrant of weft yarn
918 {
919 XYZ NewNode = WeftNode;
920 map<pair<int, int>, YARNDATA>::iterator itBinderData = m_BinderData.find( make_pair((i-1+m_iNumYYarns)%m_iNumYYarns,j) );
921
922 SectionPoint = GetSectionPoint( YarnSection, 0.5 );
923 NewNode.x = NewNode.x + SectionPoint.x - m_dGapSize;
924 if ( m_bRefine && itBinderData != m_BinderData.end() )
925 NewNode.x -= itBinderData->second.dHeight / 2.0;
926 else
927 NewNode.x -= dDefaultBinderOffset;
928 NewNode.z = NewNode.z + SectionPoint.y;
929 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode);
930
931 if ( m_bRefine )
932 ReplaceThroughBinderSection( BinderYarnIndex, CurrentNode, DefaultBinderSection, itBinderData );
933
934 if ( CurrentNode == 0 ) // Change last node to match start
935 {
936 ReplaceLastNode( BinderYarnIndex, NewNode, BinderNode );
937 if ( m_bRefine )
938 ReplaceThroughBinderSection( BinderYarnIndex, m_Yarns[BinderYarnIndex].GetNumNodes() - 1, DefaultBinderSection, itBinderData );
939 }
940 CurrentNode++;
941
942 NewNode = WeftNode;
943 double t = m_bRefine ? 0.6 : 0.55;
944 int k = m_bRefine ? 3 : 4;
945 while ( k-- > 0 )
946 {
947 InsertBinderNode( YarnSection, t, WeftNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
948 t += 0.05;
949 }
950 }
951
952 int NextCellBinder = FindBinderHeight( NextCell );
953
954 if ( NextCellBinder > iBinderIndex ) // Insert points around lower right quadrant of weft yarn
955 {
956 XYZ NewNode = WeftNode;
957 CurrentNode++; // Need to insert after node (ie before next node)
958 double t = 0.8;
959 int k = m_bRefine ? 3 : 4;
960 while ( k-- > 0 )
961 {
962 InsertBinderNode( YarnSection, t, WeftNode, CurrentNode, BinderYarnIndex, -(dBinderOffset + m_dGapSize) );
963 if ( m_bRefine )
964 ReplaceYarnSection( BinderYarnIndex, CurrentNode-1, *BinderYarnSection );
965 t += 0.05;
966 }
967
968 CurrentNode--;
969 map<pair<int, int>, YARNDATA>::iterator itBinderData = m_BinderData.find( make_pair(i,j) );
970 SectionPoint = GetSectionPoint( YarnSection, 0.0 );
971 NewNode = WeftNode;
972 NewNode.x = NewNode.x + SectionPoint.x + m_dGapSize;
973 if ( m_bRefine && itBinderData != m_BinderData.end() )
974 NewNode.x += itBinderData->second.dHeight / 2.0;
975 else
976 NewNode.x += dDefaultBinderOffset;
977 NewNode.z = NewNode.z + SectionPoint.y;
978 m_Yarns[BinderYarnIndex].InsertNode( NewNode, CurrentNode+1 );
979 CurrentNode++;
980
981 if ( m_bRefine )
982 ReplaceThroughBinderSection( BinderYarnIndex, CurrentNode, DefaultBinderSection, itBinderData );
983 }
984 delete YarnSection;
985 delete BinderYarnSection;
986 }
987 return CurrentNode;
988}
989
991{
992 // Iterate through each x yarn and check widths if it's a binder yarn
993 for ( int j = 0; j < m_iNumXYarns; ++j )
994 {
995 if ( IsBinderYarn(j) )
996 {
997 int iBinderIndex = -1;
998
999 for ( int i = 0; i < m_iNumYYarns; ++i )
1000 {
1001 // Get the cells for the two weft yarns that the yarn would be passing between
1002 const vector<PATTERN3D> &Cell = GetCell(i,j);
1003 const vector<PATTERN3D> &NextCell = GetCell((i+1)%m_iNumYYarns, j);
1004 int iCellSize = Cell.size();
1005
1006 if ( Cell[0] != NextCell[0] ) // Binder is through thickness between cells
1007 { // In orthogonal weaves binder is forced to be at either top or bottom
1008 if ( iBinderIndex == -1 )
1009 {
1010 if ( Cell[0] == PATTERN3D_XYARN )
1011 iBinderIndex = GetYarnIndex(i,j,0);
1012 else
1013 iBinderIndex = GetYarnIndex(i,j,iCellSize-1);
1014 }
1015
1016 // Get initial specified cross section
1017 CSection* BinderYarnSection = GetCrossSection( iBinderIndex, i );
1018 CSectionPowerEllipse* YarnSection = (CSectionPowerEllipse*)BinderYarnSection->Copy();
1019
1020 double FibreArea = m_Yarns[iBinderIndex].GetFibreArea("mm^2"); // Actual area of fibres within yarn
1021 double InitialArea = YarnSection->GetArea(YarnSection->GetPoints(40));
1022 if ( FibreArea/InitialArea > m_dMaxVolumeFraction )
1023 {
1024 TGERROR( "Binder yarn initial volume fraction exceeds max Vf Yarn: " << iBinderIndex );
1025 delete YarnSection;
1026 return;
1027 }
1028
1029
1030 YARNDATA Binder;
1031 if ( m_XYarnData[j].dWidth > (m_XYarnData[j].dSpacing - m_dGapSize) ) // Yarn is wider than spacing
1032 { // ***Should this do check == max height check and look at actual space between warps either side?
1033 double dMaxWidth, dMaxHeight;
1034 dMaxWidth = m_XYarnData[j].dSpacing - m_dGapSize;
1035 // Calculate maximum space available between weft yarns
1036 dMaxHeight = (m_YYarnData[i].dSpacing-m_YYarnData[i].dWidth)/2.0
1037 + (m_YYarnData[(i+1)%m_iNumYYarns].dSpacing-m_YYarnData[(i+1)%m_iNumYYarns].dWidth)/2.0 - m_dGapSize;
1038 double dMaxArea = dMaxWidth * dMaxHeight; // Max area available for binder yarn to pass through
1039 Binder.dWidth = dMaxWidth;
1040 Binder.dSpacing = dMaxWidth;
1041
1042 if ( InitialArea < dMaxArea ) // Adjust height to maintain initial area whilst reducing width
1043 {
1044 Binder.dHeight = InitialArea/dMaxWidth; // Assuming will be rectangular section
1045 Binder.dSpacing = dMaxWidth;
1046 }
1047 else // Area will need to reduce so check if this would result in exceeding the max volume fraction
1048 {
1049 if ( FibreArea/dMaxArea > m_dMaxVolumeFraction )
1050 {
1051 // Wefts will need to reduce in width in order to make room for binder at max Vf
1052 // ***Valid assumption that it's the wefts that move and not and/or warps?
1053 double MaxVfArea = FibreArea/m_dMaxVolumeFraction;
1054 Binder.dHeight = MaxVfArea/dMaxWidth; // Binder width and height now set to give max possible Vf
1055 }
1056 else // Volume fraction ok
1057 {
1058 Binder.dHeight = dMaxHeight;
1059 }
1060 }
1061 m_BinderData[make_pair(i,j)] = Binder;
1062 }
1063 else // Width of binder fits into spacing between warps so make pair.
1064 { // ***This assumes that binder height < spacing between wefts - is this correct?
1065 m_BinderData[make_pair(i,j)] = m_XYarnData[j];
1066 }
1067 }
1068 }
1069 }
1070 }
1071}
1072
1074{
1075 //PROFILE_FUNC();
1076 vector<int> RectYarnIndex; // Yarn indices of yarns containing sections to be converted to rectangles
1077
1078 for ( int j = 0; j < m_iNumXYarns; ++j )
1079 {
1080 for ( int i = 0; i < m_iNumYYarns; ++i )
1081 {
1082 const vector<PATTERN3D> &Cell = GetCell(i,j);
1083 int iCellSize = Cell.size();
1084 // Have to allow for specified gap size. All reduction is taken up in yarns
1085 int iTopWeftIndex = GetYarnIndex(i,j,iCellSize-2);
1086 int iBottomWeftIndex = GetYarnIndex(i,j,1);
1087 XYZ TopNode, BottomNode;
1088 if ( iTopWeftIndex != -1 )
1089 TopNode = m_Yarns[iTopWeftIndex].GetNode(j)->GetPosition();
1090 if ( iBottomWeftIndex != -1 )
1091 BottomNode = m_Yarns[iBottomWeftIndex].GetNode(j)->GetPosition();
1092 double TargetThickness = (iCellSize-4)*m_dFabricThickness/(iCellSize-2); //Ratio of number of mid-layers to total warp/weft layers
1093 TargetThickness -= (iCellSize-3)*m_dGapSize;
1094
1095 double StartThickness = 0.0;
1096
1097 // Find the starting thickness of the mid layers (ie without binder layer and top and bottom weft layer)
1098 for ( int k = 2; k < iCellSize-2; ++k )
1099 {
1100 if ( Cell[k] == PATTERN3D_XYARN )
1101 {
1102 StartThickness += m_XYarnData[j].dHeight;
1103 }
1104 else if ( Cell[k] == PATTERN3D_YYARN )
1105 {
1106 StartThickness += m_YYarnData[i].dHeight;
1107 }
1108 else // PATTERN3D_NOYARN
1109 {
1110 StartThickness += m_XYarnData[(j+m_iNumXYarns-1)%m_iNumXYarns].dHeight;
1111 }
1112 }
1113 double CellHeightReduction = TargetThickness / StartThickness;
1114 double zDisplacement = 0.0;
1115 if ( fabs( 1.0 - CellHeightReduction ) > TOL && CellHeightReduction < 1.0 ) // If cell contains thinner yarns would result in HeightReduction > 1 in which case don't need to refine
1116 {
1117 // Work through each mid-layer yarn in the stack at the given i,j position
1118 for ( int k = 2; k < iCellSize-2; ++k )
1119 {
1120 int YarnIndex;
1121 YarnIndex = GetYarnIndex( i, j, k );
1122 XYZ Node;
1123 double MaxWidth = 0.0;
1124
1125 if ( YarnIndex == -1 )
1126 continue;
1127 if ( m_Yarns[YarnIndex].GetYarnSection()->GetType() != "CYarnSectionInterpNode" )
1128 continue;
1129 double FibreArea = m_Yarns[YarnIndex].GetFibreArea("mm^2");
1130 if ( FibreArea == 0.0 )
1131 {
1132 TGERROR("Cannot adjust height of yarn" << YarnIndex << ": No fibre area set" );
1133 continue;
1134 }
1135
1136 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[YarnIndex].GetYarnSection()->Copy();
1137 CSectionPowerEllipse* YarnSection = NULL;
1138
1139 if ( Cell[k] == PATTERN3D_XYARN )
1140 {
1141 Node = m_Yarns[YarnIndex].GetNode(i)->GetPosition();
1142 YarnSection = (CSectionPowerEllipse*)pYarnSections->GetNodeSection(i).Copy();
1143 MaxWidth = m_XYarnData[j].dSpacing - m_dGapSize;
1144 }
1145 else if ( Cell[k] == PATTERN3D_YYARN )
1146 {
1147 Node = m_Yarns[YarnIndex].GetNode(j)->GetPosition();
1148 YarnSection = (CSectionPowerEllipse*)pYarnSections->GetNodeSection(j).Copy();
1149 if ( IsBinderYarn(j) && Cell[k-1] == PATTERN3D_NOYARN ) // Binder yarn cell so no warp yarn below
1150 { // Assume this weft will be at same height as previous node
1151 XYZ PrevNode = m_Yarns[YarnIndex].GetNode(j-1)->GetPosition();
1152 zDisplacement = Node.z - PrevNode.z;
1153 Node.z = PrevNode.z;
1154 }
1155 MaxWidth = m_YYarnData[i].dSpacing - m_dGapSize;
1156 if ( IsBinderYarn(j) ) // If it's a binder yarn reduce the max width available for the weft by half the binder height on either side
1157 { // Binder data will only be available at the given position if binder is passing through thickness at that point
1158 map<pair<int, int>, YARNDATA>::iterator itBinderData;
1159
1160 itBinderData = m_BinderData.find( make_pair((i-1+m_iNumYYarns)%m_iNumYYarns,j) );
1161 if ( itBinderData != m_BinderData.end() )
1162 {
1163 MaxWidth -= itBinderData->second.dHeight / 2.0;
1164 }
1165 itBinderData = m_BinderData.find( make_pair(i,j) );
1166 if ( itBinderData != m_BinderData.end() )
1167 {
1168 MaxWidth -= itBinderData->second.dHeight / 2.0;
1169 }
1170 }
1171 }
1172
1173 if ( YarnSection == NULL || MaxWidth == 0.0)
1174 continue;
1175
1176 // Check volume fraction
1177 double OldHeight = YarnSection->GetHeight();
1178 double TargetHeight = CellHeightReduction * OldHeight;
1179 double MaxArea = MaxWidth * TargetHeight;
1180
1181 double TargetArea = YarnSection->GetArea(YarnSection->GetPoints(40));
1182 double StartVolumeFraction = FibreArea/TargetArea;
1183 double AreaVolumeFraction = FibreArea/MaxArea; // Volume fraction if yarn was rectangle filling all available space
1184 //double MaxVolumeFraction = StartVolumeFraction > MAX_VOLUME_FRACTION ? StartVolumeFraction : MAX_VOLUME_FRACTION;
1185 double MaxVolumeFraction = m_dMaxVolumeFraction; // Need some allowance for solid yarns?
1186
1187 if ( AreaVolumeFraction > MaxVolumeFraction ) // Volume fraction for space available exceeds physically achievable
1188 {
1189 TGERROR("Cannot achieve this thickness: exceeds maximum volume fraction");
1190 return false;
1191 }
1192
1193 if ( AreaVolumeFraction > StartVolumeFraction ) // Whole area gives Vf > original yarn Vf so create section to fill area
1194 {
1195 CSectionPowerEllipse Section( MaxWidth, TargetHeight, 0.0 );
1196 *YarnSection = Section;
1197 }
1198 else // Vf can be achieved maintaining original Vf so find new power and width
1199 {
1200 if ( !AdjustPowerEllipsePower( CellHeightReduction, TargetArea, YarnSection, 0.0 ) )
1201 {
1202 YarnSection->SetPower( 0.0 );
1203 AdjustPowerEllipseSectionWidth( CellHeightReduction, MaxWidth, TargetArea, YarnSection );
1204 }
1205 }
1206
1207 double HeightChange = OldHeight - YarnSection->GetHeight();
1208 if ( !( IsBinderYarn(j) && Cell[k-1] == PATTERN3D_NOYARN) )
1209 {
1210 Node.z = Node.z - 0.5*HeightChange - zDisplacement;
1211 zDisplacement += HeightChange;
1212 }
1213
1214 if ( Cell[k] != PATTERN3D_NOYARN )
1215 {
1216 // Replace node position and cross-section with new values
1217 int iIndex = Cell[k] == PATTERN3D_XYARN ? i : j;
1218 int iNumYarns = Cell[k] == PATTERN3D_XYARN ? m_iNumYYarns : m_iNumXYarns;
1219 m_Yarns[YarnIndex].ReplaceNode(iIndex,CNode(Node));
1220 pYarnSections->ReplaceSection( iIndex, *YarnSection );
1221 if ( iIndex == 0 ) // make 1st and last nodes match
1222 {
1223 XYZ EndNode = m_Yarns[YarnIndex].GetNode(iNumYarns)->GetPosition();
1224 EndNode.z = Node.z;
1225 m_Yarns[YarnIndex].ReplaceNode( iNumYarns, CNode(EndNode) );
1226 pYarnSections->ReplaceSection( iNumYarns, *YarnSection );
1227 }
1228 }
1229 // Save list of yarns which have rectangular sections in them
1230 if ( YarnSection->GetPower() == 0.0 )
1231 {
1232 vector<int>::iterator itRectYarnIndex = find( RectYarnIndex.begin(), RectYarnIndex.end(), YarnIndex );
1233 if ( itRectYarnIndex == RectYarnIndex.end() )
1234 {
1235 RectYarnIndex.push_back( YarnIndex );
1236 }
1237 }
1238 m_Yarns[YarnIndex].AssignSection(*pYarnSections);
1239 delete pYarnSections;
1240 delete YarnSection;
1241
1242
1243 }
1244 }
1245 else
1246 {
1247 return true; // No change so return
1248 }
1249 // Move top weft and binder yarns by vertical displacement
1250 // Assume it's a weft node
1251 int YarnIndex = GetYarnIndex( i, j, iCellSize-2 );
1252 XYZ Node = m_Yarns[YarnIndex].GetNode(j)->GetPosition();
1253
1254 if ( IsBinderYarn(j) && Cell[iCellSize-3] == PATTERN3D_NOYARN )
1255 {
1256 XYZ PrevNode = m_Yarns[YarnIndex].GetNode(j-1)->GetPosition();
1257 zDisplacement = Node.z - PrevNode.z;
1258 Node.z = PrevNode.z;
1259 }
1260 else
1261 {
1262 Node.z -= zDisplacement;
1263 }
1264 m_Yarns[YarnIndex].ReplaceNode( j, CNode(Node) );
1265 if ( j == 0 )
1266 {
1267 XYZ EndNode = m_Yarns[YarnIndex].GetNode(m_iNumXYarns)->GetPosition();
1268 EndNode.z = Node.z;
1269 m_Yarns[YarnIndex].ReplaceNode( m_iNumXYarns, CNode(EndNode) );
1270 }
1271 if ( Cell[iCellSize-1] == PATTERN3D_XYARN ) // ie binder yarn
1272 {
1273 YarnIndex = GetYarnIndex( i, j, iCellSize-1 );
1274 Node = m_Yarns[YarnIndex].GetNode(i)->GetPosition();
1275 Node.z -= zDisplacement;
1276 m_Yarns[YarnIndex].ReplaceNode( i, CNode(Node) );
1277 if ( i == 0 )
1278 {
1279 XYZ EndNode = m_Yarns[YarnIndex].GetNode(m_iNumYYarns)->GetPosition();
1280 EndNode.z = Node.z;
1281 m_Yarns[YarnIndex].ReplaceNode( m_iNumYYarns, CNode(EndNode) );
1282 }
1283 }
1284 }
1285 }
1286
1287 // Replace power ellipses with power = 0 with rectangular sections
1288 vector<int>::iterator itRectYarnIndex;
1289 for ( itRectYarnIndex = RectYarnIndex.begin(); itRectYarnIndex != RectYarnIndex.end(); ++itRectYarnIndex )
1290 {
1291 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[*itRectYarnIndex].GetYarnSection()->Copy();
1292 for ( int i = 0; i < pYarnSections->GetNumNodeSections(); ++i )
1293 {
1294 CSectionPowerEllipse* YarnSection = (CSectionPowerEllipse*)pYarnSections->GetNodeSection(i).Copy();
1295 if ( YarnSection->GetPower() == 0.0 )
1296 {
1297 CSectionRectangle Rect = CSectionRectangle( YarnSection->GetWidth(), YarnSection->GetHeight() );
1298 pYarnSections->ReplaceSection( i, Rect );
1299 }
1300 else // non-rectangular section in yarn with rectangular sections. Set section meshes to not have triangular corners so that volume meshing works
1301 {
1302 CSectionMeshRectangular SectionMesh = CSectionMeshRectangular( -1, false );
1303 YarnSection->AssignSectionMesh( SectionMesh );
1304 pYarnSections->ReplaceSection( i, *YarnSection );
1305 }
1306 }
1307 m_Yarns[*itRectYarnIndex].AssignSection(*pYarnSections);
1308 }
1309 return true;
1310}
1311
1313{
1314 //PROFILE_FUNC();
1315 m_dMinZ = 0.0;
1316 m_dMaxZ = 0.0;
1317
1318 for ( int j = 0; j < m_iNumXYarns; ++j )
1319 {
1320 for ( int i = 0; i < m_iNumYYarns; ++i )
1321 {
1322 const vector<PATTERN3D> &Cell = GetCell(i,j);
1323
1324 int YarnIndex;
1325 // Bottom yarn
1326 YarnIndex = GetYarnIndex( i, j, 1 );
1327
1328 if ( YarnIndex == -1 )
1329 continue;
1330 if ( m_Yarns[YarnIndex].GetYarnSection()->GetType() != "CYarnSectionInterpNode" )
1331 continue;
1332 double FibreArea = m_Yarns[YarnIndex].GetFibreArea("mm^2");
1333 if ( FibreArea == 0.0 )
1334 {
1335 TGERROR("Cannot adjust height of yarn" << YarnIndex << ": No fibre area set" );
1336 continue;
1337 }
1338
1339 // Get current section and find area
1340 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[YarnIndex].GetYarnSection()->Copy();
1341 CSectionPowerEllipse* YarnSection;
1342 YarnSection = (CSectionPowerEllipse*)pYarnSections->GetNodeSection(j).Copy();
1343 double TargetArea = YarnSection->GetArea(YarnSection->GetPoints(40))*2.0; // *2.0 because only using half in hybrid section
1344
1345 // Find total height of mid-section yarns
1346 XYZ BottomYarn = m_Yarns[YarnIndex].GetNode(j)->GetPosition();
1347 int TopYarnIndex = GetYarnIndex( i, j, Cell.size()-2 );
1348 XYZ TopYarn = m_Yarns[TopYarnIndex].GetNode(j)->GetPosition();
1349 double MidSectionHeight = TopYarn.z - BottomYarn.z - YarnSection->GetHeight();
1350
1351 double MaxVolumeFraction = m_dMaxVolumeFraction;
1352
1353 // Find maximum width for weft yarn. If binder yarn section then need to reduce width if through thickness binder on either of sides
1354 double MaxWidth = m_YYarnData[i].dSpacing - (2*m_dGapSize);
1355 if ( IsBinderYarn(j) )
1356 {
1357 map<pair<int, int>, YARNDATA>::iterator itBinderData;
1358
1359 itBinderData = m_BinderData.find( make_pair((i-1+m_iNumYYarns)%m_iNumYYarns,j) );
1360 if ( itBinderData != m_BinderData.end() )
1361 {
1362 MaxWidth -= itBinderData->second.dHeight / 2.0;
1363 }
1364 itBinderData = m_BinderData.find( make_pair(i,j) );
1365 if ( itBinderData != m_BinderData.end() )
1366 {
1367 MaxWidth -= itBinderData->second.dHeight / 2.0;
1368 }
1369 }
1370
1371 CSectionPowerEllipse PowerEllipseSection( MaxWidth < m_YYarnData[i].dWidth ? MaxWidth : m_YYarnData[i].dWidth, m_YYarnData[i].dHeight * 2.0, 1.4 );
1372
1373 // Reduce height of power ellipse by changing cross-section whilst maintaining area
1374 ChangePowerEllipseSection( TargetArea, &PowerEllipseSection, FibreArea );
1375 CSectionPowerEllipse TopPowerEllipseSection( PowerEllipseSection );
1376
1377 double TargetHeight, WeftTargetHeight, BinderWeftTargetHeight;
1378 // Calculate weft height without binder yarn anyway as will need for opposite side to binder
1379 {
1380 TargetHeight = (m_dFabricThickness - MidSectionHeight)/2.0;
1381 WeftTargetHeight = TargetHeight - m_dGapSize;
1382 }
1383 if ( IsBinderYarn(j) ) // Weft and binder heights reduced in proportion to their original heights to give target height in total
1384 {
1385 BinderWeftTargetHeight = (TargetHeight - m_dGapSize)*m_YYarnData[i].dHeight/(m_YYarnData[i].dHeight+m_XYarnData[j].dHeight);
1386 }
1387
1388 if ( IsBinderYarn(j) && Cell[0] == PATTERN3D_XYARN ) // Binder yarn at bottom
1389 {
1390 if ( (fabs(PowerEllipseSection.GetHeight()/2.0 - BinderWeftTargetHeight) > TOL && (PowerEllipseSection.GetHeight()/2.0) > BinderWeftTargetHeight ) )
1391 {
1392 AdjustWeftHeight( PowerEllipseSection, MaxWidth, TargetArea, MaxVolumeFraction, FibreArea, BinderWeftTargetHeight );
1393 }
1394 }
1395 else
1396 {
1397 if ( fabs(PowerEllipseSection.GetHeight()/2.0 - WeftTargetHeight) > TOL )
1398 {
1399 if ( (PowerEllipseSection.GetHeight()/2.0) > WeftTargetHeight )
1400 {
1401 AdjustWeftHeight( PowerEllipseSection, MaxWidth, TargetArea, MaxVolumeFraction, FibreArea, WeftTargetHeight );
1402 }
1403 else
1404 {
1405 double EllipseTargetHeight = WeftTargetHeight * 2.0;
1406 FindPowerEllipseSectionHeight( EllipseTargetHeight, TargetArea, &PowerEllipseSection );
1407 }
1408 }
1409 }
1410
1411 CSectionEllipse EllipseSection( PowerEllipseSection.GetWidth(), 0.0 );
1412 ChangeWeftSection( EllipseSection, PowerEllipseSection, YarnIndex, j, m_YYarnData[i].dHeight/2.0);
1413
1414 double dHeight = m_YYarnData[i].dHeight - PowerEllipseSection.GetHeight()/2.0;
1415 if ( Cell[0] == PATTERN3D_XYARN ) // Binder yarn at bottom
1416 {
1417 AdjustBinderPosition( 0, i, j, dHeight, BOTTOM );
1418 }
1419
1420 // Top yarn
1421
1422 if ( IsBinderYarn(j) && Cell[Cell.size()-1] == PATTERN3D_XYARN ) // Binder yarn at top
1423 {
1424 if ( (fabs(TopPowerEllipseSection.GetHeight()/2.0 - BinderWeftTargetHeight) > TOL && (TopPowerEllipseSection.GetHeight()/2.0) > BinderWeftTargetHeight ) )
1425 {
1426 AdjustWeftHeight( TopPowerEllipseSection, MaxWidth, TargetArea, MaxVolumeFraction, FibreArea, BinderWeftTargetHeight );
1427 }
1428 }
1429 else
1430 {
1431 if ( fabs(TopPowerEllipseSection.GetHeight()/2.0 - WeftTargetHeight) > TOL )
1432 {
1433
1434 if ( (TopPowerEllipseSection.GetHeight()/2.0) > WeftTargetHeight )
1435 {
1436 AdjustWeftHeight( TopPowerEllipseSection, MaxWidth, TargetArea, MaxVolumeFraction, FibreArea, WeftTargetHeight );
1437 }
1438 else
1439 {
1440 double EllipseTargetHeight = WeftTargetHeight * 2.0;
1441 FindPowerEllipseSectionHeight( EllipseTargetHeight, TargetArea, &TopPowerEllipseSection );
1442 }
1443 }
1444 }
1445
1446 CSectionEllipse TopEllipseSection( TopPowerEllipseSection.GetWidth(), 0.0 );
1447 ChangeWeftSection( TopPowerEllipseSection, TopEllipseSection, TopYarnIndex, j, -m_YYarnData[i].dHeight/2.0);
1448 if ( Cell[Cell.size()-1] == PATTERN3D_XYARN ) // Binder yarn at top
1449 {
1450 dHeight = m_YYarnData[i].dHeight - TopPowerEllipseSection.GetHeight()/2.0;
1451 AdjustBinderPosition( Cell.size()-1, i, j, -dHeight, TOP );
1452 }
1453 delete pYarnSections;
1454 delete YarnSection;
1455 }
1456 }
1457}
1458
1459void CTextileOrthogonal::ChangeWeftSection( CSection& TopHalf, CSection& BottomHalf, int YarnIndex, int Node, double Offset) const
1460{
1461 //PROFILE_FUNC();
1462 CSectionHybrid Section( TopHalf, BottomHalf );
1463 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[YarnIndex].GetYarnSection()->Copy();
1464
1465 pYarnSections->ReplaceSection( Node, Section );
1466 XYZ NodePos = m_Yarns[YarnIndex].GetNode(Node)->GetPosition();
1467 NodePos.z += Offset;
1468 m_Yarns[YarnIndex].ReplaceNode( Node, CNode(NodePos) );
1469
1470 if ( Node == 0 )
1471 {
1472 NodePos = m_Yarns[YarnIndex].GetNode(m_iNumXYarns)->GetPosition();
1473 NodePos.z += Offset;
1474 m_Yarns[YarnIndex].ReplaceNode( m_iNumXYarns, CNode(NodePos) );
1475 pYarnSections->ReplaceSection( m_iNumXYarns, Section );
1476 }
1477 m_Yarns[YarnIndex].AssignSection( *pYarnSections );
1478 delete pYarnSections;
1479}
1480
1481bool CTextileOrthogonal::AdjustWeftHeight( CSectionPowerEllipse& PowerEllipseSection, double& MaxWidth, double& TargetArea, double& MaxVolumeFraction, double& FibreArea, double TargetHeight ) const
1482{
1483 double InitialHeight = PowerEllipseSection.GetHeight();
1484
1485 double HeightReduction = TargetHeight / (PowerEllipseSection.GetHeight()/2.0);
1486 if ( HeightReduction <= 0.1 )
1487 HeightReduction = 0.1;
1488
1489 // Adjust width whilst maintaining original area
1490 if ( !AdjustPowerEllipseSectionWidth( HeightReduction, MaxWidth, TargetArea, &PowerEllipseSection ) )
1491 {
1492 // Reached max width with area > target (ie > original Vf )
1493 // Find new volume fraction & check if ok
1494 double Area = PowerEllipseSection.GetArea( PowerEllipseSection.GetPoints(40) );
1495 double VolumeFraction = FibreArea/(Area/2.0);
1496 if ( VolumeFraction > MaxVolumeFraction )
1497 {
1498 // Vf too large so increase height to give MaxVolumeFraction.
1499 double MinArea = (FibreArea/MaxVolumeFraction) * 2.0;
1500 FindPowerEllipseSectionHeight( InitialHeight, MinArea, &PowerEllipseSection );
1501 return false;
1502 }
1503 }
1504 return true;
1505}
1506
1507void CTextileOrthogonal::AdjustWeftToFitBinderHeight( int i, int j, CSectionPowerEllipse& PowerEllipseSection, double& MaxWidth, double& TargetArea, double& MaxVolumeFraction, double& FibreArea ) const
1508{
1509 double InitialHeight = PowerEllipseSection.GetHeight();
1510 // Find proportion by which need to reduce height
1511 // If binder height is >= weft yarn height set a minimum height reduction - arbitrarily 0.1 at the moment.
1512 // Any way of determining realistic value/proportion for reduction? Currently assume weft and binder will reduce in proportion to their initial height ratio
1513 double TargetHeight = (m_YYarnData[i].dHeight - 1.5*m_dGapSize) * m_YYarnData[i].dHeight/(m_YYarnData[i].dHeight+m_XYarnData[j].dHeight);
1514 //double HeightReduction = (m_YYarnData[i].dHeight - m_XYarnData[j].dHeight - 1.5*m_dGapSize)/ (PowerEllipseSection.GetHeight()/2.0);
1515 double HeightReduction = TargetHeight / (PowerEllipseSection.GetHeight()/2.0);
1516 if ( HeightReduction <= 0.1 )
1517 HeightReduction = 0.1;
1518
1519 // Adjust width whilst maintaining original area
1520 if ( !AdjustPowerEllipseSectionWidth( HeightReduction, MaxWidth, TargetArea, &PowerEllipseSection ) )
1521 {
1522 // Reached max width with area > target (ie > original Vf )
1523 // Find new volume fraction & check if ok
1524 double Area = PowerEllipseSection.GetArea( PowerEllipseSection.GetPoints(40) );
1525 double VolumeFraction = FibreArea/(Area/2.0);
1526 if ( VolumeFraction > MaxVolumeFraction )
1527 {
1528 // Vf too large so increase height to give MaxVolumeFraction. Will therefore need to adjust binders
1529 double MinArea = (FibreArea/MaxVolumeFraction) * 2.0;
1530 FindPowerEllipseSectionHeight( InitialHeight, MinArea, &PowerEllipseSection );
1531 }
1532 }
1533}
1534
1535void CTextileOrthogonal::AdjustBinderPosition( int iCellIndex, int i, int j, double dHeight, bool bIsTop ) const
1536{
1537 int YarnIndex = GetYarnIndex( i, j, iCellIndex );
1538 XYZ Node = m_Yarns[YarnIndex].GetNode(i)->GetPosition();
1539 Node.z += dHeight;
1540 m_Yarns[YarnIndex].ReplaceNode( i, CNode(Node) );
1541 if ( i == 0 )
1542 {
1543 XYZ LastNode = m_Yarns[YarnIndex].GetNode(m_iNumYYarns)->GetPosition();
1544 LastNode.z = Node.z;
1545 m_Yarns[YarnIndex].ReplaceNode( m_iNumYYarns, CNode(LastNode) );
1546 }
1547 if ( bIsTop )
1548 {
1549 double NewMaxZ = Node.z + m_XYarnData[j].dHeight/2.0;
1550 if ( NewMaxZ > m_dMaxZ )
1551 m_dMaxZ = NewMaxZ;
1552 }
1553 else
1554 {
1555 double NewMinZ = Node.z - m_XYarnData[j].dHeight/2.0;
1556 if ( NewMinZ < m_dMinZ )
1557 m_dMinZ = NewMinZ;
1558 }
1559}
1560
1562{
1563 //PROFILE_FUNC();
1564 for ( int j = 0; j < m_iNumXYarns; ++j )
1565 {
1566 if ( IsBinderYarn( j ) )
1567 {
1568 for ( int i = 0; i < m_iNumYYarns; ++i )
1569 {
1571 }
1572 }
1573 }
1574}
1575
1577{
1578 const vector<PATTERN3D> &Cell = GetCell(i,j);
1579 int iMaxIndex = (int)Cell.size() - 1;
1580
1581 if ( iMaxIndex < 1 )
1582 return;
1583
1584 if ( Cell[iMaxIndex] == PATTERN3D_XYARN && Cell[iMaxIndex-1] == PATTERN3D_YYARN ) // Binder yarn at top and yarn underneath is weft yarn
1585 {
1586 int BinderYarnIndex = GetYarnIndex( i, j, iMaxIndex );
1587 int WeftYarnIndex = GetYarnIndex( i, j, iMaxIndex-1 );
1588 int BottomWeftYarnIndex = GetYarnIndex( i, j, 1 );
1589
1590 if ( BinderYarnIndex == -1 || WeftYarnIndex == -1 )
1591 return;
1592
1593 AdjustBinderYarnSection( i, j, BinderYarnIndex, WeftYarnIndex, BottomWeftYarnIndex, TOP );
1594 }
1595 else if ( Cell[0] == PATTERN3D_XYARN && Cell[1] == PATTERN3D_YYARN ) // Binder yarn at bottom and yarn above is weft yarn
1596 {
1597 int BinderYarnIndex = GetYarnIndex( i, j, 0 );
1598 int WeftYarnIndex = GetYarnIndex( i, j, 1 );
1599 int TopWeftYarnIndex = GetYarnIndex( i, j, iMaxIndex-1 );
1600
1601 if ( BinderYarnIndex == -1 || WeftYarnIndex == -1 )
1602 return;
1603
1604 AdjustBinderYarnSection( i, j, BinderYarnIndex, WeftYarnIndex, TopWeftYarnIndex, BOTTOM );
1605 }
1606}
1607
1608void CTextileOrthogonal::AdjustBinderYarnSection( int i, int j, int BinderYarnIndex, int WeftYarnIndex, int OppositeWeftYarnIndex, bool IsTop ) const
1609{
1610 XYZ WeftNode = m_Yarns[WeftYarnIndex].GetNode( j )->GetPosition();
1611 XYZ BinderNode = m_Yarns[BinderYarnIndex].GetNode( i )->GetPosition();
1612 XYZ OppositeWeftNode = m_Yarns[OppositeWeftYarnIndex].GetNode( j )->GetPosition();
1613
1614 // Get cross section of weft yarn
1615 CSection* WeftYarnSection = GetCrossSection( WeftYarnIndex, j );
1616 string Type = WeftYarnSection->GetType();
1617
1618 if ( Type != "CSectionHybrid" )
1619 {
1620 delete WeftYarnSection;
1621 return;
1622 }
1623 double WeftHeight = GetHybridHeight( (CSectionHybrid*)WeftYarnSection );
1624
1625 CSection* OppositeWeftSection = GetCrossSection( OppositeWeftYarnIndex, j );
1626 Type = WeftYarnSection->GetType();
1627 if ( Type != "CSectionHybrid" )
1628 {
1629 delete OppositeWeftSection;
1630 return;
1631 }
1632 double OppositeWeftHeight = GetHybridHeight( (CSectionHybrid*)OppositeWeftSection );
1633 double Height;
1634 if ( IsTop )
1635 {
1636 Height = WeftNode.z - OppositeWeftNode.z;
1637 }
1638 else
1639 {
1640 Height = OppositeWeftNode.z - WeftNode.z;
1641 }
1642
1643 double MidSectionHeight = Height;
1644 Height = MidSectionHeight/2.0 + WeftHeight; // Add whole height as node moved to flat surface of hybrid
1645 double BinderTargetHeight = m_dFabricThickness/2.0 - Height;
1646
1647 CSection* BinderYarnSection = GetCrossSection( BinderYarnIndex, i );
1648 CSectionPowerEllipse* YarnSection = (CSectionPowerEllipse*)BinderYarnSection->Copy();
1649
1650 double FibreArea = m_Yarns[BinderYarnIndex].GetFibreArea("mm^2");
1651 double InitialArea = YarnSection->GetArea(YarnSection->GetPoints(40));
1652 if ( FibreArea/InitialArea > m_dMaxVolumeFraction )
1653 {
1654 TGERROR( "Binder yarn initial volume fraction exceeds max Vf Yarn: " << BinderYarnIndex );
1655 delete YarnSection;
1656 delete WeftYarnSection;
1657 return;
1658 }
1659
1660 if ( fabs(m_XYarnData[j].dHeight - BinderTargetHeight) < TOL || m_XYarnData[j].dHeight <= BinderTargetHeight ) // Enough space for binder yarn so return
1661 {
1662 delete WeftYarnSection;
1663 return;
1664 }
1665
1666
1667 double TargetArea = InitialArea * 2.0; // *2.0 because only using half in hybrid section
1668
1669 // Create new power ellipse section with more lenticular shape - this is an assumption - may need better method of selecting appropriate profile
1670 // Create new section with target height
1671 CSectionPowerEllipse PowerEllipseSection(YarnSection->GetWidth(), BinderTargetHeight*2.0, 1.7 );
1672 double PowerEllipseArea = PowerEllipseSection.GetArea( PowerEllipseSection.GetPoints(40));
1673 double dCrimp = 0.0;
1674 bool bCorrectCrimpInterference = false;
1675
1676 if ( PowerEllipseArea < TargetArea ) // New section has smaller cross-section than original so need to adjust width
1677 {
1678 double WidthHeightReduction = 1.0;
1679 // Make assumption about max width for the moment;
1680 double MaxWidth = PowerEllipseSection.GetWidth() * 2.25;
1681 if ( !AdjustPowerEllipseSectionWidth( WidthHeightReduction, MaxWidth, TargetArea, &PowerEllipseSection ) )
1682 {
1683 // Increased to max width without achieving target area. Check if reduced area gives ok Vf
1684 PowerEllipseArea = PowerEllipseSection.GetArea( PowerEllipseSection.GetPoints(40));
1685 double VolumeFraction = FibreArea/(PowerEllipseArea/2.0);
1686 if ( VolumeFraction > m_dMaxVolumeFraction )
1687 {
1688 // New section Vf too high so increase height until achieve max Vf
1689 double MinArea = (FibreArea/m_dMaxVolumeFraction) * 2.0;
1690 // Send undeformed height of yarn as max height
1691 FindPowerEllipseSectionHeight( m_XYarnData[j].dHeight, MinArea, &PowerEllipseSection );
1692
1693 // Have now increased binder height over available space so need to check if weft was at max Vf.
1694 // If not then room to compress weft further
1695 double WeftArea = WeftYarnSection->GetArea( WeftYarnSection->GetPoints(40));
1696 double WeftFibreArea = m_Yarns[WeftYarnIndex].GetFibreArea("mm^2");
1697 double WeftVolumeFraction = WeftFibreArea/WeftArea;
1698 if ( fabs(WeftVolumeFraction- m_dMaxVolumeFraction) > TOL && WeftVolumeFraction < m_dMaxVolumeFraction ) // Weft not at max volume fraction so room to compress further
1699 {
1700 CSectionPowerEllipse* WeftPowerEllipse = (CSectionPowerEllipse*)((CSectionHybrid*)WeftYarnSection)->GetSection( IsTop?0:1 ).Copy();
1701 CSectionEllipse* WeftEllipse = (CSectionEllipse*)((CSectionHybrid*)WeftYarnSection)->GetSection( IsTop?1:0 ).Copy();
1702 CSectionPowerEllipse* MinWeftPowerEllipse = (CSectionPowerEllipse*)(WeftPowerEllipse->Copy());
1703
1704 // Find height of power ellipse with max Vf. Set initial height so that less than start height
1705 MinWeftPowerEllipse->SetHeight( MinWeftPowerEllipse->GetHeight()/2.0 );
1706 // Find height available for weft yarn now binder yarn height has increased
1707 // double TargetWeftHeightOld = m_YYarnData[i].dHeight - PowerEllipseSection.GetHeight()/2.0 - 1.5*m_dGapSize;
1708
1709 double TargetWeftHeight = (m_dFabricThickness - MidSectionHeight)/2.0 - PowerEllipseSection.GetHeight()/2.0 - m_dGapSize;
1710 double TargetWeftArea = (WeftFibreArea * 2.0 )/ m_dMaxVolumeFraction; // Multiply by 2 because calculating for whole power ellipse
1711 double MaxHeight = WeftHeight * 2.0; // not the half used in the actual section
1712 FindPowerEllipseSectionHeight( MaxHeight, TargetWeftArea, MinWeftPowerEllipse );
1713
1714 if ( TargetWeftHeight >= MinWeftPowerEllipse->GetHeight()/2.0 ) // Is max Vf weft height less than required height? If yes then can set weft to required height
1715 {
1716 WeftPowerEllipse->SetHeight( TargetWeftHeight * 2.0 );
1717 if ( IsTop )
1718 {
1719 ChangeWeftSection( *WeftPowerEllipse, *WeftEllipse, WeftYarnIndex, j, 0.0 );
1720 }
1721 else
1722 {
1723 ChangeWeftSection( *WeftEllipse, *WeftPowerEllipse, WeftYarnIndex, j, 0.0 );
1724 }
1725 WeftArea = WeftPowerEllipse->GetArea( WeftPowerEllipse->GetPoints(40) ) / 2.0;
1726 }
1727
1728 delete WeftPowerEllipse;
1729 delete WeftEllipse;
1730 delete MinWeftPowerEllipse;
1731 }
1732 WeftVolumeFraction = WeftFibreArea/WeftArea;
1733
1734 if ( fabs(WeftVolumeFraction - m_dMaxVolumeFraction) < TOL || WeftVolumeFraction >= m_dMaxVolumeFraction )
1735 {
1736 // Weft and binder now both at max Vf
1737 TGERROR("Can't reduce outer weft and binder to fit without exceeding max Vf: Binder Yarn " << BinderYarnIndex << "Weft Yarn " << WeftYarnIndex );
1738 // If yes, return with error - can't achieve this thickness without exceeding max Vf
1739 // OR find combined height of binder & weft at max Vf and introduce crimp to acommodate excess height => need change in next warp layer
1740 double dBinderWeftTargetHeight = (m_dFabricThickness - MidSectionHeight)/2.0;
1741 dCrimp = WeftHeight + PowerEllipseSection.GetHeight()/2.0 - dBinderWeftTargetHeight;
1742 // Check to see if opposite weft yarn filled all of space available
1743 // If not move stack by smaller of dCrimp and space available
1744
1745 Height = MidSectionHeight/2.0 + OppositeWeftHeight;
1746 double dOppositeSpace = m_dFabricThickness/2.0 - Height;
1747 double dOffset;
1748 if ( dCrimp > 0.0 )
1749 {
1750 if ( dOppositeSpace < TOL ) // No space to move in z-direction, just correct interference
1751 {
1752 bCorrectCrimpInterference = true;
1753 }
1754 else
1755 {
1756 if ( dCrimp < dOppositeSpace )
1757 {
1758 dOffset = dCrimp;
1759 }
1760 else
1761 {
1762 dOffset = dOppositeSpace;
1763 bCorrectCrimpInterference = true;
1764 }
1765 const vector<PATTERN3D> &Cell = GetCell(i,j);
1766 int iMaxIndex = (int)Cell.size() - 1;
1767 if ( IsTop )
1768 {
1769 for ( int k = 1; k < iMaxIndex-1; ++k )
1770 {
1771 OffsetYarn( i, j, k, -dOffset, Cell[k] );
1772 }
1773 }
1774 else
1775 {
1776 for ( int k = 2; k < iMaxIndex; ++k )
1777 {
1778 OffsetYarn( i, j, k, dOffset, Cell[k] );
1779 }
1780 }
1781 }
1782 }
1783 }
1784 }
1785 }
1786 }
1787 else if ( PowerEllipseArea > TargetArea )
1788 {
1789 // New section gives larger area => Vf has decreased at target height
1790 // Is this a fair representation? What's the weft yarn Vf? If this has increased to max Vf then might be that should
1791 // find midway where binder & weft Vf changes by similar amount?
1792 //ReducePowerEllipseHeight( TargetArea, &PowerEllipseSection );
1793 TGLOG( "New binder power ellipse area > target area => Vf decreased");
1794 }
1795 CSectionEllipse EllipseSection( PowerEllipseSection.GetWidth(), 0.0 );
1796
1797 // Work out offset for binder node
1798 XYZ Node = m_Yarns[BinderYarnIndex].GetNode(i)->GetPosition();
1799 double Offset;
1800 Offset = (-(m_XYarnData[j].dHeight - PowerEllipseSection.GetHeight()/2.0)/2.0) + PowerEllipseSection.GetHeight()/4.0 - dCrimp;
1801 //Offset = PowerEllipseSection.GetHeight()/2.0 - m_XYarnData[j].dHeight;
1802
1803 if ( IsTop )
1804 {
1805 ChangeBinderSection( EllipseSection, PowerEllipseSection, BinderYarnIndex, i, Offset );
1806 WeftNode.z -= dCrimp;
1807 }
1808 else
1809 {
1810 ChangeBinderSection( PowerEllipseSection, EllipseSection, BinderYarnIndex, i, -Offset );
1811 WeftNode.z += dCrimp;
1812 }
1813 m_Yarns[WeftYarnIndex].ReplaceNode( j, WeftNode );
1814
1815 //if ( dCrimp > 0.0 )
1816 if ( bCorrectCrimpInterference )
1817 CorrectCrimpInterference( i, j, WeftYarnIndex, IsTop );
1818
1819 delete WeftYarnSection;
1820 delete BinderYarnSection;
1821 delete YarnSection;
1822}
1823
1824void CTextileOrthogonal::ChangeBinderSection( CSection& TopHalf, CSection& BottomHalf, int YarnIndex, int Node, double Offset) const
1825{
1826 //PROFILE_FUNC();
1827 CSectionHybrid Section( TopHalf, BottomHalf );
1828 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[YarnIndex].GetYarnSection()->Copy();
1829
1830 pYarnSections->ReplaceSection( Node, Section );
1831 XYZ NodePos = m_Yarns[YarnIndex].GetNode(Node)->GetPosition();
1832 NodePos.z += Offset;
1833 m_Yarns[YarnIndex].ReplaceNode( Node, CNode(NodePos) );
1834
1835 if ( Node == 0 )
1836 {
1837 NodePos = m_Yarns[YarnIndex].GetNode(m_iNumYYarns)->GetPosition();
1838 NodePos.z += Offset;
1839 m_Yarns[YarnIndex].ReplaceNode( m_iNumYYarns, CNode(NodePos) );
1840 pYarnSections->ReplaceSection( m_iNumYYarns, Section );
1841 }
1842 m_Yarns[YarnIndex].AssignSection( *pYarnSections );
1843 delete pYarnSections;
1844}
1845
1847{
1848 XY TopSectionPoint, BottomSectionPoint;
1849 TopSectionPoint = Section->GetPoint(0.25);
1850 BottomSectionPoint = Section->GetPoint(0.75);
1851 return TopSectionPoint.y - BottomSectionPoint.y;
1852}
1853
1855{
1856 XY LeftPoint, RightPoint;
1857 LeftPoint = Section->GetPoint(0.5);
1858 RightPoint = Section->GetPoint(0.0);
1859 return RightPoint.x - LeftPoint.x;
1860}
1861
1862void CTextileOrthogonal::ReplaceYarnSection( int YarnIndex, int Node, CSection& Section ) const
1863{
1864 CYarnSectionInterpNode* pInterpNodeSection = (CYarnSectionInterpNode*)m_Yarns[YarnIndex].GetYarnSection()->Copy();
1865 pInterpNodeSection->ReplaceSection( Node, Section );
1866 m_Yarns[YarnIndex].AssignSection(*pInterpNodeSection);
1867 delete pInterpNodeSection;
1868}
1869
1870void CTextileOrthogonal::ReplaceThroughBinderSection( int BinderYarnIndex, int Node, CSection& Section, map<pair<int, int>, YARNDATA>::iterator& itBinderData ) const
1871{
1872 if ( itBinderData != m_BinderData.end() && itBinderData->second.dWidth >= (itBinderData->second.dSpacing-TOL) )
1873 {
1874 CSectionPowerEllipse ThroughBinder( itBinderData->second.dWidth, itBinderData->second.dHeight, 0.0 );
1875 ReplaceYarnSection( BinderYarnIndex, Node, ThroughBinder );
1876 }
1877 else
1878 {
1879 ReplaceYarnSection( BinderYarnIndex, Node, Section );
1880 }
1881}
1882
1883void CTextileOrthogonal::ChangePowerEllipseSection( double& TargetArea, CSectionPowerEllipse* YarnSection, double FibreArea ) const
1884{
1885 double Area = YarnSection->GetArea( YarnSection->GetPoints(40) );
1886 if ( Area > TargetArea )
1887 ReducePowerEllipseHeight( TargetArea, YarnSection );
1888 else if ( Area < TargetArea ) // do nothing if equal
1889 {
1890 double NewVolumeFraction = FibreArea/(TargetArea/2.0);
1891 if ( NewVolumeFraction <= m_dMaxVolumeFraction )
1892 return; // Reduced area but volume fraction still ok so just return
1893 // Need to increase area until volume fraction ok
1894 double HeightReduction = 1.0;
1895 AdjustPowerEllipsePower( HeightReduction, TargetArea, YarnSection, 0.1 );
1896 }
1897}
1898
1900{
1901 int i = StartIndex + 1;
1902 while ( i < m_iNumXYarns && !IsBinderYarn( i ) )
1903 {
1904 i++;
1905 }
1906 if ( i < m_iNumXYarns )
1907 return i;
1908
1909 if ( StartIndex == 0 )
1910 return StartIndex;
1911 i = StartIndex - 1;
1912 while( i >= 0 && !IsBinderYarn( i ) )
1913 {
1914 i--;
1915 }
1916 if ( i == -1 )
1917 return StartIndex;
1918 return i;
1919}
1920
1921XY CTextileOrthogonal::GetSectionPoint( CSection* YarnSection, double t ) const
1922{
1923 string WeftType = YarnSection->GetType();
1924 XY SectionPoint;
1925 if ( WeftType == "CSectionPowerEllipse" )
1926 {
1927 SectionPoint = ((CSectionPowerEllipse*)YarnSection)->GetPoint(t);
1928 }
1929 else
1930 SectionPoint = ((CSectionHybrid*)YarnSection)->GetPoint(t);
1931
1932 return SectionPoint;
1933}
1934
1935void CTextileOrthogonal::CorrectCrimpInterference( int i, int j, int WeftYarnIndex, bool IsTop) const
1936{
1937
1938 //int i, j, k;
1939 const vector<PATTERN3D> &Cell = GetCell(i,j);
1940
1941 int k;
1942 CMesh WeftYarnMesh;
1943 vector<int>::iterator itpYarn;
1944 vector<pair<int, int> > RepeatLimits;
1945 vector<pair<double, XYZ> > Intersections;
1946 XYZ Centre, P;
1947 const CYarnSection* pYarnSection;
1948 const CInterpolation* pInterpolation;
1949 CSlaveNode Node;
1950 XYZ Side, Up;
1951 YARN_POSITION_INFORMATION YarnPosInfo;
1952
1953 RepeatLimits.resize(2, pair<int, int>(-1, 0));
1954 vector<double> Modifiers;
1955 vector< vector<double> > YarnSectionModifiers;
1956
1957 int WarpYarnIndex [2];
1958 int WarpCellIndex = IsTop ? Cell.size()-3 : 2;
1959 int WarpPrevIndex = (j+m_iNumXYarns-1)%m_iNumXYarns;
1960 int WarpNextIndex = (j+1)%m_iNumXYarns;
1961 WarpYarnIndex[0] = GetYarnIndex( i, WarpPrevIndex, WarpCellIndex );
1962 WarpYarnIndex[1] = GetYarnIndex( i, WarpNextIndex, WarpCellIndex );
1963
1964
1965 // Find at how much the cross sections need to be compressed to leave given gap size
1966 WeftYarnMesh.Clear();
1967 m_Yarns[WeftYarnIndex].AddSurfaceToMesh(WeftYarnMesh, RepeatLimits);
1968
1969 WeftYarnMesh.Convert3Dto2D();
1970 WeftYarnMesh.ConvertQuadstoTriangles();
1971
1972
1973 double WeftWidth [2];
1974 WeftWidth[0] = GetHybridSectionWidth( WarpPrevIndex, WeftYarnIndex );
1975 WeftWidth[1] = GetHybridSectionWidth( WarpNextIndex, WeftYarnIndex );
1976
1977 for (k=0; k < 2; ++k)
1978 {
1979 YarnPosInfo.iSection = i;
1980 YarnPosInfo.dSectionPosition = 0;
1981 YarnPosInfo.SectionLengths = m_Yarns[WarpYarnIndex[k]].GetYarnSectionLengths();
1982
1983 pInterpolation = m_Yarns[WarpYarnIndex[k]].GetInterpolation();
1984 Node = pInterpolation->GetNode(m_Yarns[WarpYarnIndex[k]].GetMasterNodes(), i, 0);
1985 Up = Node.GetUp();
1986 Side = CrossProduct(Node.GetTangent(), Up);
1987
1988 pYarnSection = m_Yarns[WarpYarnIndex[k]].GetYarnSection();
1989 vector<XY> Points = pYarnSection->GetSection(YarnPosInfo, m_Yarns[WarpYarnIndex[k]].GetNumSectionPoints());
1990 Centre = m_Yarns[WarpYarnIndex[k]].GetMasterNodes()[i].GetPosition();
1991 vector<XY>::iterator itPoint;
1992 Modifiers.clear();
1993 for (itPoint = Points.begin(); itPoint != Points.end(); ++itPoint)
1994 {
1995 P = itPoint->x * Side + itPoint->y * Up + Centre;
1996 if (WeftYarnMesh.IntersectLine(Centre, P, Intersections, make_pair(true, false)))
1997 {
1998 double dU = Intersections[0].first;
1999 XYZ Normal = Intersections[0].second;
2000 double dProjectedGap = m_dGapSize / DotProduct(Normal, Centre-P);
2001 dU -= 0.5 * dProjectedGap;
2002 if (dU > 1)
2003 dU = 1;
2004 if (dU < 0)
2005 dU = 0;
2006 Modifiers.push_back(dU);
2007 }
2008 else
2009 Modifiers.push_back(1);
2010 }
2011 YarnSectionModifiers.push_back(Modifiers);
2012 }
2013
2014
2015
2016
2017 for ( k=0; k<2; ++k )
2018 {
2019 vector<XY> Points;
2020 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[WarpYarnIndex[k]].GetYarnSection()->Copy();
2021
2022 pYarnSection = m_Yarns[WarpYarnIndex[k]].GetYarnSection();
2023 YarnPosInfo.SectionLengths = m_Yarns[WarpYarnIndex[k]].GetYarnSectionLengths();
2024 // Add sections at the warp node
2025 YarnPosInfo.dSectionPosition = 0;
2026 YarnPosInfo.iSection = i;
2027
2028 Points = pYarnSection->GetSection(YarnPosInfo, YarnSectionModifiers[k].size());
2029 for ( int ind=0; ind<(int)Points.size(); ++ind)
2030 {
2031 Points[ind] *= YarnSectionModifiers[k][ind];
2032 }
2033 CSectionPolygon Section(Points);
2034 if (m_pSectionMesh)
2036 pYarnSections->ReplaceSection( i, Section );
2037 if ( i == 0 )
2038 {
2039 pYarnSections->ReplaceSection( m_iNumYYarns, Section );
2040 }
2041
2042 // Add mid-sections along warp so that section is the same across the width of the crossing weft yarn
2043 double u = 0.95 * ( WeftWidth[k]/2.0 ) / YarnPosInfo.SectionLengths[i]; // 0.95 so that sections don't end up in wrong order due to fp errors if butt up to each other
2044 pYarnSections->InsertSection( i, u, Section );
2045 int PrevSectionIndex = (i+m_iNumYYarns-1)%m_iNumYYarns;
2046 u = 1 - 0.95 * ( (WeftWidth[k]/2.0) / YarnPosInfo.SectionLengths[PrevSectionIndex] );
2047 pYarnSections->InsertSection( PrevSectionIndex, u, Section );
2048
2049 m_Yarns[WarpYarnIndex[k]].AssignSection(*pYarnSections);
2050 delete pYarnSections;
2051 }
2052}
2053
2054double CTextileOrthogonal::GetHybridSectionWidth( int WarpIndex, int WeftIndex ) const
2055{
2056 double Width;
2057 CYarnSectionInterpNode* pYarnSections = (CYarnSectionInterpNode*)m_Yarns[WeftIndex].GetYarnSection()->Copy();
2058 CSectionHybrid* WeftSection;
2059 WeftSection = (CSectionHybrid*)pYarnSections->GetNodeSection(WarpIndex).Copy();
2060 Width = GetHybridWidth( WeftSection );
2061 delete WeftSection;
2062 delete pYarnSections;
2063 return Width;
2064}
2065
2066void CTextileOrthogonal::OffsetYarn( int i, int j, int k, double dHeight, int YarnType ) const
2067{
2068 int YarnIndex = GetYarnIndex( i, j, k );
2069 if ( YarnIndex == -1 )
2070 return;
2071 XYZ Node;
2072 if ( YarnType == PATTERN3D_XYARN )
2073 {
2074 Node = m_Yarns[YarnIndex].GetNode(i)->GetPosition();
2075 Node.z += dHeight;
2076 m_Yarns[YarnIndex].ReplaceNode( i, CNode(Node) );
2077 if ( i == 0 )
2078 {
2079 XYZ LastNode = m_Yarns[YarnIndex].GetNode(m_iNumYYarns)->GetPosition();
2080 LastNode.z = Node.z;
2081 m_Yarns[YarnIndex].ReplaceNode( m_iNumYYarns, CNode(LastNode) );
2082 }
2083 }
2084 else if ( YarnType == PATTERN3D_YYARN )
2085 {
2086 Node = m_Yarns[YarnIndex].GetNode(j)->GetPosition();
2087 Node.z += dHeight;
2088 m_Yarns[YarnIndex].ReplaceNode( j, CNode(Node) );
2089 if ( j == 0 )
2090 {
2091 XYZ LastNode = m_Yarns[YarnIndex].GetNode(m_iNumXYarns)->GetPosition();
2092 LastNode.z = Node.z;
2093 m_Yarns[YarnIndex].ReplaceNode( m_iNumXYarns, CNode(LastNode) );
2094 }
2095 }
2096}
2097
2099{
2101 for ( int i = m_iNumYYarns-1; i >=0; --i )
2102 {
2103 int iNumWefts = (int)m_YYarns[i].size();
2104 vector<string> Rows;
2105 Rows.resize(iNumWefts);
2106
2107 for ( int j = m_iNumXYarns-1; j >= 0 ; --j )
2108 {
2109 vector<PATTERN3D> &Cell = GetCell(i, j);
2110 if ( NoYarnCell( Cell ) )
2111 continue;
2112 vector<bool> bWeftSet(iNumWefts, false);
2113 int iWeft = iNumWefts-1;
2114
2115 for ( int k = (int)Cell.size()-1; k >= 0; --k )
2116 {
2117 switch (Cell[k])
2118 {
2119 case PATTERN3D_XYARN:
2120 for ( int iW = 0; iW < iNumWefts; ++iW )
2121 {
2122 if ( !bWeftSet[iW] )
2123 Rows[iW].push_back('1');
2124 else
2125 Rows[iW].push_back('0');
2126 }
2127 break;
2128 case PATTERN3D_YYARN:
2129 bWeftSet[iWeft] = true;
2130 iWeft--;
2131 break;
2132 case PATTERN3D_NOYARN:
2133 break;
2134 }
2135 }
2136 }
2137
2138 if ( iWeftOrder == BOTTOM_TO_TOP || (iWeftOrder == ALTERNATE_WEFT_STACK && i%2))
2139 {
2140 // Add wefts from bottom to top
2141 for ( int iW = iNumWefts-1 ; iW >=0; --iW )
2142 m_PatternDraft.AddRow( Rows[iW] );
2143 }
2144 else
2145 {
2146 // Add wefts from top to bottom
2147 for ( int iW = 0 ; iW < iNumWefts; ++iW )
2148 m_PatternDraft.AddRow( Rows[iW] );
2149 }
2150 }
2151}
2152
2153void CTextileOrthogonal::SetupWeftRow( vector<int>& Layers, vector<int>& Warp, int NumWarps, int Weft )
2154{
2155 int NumLayers = *(max_element( Layers.begin(), Layers.end() )); // Size of max warp stack
2156 m_iTotalXYarns = Layers.size();
2157 vector<int>::iterator itWarp;
2158 vector<int>::iterator itLayers;
2159
2160 if ( Layers.size() != Warp.size() )
2161 TGERROR("Can't add weft row, warp and layer sizes do not match");
2162
2163 itWarp = Warp.begin();
2164 int j = NumWarps-1;
2165 int PrevYCellIndex = -1;
2166
2167 // Find weft index
2168 bool bFound = false;
2169 itLayers = Layers.begin();
2170 while ( itLayers != Layers.end() && !bFound )
2171 {
2172 vector<PATTERN3D> &Cell = GetCell(Weft, j);
2173 if ( IsBinderYarn( j ) )
2174 {
2175 ++itLayers;
2176 ++itWarp;
2177 }
2178 else
2179 {
2180 bool bFirst = true; // bFirst is true until the weft yarn has been set for the current cell
2181 int WarpIndex = -1;
2182 do
2183 {
2184 if ( *itWarp == 0 && bFirst ) // Warp yarn is down and weft not yet set
2185 {
2186 PrevYCellIndex = (NumLayers - (*itLayers)+1 )*2 + 1;
2187 // Set the cell for the warp yarn
2188 bFirst = false;
2189 bFound = true;
2190 }
2191 ++itLayers;
2192 ++itWarp;
2193 } while ( itLayers != Layers.end() && *itLayers != 1 ); // Contunue until reach end of current stack of layers
2194 if ( !bFound ) // If reached end of stack without setting weft yarn need to set it at bottom of cell entries
2195 {
2196 PrevYCellIndex = (NumLayers - *(itLayers-1))*2 +1;
2197
2198 //int number = *(itLayers - 1);
2199 //int newnumber = *itLayers - 1;
2200
2201 bFound = true;
2202 }
2203 }
2204 --j; // Move to next cell
2205
2206 }
2207
2208 itWarp = Warp.begin();
2209 j = NumWarps-1;
2210 // Left hand side of weave pattern corresponds to maximum y value (or max j in cell array)
2211 for ( itLayers = Layers.begin(); itLayers != Layers.end(); )
2212 {
2213 vector<PATTERN3D> &Cell = GetCell(Weft, j);
2214 vector<int> &YarnCell = GetYarnCell(Weft, j);
2215 YarnCell.assign(Cell.size(), -1);
2216 if ( IsBinderYarn( j ) )
2217 {
2218 if ( *itWarp == 0 )
2219 Cell[0] = PATTERN3D_XYARN;
2220 else
2221 Cell[Cell.size()-1] = PATTERN3D_XYARN;
2222 // Need to get weft layer of next cell to set for this one
2223 if ( PrevYCellIndex != -1 ) // Still a problem if binder is first warp
2224 {
2225 Cell[PrevYCellIndex] = PATTERN3D_YYARN;
2226 YarnCell[PrevYCellIndex] = Weft;
2227 }
2228 ++itLayers;
2229 ++itWarp;
2230 }
2231 else
2232 {
2233 bool bFirst = true; // bFirst is true until the weft yarn has been set for the current cell
2234 int WarpIndex = -1;
2235 do
2236 {
2237 if ( *itWarp == 0 && bFirst ) // Warp yarn is down and weft not yet set
2238 {
2239 int WeftCellIndex = (NumLayers - (*itLayers)+1 )*2 + 1;
2240 PrevYCellIndex = WeftCellIndex;
2241 Cell[WeftCellIndex] = PATTERN3D_YYARN;
2242 YarnCell[WeftCellIndex] = Weft;
2243
2244 // Set the cell for the warp yarn
2245 Cell[WeftCellIndex-1] = PATTERN3D_XYARN;
2246 bFirst = false;
2247 }
2248 else if ( *itWarp != PATTERN3D_NOYARN ) //Not a no yarn position
2249 {
2250 // Warp is up and no weft yarn yet. Set x yarn cell without space allowed for weft yarn
2251 WarpIndex = (NumLayers - (*itLayers)+1) *2;
2252 Cell[WarpIndex] = PATTERN3D_XYARN;
2253 }
2254
2255 ++itLayers;
2256 ++itWarp;
2257 } while ( itLayers != Layers.end() && *itLayers != 1 ); // Contunue until reach end of current stack of layers
2258 if ( bFirst && *(itWarp-1) != PATTERN3D_NOYARN ) // If reached end of stack without setting weft yarn need to set it at bottom of cell entries
2259 {
2260 int WeftCellIndex = (NumLayers - *(itLayers-1))*2 +1;
2261 PrevYCellIndex = WeftCellIndex;
2262 Cell[WeftCellIndex] = PATTERN3D_YYARN;
2263 //Cell[(NumLayers - *(itLayers-1))*2 +1] = PATTERN3D_YYARN;
2264 YarnCell[(NumLayers - *(itLayers-1))*2 +1] = Weft;
2265 }
2266 }
2267 --j; // Move to next cell
2268
2269 }
2270 for ( j = 1; j < m_iNumXYarns-1; ++j )
2271 {
2272 if ( IsBinderYarn(j) )
2273 {
2274 vector<PATTERN3D> &Cell = GetCell(Weft, j);
2275 vector<int> &YarnCell = GetYarnCell(Weft, j);
2276 vector<PATTERN3D> &PrevCell = GetCell(Weft, j-1);
2277 vector<PATTERN3D> &NextCell = GetCell(Weft, j+1);
2278 int WeftHeight = FindWeftHeight( Cell );
2279 int NextWeftHeight = FindWeftHeight( NextCell );
2280 int PrevWeftHeight = FindWeftHeight( PrevCell);
2281 if ( NextWeftHeight != PrevWeftHeight )
2282 {
2283 Cell[WeftHeight] = PATTERN3D_NOYARN;
2284 Cell[PrevWeftHeight] = PATTERN3D_YYARN;
2285 YarnCell[WeftHeight] = -1;
2286 YarnCell[PrevWeftHeight] = Weft;
2287 }
2288 }
2289 }
2290 m_bNeedsBuilding = true;
2291}
2292
2294{
2295
2296 //bool bWeftChanged = false;
2297 vector<int> Levels;
2298
2299 for (int i = 0; i < m_iNumYYarns-1; ++i )
2300 {
2301 int j;
2302 int WeftLevel = -1;
2303 Levels.clear();
2304 bool bRemoveCells = true;
2305 for ( j = 0; j < m_iNumXYarns; ++j )
2306 {
2307
2308 vector<PATTERN3D> &Cell1 = GetCell(i,j);
2309 vector<PATTERN3D> &Cell2 = GetCell(i+1,j);
2310
2311 if ( (Cell1[0] != Cell2[0] || Cell1[Cell1.size()-1] != Cell2[Cell2.size()-1]) ) // Binder yarn changed level - can't consolidate - does this assume binders at top and bottom only
2312 {
2313 break;
2314 }
2315 int Level2 = FindWeftHeight( Cell2 );
2316 if ( Level2 == -1 ) // -1 means no weft yarn in cell
2317 {
2318 Levels.push_back(Level2);
2319 bRemoveCells = false;
2320 continue;
2321 }
2322 if ( Cell1[Level2] != PATTERN3D_NOYARN ) // If no space in first cell at weft level, can't consolidate
2323 {
2324 Levels.push_back(-1);
2325 bRemoveCells = false;
2326 //break;
2327 continue;
2328 }
2329 else
2330 Levels.push_back(Level2);
2331 /*if ( WeftLevel == -1 )
2332 {
2333 WeftLevel = Level2;
2334 }
2335 else if ( WeftLevel != Level2 ) // Assume at moment that if weft changes layers can't consolidate
2336 {
2337 Consolidate
2338 break;
2339 }*/
2340 }
2341 if ( j == m_iNumXYarns ) // Only consolidate if can move cell at each warp position (ie across whole width)
2342 {
2343 if ( bRemoveCells )
2344 {
2345 for ( j = m_iNumXYarns-1; j >= 0 ; --j )
2346 {
2347 vector<PATTERN3D> &Cell = GetCell(i,j);
2348 vector<int> &YarnCell = GetYarnCell(i,j);
2349 vector<int> &NextYarnCell = GetYarnCell(i+1,j);
2350 //Cell[WeftLevel] = PATTERN3D_YYARN;
2351 Cell[Levels[j]] = PATTERN3D_YYARN;
2352 YarnCell[Levels[j]] = NextYarnCell[Levels[j]];
2353 RemoveCell(i+1,j);
2354 RemoveYarnCell(i+1,j);
2355
2356 //LastLevel = WeftLevel;
2357 }
2358 m_iNumYYarns--;
2359 m_YYarnData.erase(m_YYarnData.begin()+(i+1));
2360 --i;
2361 }
2362 else
2363 {
2364 for ( j = m_iNumXYarns-1; j >= 0 ; --j )
2365 {
2366 vector<PATTERN3D> &Cell = GetCell(i,j);
2367 vector<PATTERN3D> &Cell1 = GetCell(i+1,j);
2368 vector<int> &YarnCell = GetYarnCell(i,j);
2369 vector<int> &YarnCell1 = GetYarnCell(i+1,j);
2370 if ( Levels[j] != -1 )
2371 {
2372 Cell[Levels[j]] = PATTERN3D_YYARN;
2373 Cell1[Levels[j]] = PATTERN3D_NOYARN;
2374 YarnCell[Levels[j]] = YarnCell1[Levels[j]];
2375 YarnCell1[Levels[j]] = -1;
2376 }
2377 }
2378 }
2379 }
2380 }
2381
2382 vector<int> DeleteCell;
2383 for (int i = 0; i < m_iNumYYarns-1; ++i )
2384 {
2385 int j;
2386 int WeftLevel = -1;
2387
2388 DeleteCell.clear();
2389
2390 for ( j = 0; j < m_iNumXYarns; ++j )
2391 {
2392
2393 vector<PATTERN3D> &Cell1 = GetCell(i,j);
2394 vector<PATTERN3D> &Cell2 = GetCell(i+1,j);
2395
2396 int Weft1 = FindWeftHeight( Cell1 );
2397
2398 if ( ((Cell1[0] != Cell2[0] || Cell1[Cell1.size()-1] != Cell2[Cell2.size()-1])) ) // Binder yarn changed level
2399 {
2400 if ( Weft1 == -1 )
2401 {
2402 DeleteCell.push_back(0);
2403 continue;
2404 }
2405 else
2406 break;
2407 }
2408 int k;
2409 for ( k = 1; k < Cell2.size(); ++k )
2410 {
2411 if ( Cell2[k] == PATTERN3D_YYARN )
2412 {
2413 if ( Cell1[k] != PATTERN3D_NOYARN )
2414 break;
2415 }
2416 }
2417 if ( k != Cell2.size() )
2418 break;
2419 DeleteCell.push_back(1);
2420 }
2421 if ( j == m_iNumXYarns )
2422 {
2423
2424 for ( j = m_iNumXYarns-1; j >= 0 ; --j )
2425 {
2426 if ( DeleteCell[j] == 0 )
2427 {
2428 RemoveCell(i,j);
2429 RemoveYarnCell(i,j);
2430 }
2431 else
2432 {
2433 vector<PATTERN3D> &Cell = GetCell(i,j);
2434 vector<PATTERN3D> &Cell1 = GetCell(i+1,j);
2435 vector<int> &YarnCell = GetYarnCell(i,j);
2436 vector<int> &YarnCell1 = GetYarnCell(i+1,j);
2437 for ( int k = 1; k < Cell1.size(); ++k )
2438 {
2439 if ( Cell1[k] == PATTERN3D_YYARN )
2440 {
2441 Cell[k] = PATTERN3D_YYARN;
2442 YarnCell[k] = YarnCell1[k];
2443 }
2444 }
2445 RemoveCell(i+1,j);
2446 RemoveYarnCell(i+1,j);
2447 }
2448 }
2449 m_iNumYYarns--;
2450 m_YYarnData.erase(m_YYarnData.begin()+(i+1)); // Assumes yarn data is same for both sets of yarns otherwise won't be correct
2451 --i;
2452 }
2453 }
2454
2455
2456 for ( int j = 0; j < m_iNumXYarns; ++j )
2457 {
2458 if ( !IsBinderYarn( j ) )
2459 continue;
2460 for (int i = 0; i < m_iNumYYarns; ++i )
2461 {
2462 vector<PATTERN3D> &Cell = GetCell(i,j);
2463 MoveBinderYarnPosition( Cell );
2464 }
2465 }
2466
2467
2468}
2469
2470void CTextileOrthogonal::MoveBinderYarnPosition( vector<PATTERN3D> &Cell )
2471{
2472 if ( Cell[0] == PATTERN3D_XYARN ) // Binder at bottom. Track up through cell until
2473 {
2474 int i = 1;
2475 if ( Cell[1] != PATTERN3D_NOYARN ) // No space directly over binder - don't need to move
2476 return;
2477 while ( i < Cell.size() && Cell[i] == PATTERN3D_NOYARN )
2478 {
2479 ++i;
2480 }
2481 if ( i < Cell.size() )
2482 {
2483 Cell[i-1] = PATTERN3D_XYARN;
2484 Cell[0] = PATTERN3D_NOYARN;
2485 }
2486 }
2487 else if ( Cell[Cell.size()-1] == PATTERN3D_XYARN )
2488 {
2489 int i = Cell.size()-2;
2490 if ( Cell[i] != PATTERN3D_NOYARN ) // No space directly under binder - don't need to move
2491 return;
2492 while ( i >= 0 && Cell[i] == PATTERN3D_NOYARN )
2493 {
2494 --i;
2495 }
2496 if ( i >= 0 )
2497 {
2498 Cell[i+1] = PATTERN3D_XYARN;
2499 Cell[Cell.size()-1] = PATTERN3D_NOYARN;
2500 }
2501 }
2502}
2503
2504int CTextileOrthogonal::FindBinderHeight( const vector<PATTERN3D>& Cell ) const
2505{
2506 int i = Cell.size() - 1;
2507 while( i > 0 )
2508 {
2509 if ( Cell[i] == PATTERN3D_XYARN )
2510 return i;
2511 --i;
2512 }
2513 return i;
2514}
2515
2516vector<int> &CTextileOrthogonal::GetYarnCell(int x, int y)
2517{
2518 return m_WeftYarns[x + m_iNumYYarns*y];
2519}
2520
2521const vector<int> &CTextileOrthogonal::GetYarnCell(int x, int y) const
2522{
2523 return m_WeftYarns[x + m_iNumYYarns*y];
2524}
2525
2526
2528{
2529 m_WeftYarns.erase(m_WeftYarns.begin()+(x + m_iNumYYarns*y));
2530}
2531
2533{
2534 int iXYarnCount = 0;
2535
2536 vector<PATTERN3D> Pattern = GetCell(x, y);
2537 vector<int> YarnCell = GetYarnCell(x, y);
2538 int k;
2539 if ( Pattern[z] == PATTERN3D_NOYARN )
2540 return -1;
2541
2542 if ( Pattern[z] == PATTERN3D_YYARN )
2543 {
2544 return YarnCell[z]+m_iYYarnOffset;
2545 }
2546 for (k=0; k<z; ++k)
2547 {
2548 if (Pattern[k] == PATTERN3D_XYARN)
2549 ++iXYarnCount;
2550 }
2551
2552 return m_XYarns[y][iXYarnCount];
2553
2554}
2555
2556int CTextileOrthogonal::FindWeftYarnHeight(const vector<PATTERN3D>& YarnCell, int WeftIndex) const
2557{
2558 int i = YarnCell.size() - 1;
2559 while (i >= 0)
2560 {
2561 if (YarnCell[i] == WeftIndex)
2562 return i;
2563 --i;
2564 }
2565 return i;
2566}
2567
2569{
2570 int iYarn = 0;
2571 for (int i = 0; i < m_YYarns.size(); ++i)
2572 {
2573 vector<int>::iterator itYYarns;
2574 for (itYYarns = m_YYarns[i].begin(); itYYarns != m_YYarns[i].end(); ++itYYarns)
2575 {
2576 if (iYarn == WeftIndex)
2577 return *itYYarns;
2578 ++iYarn;
2579 }
2580 }
2581 return -1;
2582}
2583
2584int CTextileOrthogonal::AddWeftNodes(int CurrentNode, int i, int j, int WeftIndex) const
2585{
2586 const vector<PATTERN3D> &Cell = GetCell(i, j);
2587 const vector<PATTERN3D> &YarnCell = GetYarnCell(i, j);
2588
2589 int iIndex = FindWeftYarnHeight(YarnCell, WeftIndex);
2590 if (iIndex == -1)
2591 return -1; // Partial weft - no weft yarn at this location
2592
2593
2594 int NextCellIndex = (j + 1) % m_iNumXYarns;
2595 int PrevCellIndex = (j + m_iNumXYarns - 1) % m_iNumXYarns;
2596
2597 const vector<PATTERN3D> &NextCell = GetCell(i, NextCellIndex);
2598 const vector<PATTERN3D> &PrevCell = GetCell(i, PrevCellIndex);
2599
2600 const vector<PATTERN3D> &NextYarnCell = GetYarnCell(i, NextCellIndex);
2601 const vector<PATTERN3D> &PrevYarnCell = GetYarnCell(i, PrevCellIndex);
2602
2603 int iPrevIndex = FindWeftYarnHeight(PrevYarnCell, WeftIndex);
2604 int iNextIndex = FindWeftYarnHeight(NextYarnCell, WeftIndex);
2605 int iMaxIndex = Cell.size() - 1;
2606
2607 XY SectionPoint;
2608 XYZ WarpBelowNode, WarpAboveNode;
2609 int iStartNode = CurrentNode;
2610
2611 if (iIndex < 0)
2612 return CurrentNode;
2613
2614 double dWeftOffset = m_YYarnData[i].dHeight / 2.0;
2615
2616 int WeftYarnIndex = FindWeftYarnIndex(WeftIndex); // Find overall yarn index from m_YYarns
2617
2618 if (WeftYarnIndex == -1) // Can this happen?
2619 return CurrentNode;
2620
2621 int WarpAboveIndex, WarpBelowIndex;
2622 int WarpAboveCellIndex, WarpBelowCellIndex;
2623
2624 // Get indices of warp yarns above and below weft
2625 if (iIndex < (int)Cell.size() - 1)
2626 {
2627 WarpAboveCellIndex = FindWarpAboveIndex(Cell, iIndex);
2628 if (WarpAboveCellIndex != -1)
2629 {
2630 WarpAboveIndex = GetYarnIndex(i, j, WarpAboveCellIndex);
2631 if (WarpAboveIndex >= 0)
2632 WarpAboveNode = m_Yarns[WarpAboveIndex].GetNode(i)->GetPosition();
2633 //WarpAboveNode = m_Yarns[WarpAboveIndex].GetNode(XNode)->GetPosition();
2634 }
2635 else
2636 WarpAboveIndex = -1;
2637 }
2638 else
2639 WarpAboveIndex = -1;
2640
2641 if (iIndex > 0)
2642 {
2643 WarpBelowCellIndex = FindWarpBelowIndex(Cell, iIndex);
2644
2645 if (WarpBelowCellIndex != -1)
2646 {
2647 WarpBelowIndex = GetYarnIndex(i, j, WarpBelowCellIndex);
2648 if (WarpBelowIndex >= 0)
2649 WarpBelowNode = m_Yarns[WarpBelowIndex].GetNode(i)->GetPosition();
2650 //WarpBelowNode = m_Yarns[WarpBelowIndex].GetNode(XNode)->GetPosition();
2651 }
2652 else
2653 WarpBelowIndex = -1;
2654 }
2655 else
2656 WarpBelowIndex = -1;
2657
2658 XYZ WeftNode = m_Yarns[WeftYarnIndex].GetNode(CurrentNode)->GetPosition();
2659
2660 if (iIndex > 0 && iPrevIndex != -1 && iPrevIndex < iIndex - 1 && PrevCell[iPrevIndex] == PATTERN3D_YYARN ) // Check for being more than one layer apart
2661 {
2662 // Get cross section of warp yarn below
2663 if (WarpBelowIndex == -1)
2664 return CurrentNode;
2665 CSection* YarnSection = GetCrossSection(WarpBelowIndex);
2666 if (YarnSection == NULL)
2667 return CurrentNode;
2668
2669 // Insert points around Top left quadrant of warp yarn
2670 XYZ NewNode = WarpBelowNode;
2671
2672 if (iIndex - iPrevIndex > 2)
2673 {
2674 SectionPoint = YarnSection->GetPoint(0.5);
2675 NewNode.y = NewNode.y + SectionPoint.x - dWeftOffset - m_dGapSize;
2676 NewNode.z = NewNode.z + SectionPoint.y;
2677 m_Yarns[WeftYarnIndex].InsertNode(NewNode, CurrentNode);
2678 CurrentNode++;
2679 }
2680
2681 InsertWeftNode(YarnSection, 0.45, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2682 InsertWeftNode(YarnSection, 0.4, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2683 if (!(iIndex < iMaxIndex && iNextIndex > iIndex && NextCell[iNextIndex] == PATTERN3D_YYARN
2684 && GetYarnIndex(i, NextCellIndex, iNextIndex) == WeftYarnIndex))
2685 {
2686 InsertWeftNode(YarnSection, 0.35, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2687 InsertWeftNode(YarnSection, 0.3, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2688 }
2689
2690 delete YarnSection;
2691 }
2692 else if (iIndex < iMaxIndex && iPrevIndex != -1 && iPrevIndex > iIndex + 1 && PrevCell[iPrevIndex] == PATTERN3D_YYARN )
2693 {
2694 if (WarpAboveCellIndex != iIndex + 1) // Warp not directly above so don't need to change weft
2695 return CurrentNode;
2696 // Get cross section of warp yarn below
2697 CSection* YarnSection = GetCrossSection(WarpAboveIndex);
2698 if (YarnSection == NULL)
2699 return CurrentNode;
2700 // Insert points around lower left quadrant of weft yarn
2701 XYZ NewNode = WarpAboveNode;
2702
2703 if (iPrevIndex - iIndex > 2)
2704 {
2705 SectionPoint = YarnSection->GetPoint(0.5);
2706 NewNode.y = NewNode.y + SectionPoint.x - dWeftOffset - m_dGapSize;
2707 NewNode.z = NewNode.z + SectionPoint.y;
2708 m_Yarns[WeftYarnIndex].InsertNode(NewNode, CurrentNode);
2709 CurrentNode++;
2710 }
2711
2712 NewNode = WarpAboveNode;
2713
2714 InsertWeftNode(YarnSection, 0.55, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2715 InsertWeftNode(YarnSection, 0.6, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2716
2717 if (!(iIndex > 0 && iNextIndex < iIndex && NextCell[iNextIndex] == PATTERN3D_YYARN
2718 && GetYarnIndex(i, NextCellIndex, iNextIndex) == WeftYarnIndex))
2719 {
2720 InsertWeftNode(YarnSection, 0.65, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2721 InsertWeftNode(YarnSection, 0.7, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2722 }
2723
2724 if (iNextIndex >= iIndex && NextCell[iNextIndex] == PATTERN3D_YYARN
2725 && GetYarnIndex(i, NextCellIndex, iNextIndex) == WeftYarnIndex)
2726 {
2727 InsertWeftNode(YarnSection, 0.75, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize), false);
2728 }
2729 delete YarnSection;
2730 }
2731
2732
2733
2734 if (iIndex > 0 && iNextIndex != -1 && iNextIndex < iIndex - 1 && NextCell[iNextIndex] == PATTERN3D_YYARN )
2735 {
2736
2737 // Get cross section of weft yarn below
2738 CSection* YarnSection = GetCrossSection(WarpBelowIndex);
2739 if (YarnSection == NULL)
2740 return CurrentNode;
2741
2742 if (iPrevIndex <= iIndex && PrevCell[iPrevIndex] == PATTERN3D_YYARN
2743 && GetYarnIndex(i, PrevCellIndex, iPrevIndex) == WeftYarnIndex)
2744 {
2745 InsertWeftNode(YarnSection, 0.25, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize, false);
2746 }
2747 // Insert points around upper right quadrant of weft
2748
2749 XYZ NewNode = WarpBelowNode;
2750 CurrentNode++; // Need to insert after node (ie before next node)
2751 if (!(iIndex < iMaxIndex && iPrevIndex > iIndex && PrevCell[iPrevIndex] == PATTERN3D_YYARN
2752 && GetYarnIndex(i, PrevCellIndex, iPrevIndex) == WeftYarnIndex))
2753 {
2754 InsertWeftNode(YarnSection, 0.2, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2755 InsertWeftNode(YarnSection, 0.15, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2756 }
2757 InsertWeftNode(YarnSection, 0.1, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2758 InsertWeftNode(YarnSection, 0.05, WarpBelowNode, CurrentNode, WeftYarnIndex, dWeftOffset + m_dGapSize);
2759 CurrentNode--;
2760
2761 if (iIndex - iNextIndex > 2)
2762 {
2763 SectionPoint = YarnSection->GetPoint(0);
2764 NewNode = WarpBelowNode;
2765 NewNode.y = NewNode.y + SectionPoint.x + dWeftOffset + m_dGapSize;
2766 NewNode.z = NewNode.z + SectionPoint.y;
2767 m_Yarns[WeftYarnIndex].InsertNode(NewNode, CurrentNode + 1);
2768 CurrentNode++;
2769 }
2770
2771 delete YarnSection;
2772 }
2773 else if (iIndex < iMaxIndex && iNextIndex != -1 && iNextIndex > iIndex + 1 && NextCell[iNextIndex] == PATTERN3D_YYARN )
2774 {
2775 if (WarpAboveCellIndex != iIndex + 1) // Warp not directly above so don't need to change weft
2776 return CurrentNode;
2777
2778 // Get cross section of weft yarn below
2779 CSection* YarnSection = GetCrossSection(WarpAboveIndex);
2780 if (YarnSection == NULL)
2781 return CurrentNode;
2782
2783 if (iPrevIndex >= iIndex && PrevCell[iPrevIndex] == PATTERN3D_YYARN
2784 && GetYarnIndex(i, PrevCellIndex, iPrevIndex) == WeftYarnIndex)
2785 {
2786 InsertWeftNode(YarnSection, 0.75, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize), false);
2787 }
2788 // Insert points around lower right quadrant of weft yarn
2789 {
2790 XYZ NewNode = WarpAboveNode;
2791 CurrentNode++; // Need to insert after node (ie before next node)
2792 if (!(iIndex > 0 && iPrevIndex < iIndex && PrevCell[iPrevIndex] == PATTERN3D_YYARN
2793 && GetYarnIndex(i, PrevCellIndex, iPrevIndex) == WeftYarnIndex))
2794 {
2795 InsertWeftNode(YarnSection, 0.8, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2796 InsertWeftNode(YarnSection, 0.85, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2797 }
2798 InsertWeftNode(YarnSection, 0.9, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2799 InsertWeftNode(YarnSection, 0.95, WarpAboveNode, CurrentNode, WeftYarnIndex, -(dWeftOffset + m_dGapSize));
2800 CurrentNode--;
2801
2802 if (iNextIndex - iIndex > 2)
2803 {
2804 SectionPoint = YarnSection->GetPoint(0);
2805 NewNode = WarpAboveNode;
2806 NewNode.y = NewNode.y + SectionPoint.x + dWeftOffset + m_dGapSize;
2807 NewNode.z = NewNode.z + SectionPoint.y;
2808 m_Yarns[WeftYarnIndex].InsertNode(NewNode, CurrentNode + 1);
2809 CurrentNode++;
2810 }
2811 }
2812
2813 delete YarnSection;
2814 }
2815
2816 if (iStartNode == 0 && m_bWeftRepeat)
2817 {
2818 XYZ NewNode = m_Yarns[WeftYarnIndex].GetNode(0)->GetPosition();
2819 ReplaceLastNode(WeftYarnIndex, NewNode, WeftNode);
2820 }
2821
2822 return CurrentNode;
2823}
2824
2825int CTextileOrthogonal::GetWeftYarnIndex(const vector<int> &YarnCell, int n) const
2826{
2827 int i = YarnCell.size()-1;
2828 int YarnCount = 0;
2829 while ( i > 0 )
2830 {
2831 if (YarnCell[i] != -1)
2832 {
2833 if (YarnCount == n)
2834 return YarnCell[i]; // Returns the YYarn index
2835 else
2836 YarnCount++;
2837 }
2838 --i;
2839 }
2840 return -1; // No weft found
2841}
2842
2844{
2845 //PROFILE_FUNC();
2846 int iNumXYarns = m_iNumXYarns;
2847
2848 for (int i = 0; i < m_iNumYYarns; ++i)
2849 {
2850 int NumWefts = m_YYarns[i].size(); // Get the number of weft yarns in the stack
2851 for (int k = 0; k < NumWefts; ++k) // Need to loop for each of the weft yarns in the stack
2852 {
2853 int CurrentYNode = 0;
2854 const vector<int> &YarnCell = GetYarnCell(i, 0);
2855 int WeftIndex = GetWeftYarnIndex(YarnCell, k); // This is the index into the set of y-yarns
2856 if (WeftIndex == -1)
2857 continue; // This may not work where partial weft insertions as with the Aachen textiles
2858
2859 for (int j = 0; j < iNumXYarns; ++j) // Add nodes for each warp yarn position
2860 {
2861 CurrentYNode = AddWeftNodes(CurrentYNode, i, j, WeftIndex);
2862 CurrentYNode++;
2863 }
2864 m_bNeedsBuilding = false;
2866 }
2867 }
2868}
#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 TGLOG(MESSAGE)
Definition: Logger.h:36
#define NULL
Definition: ShinyConfig.h:50
#define TOL
#define BOTTOM
#define TOP
Bezier interpolation for yarn paths.
Abstract base class for describing the yarn path interpolations.
Definition: Interpolation.h:33
virtual CSlaveNode GetNode(const vector< CNode > &MasterNodes, int iIndex, double t) const =0
Get a node from parametric function. Initialise should be called first.
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
void Convert3Dto2D()
Convert all 3D elements to 2D elements representing their surface.
Definition: Mesh.cpp:576
void Clear()
Empty mesh nodes and indices.
Definition: Mesh.cpp:1448
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.
Definition: Mesh.cpp:1633
Represents a point on the centreline of a yarn.
Definition: Node.h:28
XYZ GetUp() const
Definition: Node.h:59
XYZ GetTangent() const
Definition: Node.h:58
void AddRow(string Row)
Add a row representing one weft insertion '1' indicates warp up, '0' warp down and '2' no yarn.
Elliptical Section.
CSection * Copy() const
Create a copy of the derived section and return a pointer to the newly created instance.
Abstract base class respresenting a yarn cross-section.
Definition: Section.h:31
virtual CSection * Copy() const =0
Create a copy of the derived section and return a pointer to the newly created instance.
void AssignSectionMesh(const CSectionMesh &SectionMesh)
Assign a mesh to the section.
Definition: Section.cpp:227
virtual string GetType() const =0
Derived class should return the class name.
static double GetArea(const vector< XY > &Section)
Get the area of a section.
Definition: Section.cpp:261
virtual const vector< XY > & GetPoints(int iNumPoints, bool bEquiSpaced=false) const
Get a section with given number of points on the perimeter.
Definition: Section.cpp:119
virtual XY GetPoint(double t) const =0
Get a point lying on the perimeter correspending to parametric value t.
Hybrid of any number of other sections.
Definition: SectionHybrid.h:29
XY GetPoint(double t) const
Get a point lying on the perimeter correspending to parametric value t.
Create a rectangular mesh, the number of layers can be specified or set as -1 for automatic determina...
Creates a polygonal section, where a list of points are given to form the closed polygon.
CSection * Copy() const
Create a copy of the derived section and return a pointer to the newly created instance.
void SetHeight(double dHeight)
A derivation of the CNode class which contains data specific to slave nodes such as sections.
Definition: SlaveNode.h:30
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 FindWarpBelowIndex(const vector< PATTERN3D > &Cell, int iIndex) const
int GetYarnIndex(int x, int y, int z) const
void FindPowerEllipseSectionHeight(double &MaxHeight, double &TargetArea, CSectionPowerEllipse *YarnSection) const
void SetYarnProperties(CYarn &Yarn, int iType) const
void CheckUpVectors(int WarpIndex, bool Yarn=PATTERN3D_XYARN, bool bYarnsIndex=false) const
int FindWarpAboveIndex(const vector< PATTERN3D > &Cell, int iIndex) const
bool AdjustPowerEllipseSectionWidth(double &HeightReduction, double &MaxWidth, double TargetArea, CSectionPowerEllipse *YarnSection) const
Adjust section to target height whilst maintaining cross-sectional area.
double GetHeight() const
Get the height of the unit cell.
int FindPrevYCellIndex(int Starti, int j, int k) const
Find next cell in x direction which isn't a noyarn, searching backwards.
int FindWeftHeight(const vector< PATTERN3D > &Cell) const
int FindNextCellIndex(int index) const
Find next cell in y direction which isn't a binder yarn.
int FindNextYCellIndex(int Starti, int j, int k) const
Find next cell in x direction which isn't a noyarn.
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.
CSection * GetCrossSection(int YarnIndex, int Node=-1) const
Gets the cross-section of a yarn, either constant or interp node, power elliptical sections.
void AddWarpLayer()
Add yarns parallel to the X axis in warp yarn positions, no yarns in binder positions.
void InsertWeftNode(CSection *YarnSection, double t, XYZ &WarpNode, int &CurrentNode, int WeftYarnIndex, double Offset, bool bInsert=true) const
void ReducePowerEllipseHeight(double &TargetArea, CSectionPowerEllipse *YarnSection) const
void RemoveCell(int x, int y)
bool AdjustPowerEllipsePower(double &HeightReduction, double TargetArea, CSectionPowerEllipse *YarnSection, double MinPower) const
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
void ReplaceThroughBinderSection(int BinderYarnIndex, int Node, CSection &Section, map< pair< int, int >, YARNDATA >::iterator &itBinderData) const
Replace binder cross section with default if at top, adjusted if through thickness with spacing narro...
vector< int > & GetYarnCell(int x, int y)
virtual string GetType() const
Derived class should return the class name.
void ShapeBinderYarns() const
Shape the binder yarns around the weft at top and bottom.
XY GetSectionPoint(CSection *YarnSection, double t) const
Get section point for power ellipse or hybrid section.
void ReplaceYarnSection(int YarnIndex, int Node, CSection &Section) const
Replace the yarn cross section at the given index.
int FindNextBinderIndex(int StartIndex) const
void SwapBinderPosition(int x, int y)
Binders in orthogonal weaves are either at the top or bottom of stack.
vector< vector< int > > m_WeftYarns
virtual void SetupLayers(int iNumWarpLayers, int iNumWeftLayers, int iNumBinderLayers=1)
Find min and max z values for the textile.
void AdjustWeftToFitBinderHeight(int i, int j, CSectionPowerEllipse &PowerEllipseSection, double &MaxWidth, double &TargetArea, double &MaxVolumeFraction, double &FibreArea) const
void OffsetYarn(int i, int j, int k, double dHeight, int YarnType) const
Offset yarn at position i,j at cell height k by dHeight in the z direction.
void ChangeWeftSection(CSection &TopHalf, CSection &BottomHalf, int YarnIndex, int Node, double Offset) const
int FindWeftYarnIndex(int WeftIndex) const
Find yarn index from m_YYarns using single weft index.
int AddWeftNodes(int CurrentNode, int i, int j, int WeftIndex) const
Add weft nodes around outline of adjacent warp yarns.
void CorrectCrimpInterference(int i, int j, int WeftYarnIndex, bool IsTop) const
Correct interference int warp yarn caused by creating crimp in top/bottom weft yarns.
void AdjustBinderYarnSection(int i, int j) const
Adjust binder section for specified i,j position.
void ChangePowerEllipseSection(double &TargetArea, CSectionPowerEllipse *YarnSection, double FibreArea) const
void CheckBinderWidths() const
Check if binder yarn widths are greater than through thickness spacing. Adjust to fit if necessary.
int FindBinderHeight(const vector< PATTERN3D > &Cell) const
Find the height of the binder yarn within a cell.
virtual void ConvertToPatternDraft(int iWeftOrder=BOTTOM_TO_TOP)
bool m_bWeavePattern
Indicates whether textile is loaded from weave pattern.
double GetHybridWidth(CSectionHybrid *Section) const
Get width of hybrid section.
bool AdjustWeftHeight(CSectionPowerEllipse &PowerEllipseSection, double &MaxWidth, double &TargetArea, double &MaxVolumeFraction, double &FibreArea, double TargetHeight) const
map< pair< int, int >, YARNDATA > m_BinderData
bool AdjustMidLayerHeights() const
Adjust height of inside layers to meet specified textile thickness, keeping yarn cross-sectional area...
double GetHybridSectionWidth(int WarpIndex, int WeftIndex) const
void MoveBinderYarnPosition(vector< PATTERN3D > &Cell)
Move binder yarn to top/bottom of weft stack if there are no_yarns in cell.
virtual void SetupWeftRow(vector< int > &Layers, vector< int > &Row, int NumWarps, int Weft)
Set up row of pattern cells for one weft pattern using one row of weave pattern data and the layers p...
int FindWeftYarnHeight(const vector< PATTERN3D > &YarnCell, int WeftIndex) const
Find position of given yarn index in YarnCell.
virtual void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType)
Used for saving data to XML.
void AdjustBinderPosition(int iCellIndex, int i, int j, double dHeight, bool bIsTop) const
void AdjustBinderYarns() const
Adjust binder yarn cross sections to fit specified yarn thickness.
void ChangeBinderSection(CSection &TopHalf, CSection &BottomHalf, int YarnIndex, int Node, double Offset) const
virtual bool BuildTextile() const
Build the textile.
double GetHybridHeight(CSectionHybrid *Section) const
Get height of hybrid section. Assumes max height at mid-point.
int GetWeavePatternYarnIndex(int x, int y, int z) const
int GetWeftYarnIndex(const vector< int > &YarnCell, int n) const
Finds the y-yarn index of the nth weft yarn in a YarnCell.
CTextileOrthogonal(int iNumXYarns, int iNumYYarns, double dXSpacing, double dYSpacing, double dXHeight, double dYHeight, bool bRefine=false, bool bWeavePattern=false)
Build a weave unit cell of given width, height, yarn spacing and fabric thickness.
int AddBinderNodes(int CurrentNode, int i, int j) const
Add extra nodes to binder yarns to match shape of adjacent weft yarns.
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.
Abstract base class used to define the sections along the length of a yarn.
Definition: YarnSection.h:58
virtual vector< XY > GetSection(const YARN_POSITION_INFORMATION PositionInfo, int iNumPoints, bool bEquiSpaced=false) const =0
This function must be implemented by derived classes.
Creates a section which is linearly interpolated between sections defined at the nodes.
void ReplaceSection(int iIndex, const CSection &Section)
Replace a section at a node.
void AddSection(const CSection &Section)
Add a section at a node.
const CSection & GetNodeSection(int iIndex) const
void InsertSection(int iIndex, const CSection &Section)
Insert a section at a node.
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
double DotProduct(const XYZ &left, const XYZ &right)
Get the dot product of two vectors.
Definition: mymath.h:512
XYZ CrossProduct(const XYZ &left, const XYZ &right)
Get the cross product of two vectors.
Definition: mymath.h:524
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
Data structure to keep track of yarn parameters.