TexGen
YarnSectionInterpNode.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2006 Martin Sherburn
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18=============================================================================*/
19
20#include "PrecompiledHeaders.h"
23//#include "TexGen.h"
24using namespace TexGen;
25
26CYarnSectionInterpNode::CYarnSectionInterpNode(bool bRamped, bool bPolar, bool bConstMesh)
27: CYarnSectionInterp(bRamped, bPolar, bConstMesh)
28{
29}
30
32{
33}
34
36: CYarnSectionInterp(Element)
37{
38 int i = 0;
39 FOR_EACH_TIXMLELEMENT(pNodeSection, Element, "NodeSection")
40 {
41 TiXmlElement* pSection = pNodeSection->FirstChildElement("Section");
42 if (pSection)
43 {
44 m_Sections.push_back(CSection::CreateSection(*pSection));
45 }
46 FOR_EACH_TIXMLELEMENT(pMidNodeSection, *pNodeSection, "MidNodeSection")
47 {
48 if (i >= (int)m_MidNodeSections.size())
49 m_MidNodeSections.resize(i+1);
50 pSection = pMidNodeSection->FirstChildElement("Section");
51 if (pSection)
52 {
53 m_MidNodeSections[i].push_back(make_pair(
54 valueify<double>(pMidNodeSection->Attribute("t")),
56 ));
57 }
58 }
59 ++i;
60 }
61 m_MidNodeSections.resize(m_Sections.size()-1);
62}
63
64void CYarnSectionInterpNode::PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType) const
65{
67
68 int i, j;
69 for (i=0; i<(int)m_Sections.size(); ++i)
70 {
71 TiXmlElement NodeSection("NodeSection");
72 NodeSection.SetAttribute("nodeindex", i);
73 TiXmlElement Section("Section");
74 m_Sections[i]->PopulateTiXmlElement(Section, OutputType);
75 NodeSection.InsertEndChild(Section);
76 if (i < (int)m_MidNodeSections.size())
77 {
78 for (j=0; j<(int)m_MidNodeSections[i].size(); ++j)
79 {
80 TiXmlElement MidSideNode("MidNodeSection");
81 MidSideNode.SetAttribute("nodeindex", i);
82 MidSideNode.SetAttribute("t", stringify(m_MidNodeSections[i][j].first));
83 TiXmlElement MidSection("Section");
84 m_MidNodeSections[i][j].second->PopulateTiXmlElement(MidSection, OutputType);
85 MidSideNode.InsertEndChild(MidSection);
86 NodeSection.InsertEndChild(MidSideNode);
87 }
88 }
89 Element.InsertEndChild(NodeSection);
90 }
91}
92
93vector<XY> CYarnSectionInterpNode::GetSection(const YARN_POSITION_INFORMATION PositionInfo, int iNumPoints, bool bEquiSpaced) const
94{
95 if (PositionInfo.SectionLengths.size()+1 != m_Sections.size())
96 {
97 // The number of sections specified is not equal to the number of nodes specified.
98 TGERROR("Unable to get section, the number of sections specified (" << m_Sections.size() << ") is not equal to the number of nodes (" << PositionInfo.SectionLengths.size()+1 << ")");
99 assert(false);
100 return vector<XY>();
101 }
102
103 const CSection *pSection1, *pSection2;
104 double u;
105 GetSectionsToInterp(PositionInfo, pSection1, pSection2, u);
106
107 vector<XY> Points;
108 GetInterpedSection(*pSection1, *pSection2, u, iNumPoints, bEquiSpaced, Points);
109
110 return Points;
111}
112
113CMesh CYarnSectionInterpNode::GetSectionMesh(const YARN_POSITION_INFORMATION PositionInfo, int iNumPoints, bool bEquiSpaced) const
114{
115 if (PositionInfo.SectionLengths.size()+1 != m_Sections.size())
116 {
117 // The number of sections specified is not equal to the number of nodes specified.
118 TGERROR("Unable to get section mesh, the number of sections specified (" << m_Sections.size() << ") is not equal to the number of nodes (" << PositionInfo.SectionLengths.size()+1 << ")");
119 assert(false);
120 return CMesh();
121 }
122
123 const CSection *pSection1, *pSection2;
124 double u;
125 GetSectionsToInterp(PositionInfo, pSection1, pSection2, u);
126
127 CMesh Mesh;
128 GetInterpedSectionMesh(*pSection1, *pSection2, u, iNumPoints, bEquiSpaced, Mesh);
129
130 return Mesh;
131}
132
134{
135 m_Sections.push_back(Section);
136 m_MidNodeSections.resize(m_Sections.size()-1);
137}
138
139void CYarnSectionInterpNode::InsertSection(int iIndex, const CSection &Section)
140{
141 if (iIndex < 0 || iIndex >= (int)m_Sections.size())
142 {
143 TGERROR("Unable to insert section, index out of range " << iIndex);
144 return;
145 }
146 m_Sections.insert(m_Sections.begin()+iIndex, Section);
147 m_MidNodeSections.resize(m_Sections.size()-1);
148}
149
150void CYarnSectionInterpNode::InsertSection(int iIndex, double u, const CSection &Section)
151{
152 if (iIndex < 0 || iIndex >= (int)m_MidNodeSections.size())
153 {
154 TGERROR("Unable to insert section, index out of range " << iIndex);
155 return;
156 }
157 m_MidNodeSections[iIndex].push_back(pair<double, CObjectContainer<CSection> >(u, Section));
158 sort(m_MidNodeSections[iIndex].begin(), m_MidNodeSections[iIndex].end(), LessPairDoubleObjectRef<CSection>());
159}
160
161void CYarnSectionInterpNode::ReplaceSection(int iIndex, const CSection &Section)
162{
163 if (iIndex < 0 || iIndex >= (int)m_Sections.size())
164 {
165 TGERROR("Unable to replace section, index out of range " << iIndex);
166 return;
167 }
168 m_Sections[iIndex] = Section;
169}
170
172{
173 assert(iIndex >= 0 && iIndex < (int)m_Sections.size());
174 return *m_Sections[iIndex];
175}
176
177/*int CYarnSectionInterpNode::ConvertToLocalT( int t )
178{
179 int iNumSections = MasterNodes.size()-1;
180 t *= iNumSections;
181 int iIndex = int(t);
182 t -= iIndex;
183 if (iIndex >= iNumSections)
184 {
185 iIndex = iNumSections-1;
186 t = 1;
187 }
188}*/
189
190void CYarnSectionInterpNode::GetSectionsToInterp(const YARN_POSITION_INFORMATION PositionInfo, const CSection* &pSection1, const CSection* &pSection2, double &u) const
191{
192 pSection1 = m_Sections[PositionInfo.iSection];
193 pSection2 = m_Sections[PositionInfo.iSection+1];
194 u = PositionInfo.dSectionPosition;
195 vector<pair<double, CObjectContainer<CSection> > >::const_iterator itSection;
196 int iMidSection1 = -1, iMidSection2 = -1;
197 int i;
198 double u1, u2;
199 assert(PositionInfo.iSection < (int)m_MidNodeSections.size());
200 for (itSection = m_MidNodeSections[PositionInfo.iSection].begin(), i = 0;
201 itSection != m_MidNodeSections[PositionInfo.iSection].end(); ++itSection, ++i)
202 {
203 if (itSection->first < PositionInfo.dSectionPosition)
204 {
205 iMidSection1 = i;
206 u1 = itSection->first;
207 }
208 else
209 {
210 iMidSection2 = i;
211 u2 = itSection->first;
212 break;
213 }
214 }
215 if (iMidSection1 != -1 && iMidSection2 != -1)
216 {
217 pSection1 = m_MidNodeSections[PositionInfo.iSection][iMidSection1].second;
218 pSection2 = m_MidNodeSections[PositionInfo.iSection][iMidSection2].second;
219 u = (PositionInfo.dSectionPosition - u1)/(u2-u1);
220 }
221 else if (iMidSection1 != -1)
222 {
223 pSection1 = m_MidNodeSections[PositionInfo.iSection][iMidSection1].second;
224 u = (PositionInfo.dSectionPosition - u1)/(1-u1);
225 }
226 else if (iMidSection2 != -1)
227 {
228 pSection2 = m_MidNodeSections[PositionInfo.iSection][iMidSection2].second;
229 u = PositionInfo.dSectionPosition/u2;
230 }
231}
232
234{
235
236 int iNumSections = (int)m_Sections.size();
237
238 CSection* Section = m_Sections[0]->Copy();
239 int iNumLayers = Section->GetSectionMeshLayers();
240 int iMaxLayers = iNumLayers;
241 delete Section;
242
243 if ( iNumLayers != -1 ) // Num layers has been set. Check that all set to same value
244 {
245 int i;
246 for ( i = 1; i < iNumSections; ++i )
247 {
248
249 CSection* Section = m_Sections[i]->Copy();
250
251 if ( Section->GetSectionMeshLayers() != iNumLayers )
252 {
253 delete Section;
254 break;
255 }
256 delete Section;
257 }
258 if ( i == iNumSections ) // Return if all same
259 return;
260 }
261
262 // Not all set the same so calculate
263 for ( int i = 0; i < iNumSections; ++i )
264 {
265 int iNumLayers = CalculateNumberofLayers(m_Sections[i]->GetPoints( iNumPoints, true ));
266
267 if ( iNumLayers > iMaxLayers )
268 iMaxLayers = iNumLayers;
269
270 if ( i < iNumSections-1 )
271 {
272 for ( int j = 0; j < (int)m_MidNodeSections[i].size(); ++j )
273 {
274 iNumLayers = CalculateNumberofLayers(m_MidNodeSections[i][j].second->GetPoints( iNumPoints, true ));
275 if ( iNumLayers > iMaxLayers )
276 iMaxLayers = iNumLayers;
277 }
278 }
279 }
280 if ( iMaxLayers != -1 )
281 {
282 for ( int i = 0; i < (int)m_Sections.size(); ++i )
283 {
284 const CSection* pSection = m_Sections[i]; // Convoluted but can't find another way to get around this at the moment
285 CSection* pSection2 = const_cast<CSection*> (pSection);
286 pSection2->SetSectionMeshLayers(iMaxLayers);
287
288 if ( i < iNumSections-1 )
289 {
290 for ( int j = 0; j < (int)m_MidNodeSections[i].size(); ++j )
291 {
292 const CSection* pSection = m_MidNodeSections[i][j].second; // Convoluted but can't find another way to get around this at the moment
293 CSection* pSection2 = const_cast<CSection*> (pSection);
294 pSection2->SetSectionMeshLayers(iMaxLayers);
295 }
296 }
297 }
298
299 }
300}
301
303{
304 if (iIndex < 0 || iIndex >= (int)m_Sections.size())
305 {
306 TGERROR("Unable to delete section, index out of range " << iIndex);
307 return;
308 }
309 m_Sections.erase(m_Sections.begin()+iIndex);
310 m_MidNodeSections.resize(m_Sections.size()-1);
311}
312
314{
315 if ( iIndex < 0 || iIndex >= (int)m_Sections.size())
316 {
317 TGERROR("Unable to get number of mid node sections, index out of range " << iIndex );
318 return(0);
319 }
320 return( (int)m_MidNodeSections[iIndex].size() );
321}
322
323double CYarnSectionInterpNode::GetMidNodeSectionPos( int iNodeIndex, int iIndex ) const
324{
325 assert(iNodeIndex >= 0 && iNodeIndex < (int)m_Sections.size());
326 assert(iIndex >= 0 && iIndex < (int)m_MidNodeSections[iNodeIndex].size() );
327
328 return( m_MidNodeSections[iNodeIndex][iIndex].first );
329}
330
331void CYarnSectionInterpNode::ReplaceMidSection(int iNodeIndex, int iIndex, const CSection &Section)
332{
333 if (iNodeIndex < 0 || iNodeIndex >= (int)m_Sections.size())
334 {
335 TGERROR("Unable to replace mid section, index out of range " << iNodeIndex);
336 return;
337 }
338 if ( iIndex < 0 || iIndex >= (int)m_MidNodeSections[iNodeIndex].size() )
339 {
340 TGERROR("Unable to replace mid section, mid index out of range " << iIndex);
341 return;
342 }
343 m_MidNodeSections[iNodeIndex][iIndex].second = Section;
344}
345
#define TGERROR(MESSAGE)
Macros used to report the file name and line number to the TexGenError and TexGenLog functions.
Definition: Logger.h:29
#define FOR_EACH_TIXMLELEMENT(CHILDELEMENT, PARENTELEMENT, ELEMENTNAME)
Macro to enable looping over tinyxml easier.
Definition: Misc.h:45
Defines the nodes and elements of a surface or volume mesh.
Definition: Mesh.h:58
Object container to help handle memory management issues.
Abstract base class respresenting a yarn cross-section.
Definition: Section.h:31
static CObjectContainer< CSection > CreateSection(TiXmlElement &Element)
Create a section from TiXmlElement.
Definition: Section.cpp:78
void SetSectionMeshLayers(int iNum)
Specify number of layers for associated section mesh.
Definition: Section.cpp:232
int GetSectionMeshLayers()
Get the number of layers for associated section mesh.
Definition: Section.cpp:239
Abstract base class to handle interpolation for derived classes.
virtual void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType) const
Used for saving data to XML.
int CalculateNumberofLayers(const vector< XY > &Section) const
bool GetInterpedSection(const CSection &Section1, const CSection &Section2, double u, int iNumPoints, bool bEquiSpaced, vector< XY > &Points) const
bool GetInterpedSectionMesh(const CSection &Section1, const CSection &Section2, double u, int iNumPoints, bool bEquiSpaced, CMesh &Mesh) const
void ReplaceMidSection(int iNodeIndex, int iIndex, const CSection &Section)
Replace a mid node section.
double GetMidNodeSectionPos(int iNodeIndex, int iIndex) const
void ReplaceSection(int iIndex, const CSection &Section)
Replace a section at a node.
void AddSection(const CSection &Section)
Add a section at a node.
CMesh GetSectionMesh(const YARN_POSITION_INFORMATION PositionInfo, int iNumPoints, bool bEquiSpaced) const
This function must be implemented by derived classes.
void GetSectionsToInterp(const YARN_POSITION_INFORMATION PositionInfo, const CSection *&pSection1, const CSection *&pSection2, double &u) const
vector< vector< pair< double, CObjectContainer< CSection > > > > m_MidNodeSections
const CSection & GetNodeSection(int iIndex) const
vector< CObjectContainer< CSection > > m_Sections
void InsertSection(int iIndex, const CSection &Section)
Insert a section at a node.
vector< XY > GetSection(const YARN_POSITION_INFORMATION PositionInfo, int iNumPoints, bool bEquiSpaced=false) const
This function must be implemented by derived classes.
void DeleteSection(int iIndex)
Delete a section at a node.
void PopulateTiXmlElement(TiXmlElement &Element, OUTPUT_TYPE OutputType) const
Used for saving data to XML.
int GetNumMidNodeSections(int iIndex) const
CYarnSectionInterpNode(bool bRamped=true, bool bPolar=false, bool bConstMesh=true)
void SetSectionMeshLayersEqual(int iNumPoints) const
Function to set the number of layers equal for all sections in a given yarn.
Namespace containing a series of customised math operations not found in the standard c++ library.
OUTPUT_TYPE
Definition: Misc.h:105
std::string stringify(const T &x, int iPrecision=12, bool bScientific=true)
Function to convert a value (e.g. int, double, etc...) to a string.
Definition: Misc.h:50
Used to sort double-objectref pairs.
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