TexGen
TexGenRenderer.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"
21#include "TexGenRenderer.h"
23
24//#include "../Core/TexGen.h"
25using namespace TexGen;
26CTexGenRenderer::CTexGenRenderer(vtkRenderWindowInteractor *pRenderWindowInteractor)
27: m_pRenderer(NULL)
28, m_pRenderWindow(NULL)
29, m_pRenderWindowInteractor(pRenderWindowInteractor)
30, m_pOrientationMarkerWidget(NULL)
31, m_pCallback(NULL)
32, m_bXRay(false)
33, m_bTrimToDomain(true)
34, m_iBatchCount(0)
35{
36 m_pRenderer = vtkRenderer::New();
37
39 {
40 m_pRenderWindow = vtkRenderWindow::New();
41 m_pRenderWindowInteractor = vtkRenderWindowInteractor::New();
42
43 m_pRenderWindow->AddRenderer(m_pRenderer);
45 }
46 // interactor style
47// vtkInteractorStyleTerrain *pInteractionStyle = vtkInteractorStyleTerrain::New();
49 m_pRenderWindowInteractor->SetInteractorStyle(pInteractionStyle);
50 pInteractionStyle->Delete();
51
52 m_pOrientationMarkerWidget = vtkOrientationMarkerWidget::New();
53 vtkAxesActor* pAxes = vtkAxesActor::New();
54 pAxes->GetXAxisCaptionActor2D()->GetCaptionTextProperty()->ShadowOn();
55 pAxes->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->ShadowOn();
56 pAxes->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->ShadowOn();
57
58 m_pOrientationMarkerWidget->SetOrientationMarker(pAxes);
59 pAxes->Delete();
60 m_pOrientationMarkerWidget->SetViewport(0.0, 0.0, 0.15, 0.3);
62 m_pOrientationMarkerWidget->SetDefaultRenderer(m_pRenderer);
63
64 vtkCamera *camera = m_pRenderer->GetActiveCamera();
65
66 camera->SetFocalPoint(0, 1, -0.5);
67 camera->SetPosition(0, 0, 0);
68 camera->SetViewUp(0, 0, 1);
69}
70
72{
73 if (m_pRenderer)
74 {
75 m_pRenderer->Delete();
77 }
78 if (m_pRenderWindow) // If render window was created then window interactor was also created, otherwise it was created by an external source and should not be deleted
79 {
80 m_pRenderWindow->Delete();
83 {
86 }
87 }
89 {
91 }
92}
93
95{
96 m_pRenderer->SetBackground(Color.Array());
99}
100
101void CTexGenRenderer::SetParallelProjection(bool bParallelProjection)
102{
103 if (bParallelProjection)
104 m_pRenderer->GetActiveCamera()->ParallelProjectionOn();
105 else
106 m_pRenderer->GetActiveCamera()->ParallelProjectionOff();
107 RefreshView();
108}
109
111{
112 return m_pRenderer->GetActiveCamera()->GetParallelProjection()?true:false;
113}
114
116{
117 m_bXRay = bXRay;
118}
119
121{
122 m_bTrimToDomain = bTrim;
123}
124
125void CTexGenRenderer::Start(bool bTakeControl, int iWidth, int iHeight, bool bFullScreen)
126{
127 m_pRenderWindow->SetSize(iWidth, iHeight);
128 if (bFullScreen)
129 m_pRenderWindow->FullScreenOn();
130 m_pRenderWindow->Render();
131
132 if (bTakeControl)
133 {
134 TGLOG("Starting rendering");
136 }
137}
138
139void CTexGenRenderer::TakeScreenShot(string FileName, int iMagnification)
140{
141 vtkRenderLargeImage* pRenderLarge = vtkRenderLargeImage::New();
142 pRenderLarge->SetInput(m_pRenderer);
143 pRenderLarge->SetMagnification(iMagnification);
144
145 // If magnifying need to turn off axes otherwise they are tiled across image
146 int iAxes = m_pOrientationMarkerWidget->GetEnabled();
147 if ( iMagnification > 1 && iAxes )
148 m_pOrientationMarkerWidget->SetEnabled(0);
149
150/* vtkImageCast* pCast = vtkImageCast::New();
151 pCast->SetInputConnection(pRenderLarge->GetOutputPort());
152 pCast->SetOutputScalarType(pRenderLarge->GetOutput()->GetScalarType());
153 pCast->ClampOverflowOn();
154
155 vtkImageResample* pResample = vtkImageResample::New();
156 pResample->SetInputConnection(pCast->GetOutputPort());
157 pResample->SetDimensionality(2);
158 pResample->SetAxisMagnificationFactor(0, 2);
159 pResample->SetAxisMagnificationFactor(1, 2);*/
160
161 // We write out the image which causes the rendering to occur. If you
162 // watch your screen you might see the pieces being rendered right
163 // after one another.
164 vtkPNGWriter* pPNGWriter = vtkPNGWriter::New();
165 pPNGWriter->SetInputConnection(pRenderLarge->GetOutputPort());
166 pPNGWriter->SetFileName(FileName.c_str());
167 pPNGWriter->Write();
168
169 // Restore axes
170 m_pOrientationMarkerWidget->SetEnabled(iAxes);
171
172 pRenderLarge->Delete();
173// pCast->Delete();
174// pResample->Delete();
175 pPNGWriter->Delete();
176}
177
179{
180/* vtkActorCollection *Actors = m_pRenderer->GetActors();
181 vtkActor *Actor;
182 for (Actors->InitTraversal(); (Actor = Actors->GetNextItem())!=NULL; )
183 {
184 m_pRenderer->RemoveActor(Actor);
185 }*/
186// multimap<PROP_TYPE, vtkProp*>::iterator itProp;
187 while (!m_Props.empty())
188 RemoveProp(m_Props.begin()->second);
189/* for (itProp = m_Props.begin(); itProp != m_Props.end(); ++itProp)
190 {
191 RemoveProp(itProp->second);
192// m_pRenderer->RemoveViewProp(itProp->second);
193 }*/
194// m_Props.clear();
195 RefreshView();
196}
197
199{
200 multimap<PROP_TYPE, vtkProp*>::iterator itProp;
201 while ((itProp = m_Props.find(Type)) != m_Props.end())
202 RemoveProp(itProp->second);
203/* for (itProp = m_Props.lower_bound(Type); itProp != m_Props.upper_bound(Type); ++itProp)
204 {
205 RemoveProp(itProp->second);
206// m_pRenderer->RemoveViewProp(itProp->second);
207 }*/
208// m_Props.erase(m_Props.lower_bound(Type), m_Props.upper_bound(Type));
209 RefreshView();
210}
211
213{
214 multimap<PROP_TYPE, vtkProp*>::iterator itProp;
215 for (itProp = m_Props.lower_bound(Type); itProp != m_Props.upper_bound(Type); ++itProp)
216 {
217 vtkActor* pActor = dynamic_cast<vtkActor*>(itProp->second);
218 if (pActor)
219 {
220 ApplyColor(pActor, Color);
221 }
222 }
223 RefreshView();
224}
225
227{
228 // Simulate the fact that the axes are a prop inside the scene
229 if (Type == PROP_AXES)
230 return m_pOrientationMarkerWidget->GetEnabled();
231 return m_Props.count(Type);
232}
233
234vector<vtkProp*> CTexGenRenderer::GetProps(set<PROP_TYPE> Types)
235{
236 vector<vtkProp*> Props;
237 multimap<PROP_TYPE, vtkProp*>::iterator itProp;
238 for (itProp = m_Props.begin(); itProp != m_Props.end(); ++itProp)
239 {
240 if (Types.count(itProp->first))
241 {
242 Props.push_back(itProp->second);
243 }
244 }
245 return Props;
246}
247
249{
250 vector<vtkProp*> Props;
251 pair<multimap<PROP_TYPE, vtkProp*>::iterator, multimap<PROP_TYPE, vtkProp*>::iterator> Range = m_Props.equal_range(Type);
252 multimap<PROP_TYPE, vtkProp*>::iterator itProp;
253 for (itProp = Range.first; itProp != Range.second; ++itProp)
254 {
255 Props.push_back(itProp->second);
256 }
257 return Props;
258}
259
261{
262 map<vtkProp*, PROP_YARN_INFO>::const_iterator itProp = m_YarnProps.find(pProp);
263 if (itProp != m_YarnProps.end())
264 {
265 return &itProp->second;
266 }
267 return NULL;
268}
269
271{
272 map<vtkProp*, PROP_NODE_INFO>::const_iterator itProp = m_NodeProps.find(pProp);
273 if (itProp != m_NodeProps.end())
274 {
275 return &itProp->second;
276 }
277 return NULL;
278}
279
281{
282 map<vtkProp*, PROP_IMAGE_INFO>::const_iterator itProp = m_ImageProps.find(pProp);
283 if (itProp != m_ImageProps.end())
284 {
285 return &itProp->second;
286 }
287 return NULL;
288}
289
290vector<vtkProp*> CTexGenRenderer::GetProps(PROP_INFO* pInfo, bool bIgnoreTextileName)
291{
292 vector<vtkProp*> Props;
293 PROP_YARN_INFO* pYarnProp = dynamic_cast<PROP_YARN_INFO*>(pInfo);
294 PROP_NODE_INFO* pNodeProp = dynamic_cast<PROP_NODE_INFO*>(pInfo);
295 PROP_IMAGE_INFO* pImageProp = dynamic_cast<PROP_IMAGE_INFO*>(pInfo);
296 if (pYarnProp)
297 {
298 map<vtkProp*, PROP_YARN_INFO>::const_iterator itProp;
299 for (itProp = m_YarnProps.begin(); itProp != m_YarnProps.end(); ++itProp)
300 {
301 if (pYarnProp->iYarn == itProp->second.iYarn &&
302 (bIgnoreTextileName || pYarnProp->TextileName == itProp->second.TextileName))
303 Props.push_back(itProp->first);
304 }
305 }
306 if (pNodeProp)
307 {
308 map<vtkProp*, PROP_NODE_INFO>::const_iterator itProp;
309 for (itProp = m_NodeProps.begin(); itProp != m_NodeProps.end(); ++itProp)
310 {
311 if (pNodeProp->iNode == itProp->second.iNode &&
312 pNodeProp->iYarn == itProp->second.iYarn &&
313 (bIgnoreTextileName || pNodeProp->TextileName == itProp->second.TextileName))
314 Props.push_back(itProp->first);
315 }
316 }
317 if (pImageProp)
318 {
319 map<vtkProp*, PROP_IMAGE_INFO>::const_iterator itProp;
320 for (itProp = m_ImageProps.begin(); itProp != m_ImageProps.end(); ++itProp)
321 {
322 if (pImageProp->iImageID == itProp->second.iImageID)
323 Props.push_back(itProp->first);
324 }
325 }
326 return Props;
327}
328
329vector<vtkProp*> CTexGenRenderer::GetNodeProps(PROP_YARN_INFO Info, bool bIgnoreTextileName)
330{
331 vector<vtkProp*> Props;
332 map<vtkProp*, PROP_NODE_INFO>::const_iterator itProp;
333 for (itProp = m_NodeProps.begin(); itProp != m_NodeProps.end(); ++itProp)
334 {
335 if (Info.iYarn == itProp->second.iYarn &&
336 Info.TextileName == itProp->second.TextileName)
337 Props.push_back(itProp->first);
338 }
339 return Props;
340}
341
342void CTexGenRenderer::RefreshTextile(string TextileName)
343{
344 BeginBatch();
345 bool bSurface = (GetNumProps(PROP_SURFACE)>0);
346 bool bPath = (GetNumProps(PROP_PATH)>0);
347 bool bNodes = (GetNumProps(PROP_NODE)>0);
348 bool bVolume = (GetNumProps(PROP_VOLUME)>0);
349 set<PROP_TYPE> Types;
350 Types.insert(PROP_NODE);
351 Types.insert(PROP_PATH);
352 Types.insert(PROP_SURFACE);
353 Types.insert(PROP_VOLUME);
354 vector<vtkProp*> Props = GetProps(Types);
355 vector<vtkProp*>::iterator itProp;
356 for (itProp = Props.begin(); itProp != Props.end(); ++itProp)
357 {
358 RemoveProp(*itProp);
359 }
360 if (bSurface)
361 RenderTextile(TextileName, 1);
362 if (bPath)
363 RenderPaths(TextileName);
364 if (bNodes)
365 RenderNodes(TextileName);
366 if (bVolume)
367 RenderMesh(TextileName);
368 EndBatch();
369}
370
372{
373 BeginBatch();
374 bool bSurface = (GetNumProps(PROP_SURFACE)>0);
375 bool bPath = (GetNumProps(PROP_PATH)>0);
376 bool bNodes = (GetNumProps(PROP_NODE)>0);
377 bool bVolume = (GetNumProps(PROP_VOLUME)>0);
378 vector<vtkProp*> YarnProps = GetProps(&YarnInfo);
379 vector<vtkProp*> NodeProps = GetNodeProps(YarnInfo);
380 vector<vtkProp*> Props;
381 Props.insert(Props.end(), YarnProps.begin(), YarnProps.end());
382 Props.insert(Props.end(), NodeProps.begin(), NodeProps.end());
383 vector<vtkProp*>::iterator itProp;
384 for (itProp = Props.begin(); itProp != Props.end(); ++itProp)
385 {
386 RemoveProp(*itProp);
387 }
388 CTextile* pTextile = TEXGEN.GetTextile(YarnInfo.TextileName);
389 if (pTextile)
390 {
391 const CDomain* pDomain = NULL;
392 if (m_bTrimToDomain)
393 pDomain = pTextile->GetDomain();
394 CYarn &Yarn = pTextile->GetYarns()[YarnInfo.iYarn];
395 if (bSurface)
396 {
397 vtkProp* pYarnProp = RenderYarn(Yarn, pDomain, GetIndexedColor(YarnInfo.iYarn), 1);
398 if (pYarnProp)
399 {
400 m_YarnProps[pYarnProp] = YarnInfo;
401 }
402 }
403 if (bPath)
404 {
405 RenderPath(*pTextile, YarnInfo.iYarn);
406 }
407 if (bNodes)
408 {
409 RenderNodes(*pTextile, YarnInfo.iYarn);
410 }
411 if( bVolume )
412 {
413 vtkProp* pYarnProp = RenderYarnMesh(Yarn, pDomain, GetIndexedColor(YarnInfo.iYarn));
414 if (pYarnProp)
415 {
416 m_YarnProps[pYarnProp] = YarnInfo;
417 }
418 }
419 }
420 EndBatch();
421}
422
423void CTexGenRenderer::AddProp(PROP_TYPE Type, vtkProp *pProp)
424{
425// if (bRefreshView)
426// {
427 int iNumPropsBefore = m_Props.size();
428 double Bounds[6];
429 m_pRenderer->ComputeVisiblePropBounds(Bounds);
430 double dDiagonalBefore = sqrt((Bounds[1]-Bounds[0])*(Bounds[1]-Bounds[0]) +
431 (Bounds[3]-Bounds[2])*(Bounds[3]-Bounds[2]) +
432 (Bounds[5]-Bounds[4])*(Bounds[5]-Bounds[4]));
433 m_pRenderer->AddViewProp(pProp);
434 m_Props.insert(make_pair(Type, pProp));
435 pProp->Delete();
436 m_pRenderer->ComputeVisiblePropBounds(Bounds);
437 double dDiagonalAfter = sqrt((Bounds[1]-Bounds[0])*(Bounds[1]-Bounds[0]) +
438 (Bounds[3]-Bounds[2])*(Bounds[3]-Bounds[2]) +
439 (Bounds[5]-Bounds[4])*(Bounds[5]-Bounds[4]));
440 if (abs(dDiagonalBefore-dDiagonalAfter) > 0.1*dDiagonalBefore || iNumPropsBefore==0)
441 ResetCamera();
442 else
443 RefreshView();
444/* }
445 else
446 {
447 m_pRenderer->AddViewProp(pProp);
448 m_Props.insert(make_pair(Type, pProp));
449 pProp->Delete();
450 }*/
451}
452
453void CTexGenRenderer::RemoveProp(vtkProp *pProp)
454{
455 m_pRenderer->RemoveViewProp(pProp);
456 m_YarnProps.erase(pProp);
457 m_NodeProps.erase(pProp);
458 m_ImageProps.erase(pProp);
459 multimap<PROP_TYPE, vtkProp*>::iterator itProp;
460 for (itProp = m_Props.begin(); itProp != m_Props.end(); )
461 {
462 if (itProp->second == pProp)
463 m_Props.erase(itProp++);
464 else
465 ++itProp;
466 }
467}
468
469vtkActor *CTexGenRenderer::ConvertToActor(vtkPolyData *pPolyData)
470{
471 vtkActor *pActor = vtkActor::New();
472 vtkPolyDataMapper *pPolyDataMapper = vtkPolyDataMapper::New();
473 pPolyDataMapper->SetInputData(pPolyData);
474 pActor->SetMapper(pPolyDataMapper);
475
476 pPolyDataMapper->Delete();
477 pPolyData->Delete();
478
479 return pActor;
480}
481
482vtkActor *CTexGenRenderer::ConvertToActor(vtkAlgorithm *pAlgorithm)
483{
484 vtkActor *pActor = vtkActor::New();
485 vtkPolyDataMapper *pPolyDataMapper = vtkPolyDataMapper::New();
486 pPolyDataMapper->SetInputConnection(pAlgorithm->GetOutputPort());
487 pActor->SetMapper(pPolyDataMapper);
488
489 pPolyDataMapper->Delete();
490 pAlgorithm->Delete();
491
492 return pActor;
493}
494
495void CTexGenRenderer::RenderTextile(string TextileName, double dOpacity)
496{
497 if (TextileName == "")
498 {
499 map<string, CTextile*>::const_iterator itTextile;
500 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
501 {
502 assert(itTextile->first != "");
503 RenderTextile(itTextile->first, dOpacity);
504 }
505 return;
506 }
507 TGLOGINDENT("Adding textile \"" << TextileName << "\" to renderer");
508 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
509 if (!pTextile)
510 return;
511 RenderTextile(*pTextile, dOpacity);
512}
513
514void CTexGenRenderer::RenderTextile(CTextile &Textile, double dOpacity)
515{
516 const CDomain *pDomain = NULL;
517 if (m_bTrimToDomain)
518 pDomain = Textile.GetDomain();
519
520 vector<CYarn>::iterator itYarn;
521
522 int i;
523 vtkProp* pProp;
524 BeginBatch();
525 for (itYarn = Textile.GetYarns().begin(), i=0; itYarn != Textile.GetYarns().end(); ++itYarn, ++i)
526 {
527 pProp = RenderYarn(*itYarn, pDomain, GetIndexedColor(i), dOpacity);
528 if (pProp)
529 {
530 PROP_YARN_INFO Info;
531 Info.iYarn = i;
532 Info.TextileName = Textile.GetName();
533 m_YarnProps[pProp] = Info;
534 }
535 }
536 EndBatch();
537}
538
539vtkProp* CTexGenRenderer::RenderYarn(CYarn &Yarn, const CDomain *pDomain, COLOR Color, double dOpacity)
540{
541 CMesh Mesh;
542
543 TGLOGINDENT("Adding yarn surface to renderer");
544 if (pDomain)
545 Yarn.AddSurfaceToMesh(Mesh, *pDomain);
546 else
547 Yarn.AddSurfaceToMesh(Mesh);
548
549 if (Mesh.NodesEmpty())
550 return NULL;
551
552 vtkActor *pActor;
553 vtkAlgorithm *pAlgorithm = CalculateNormals(GetPolyData(Mesh));
554
555 pActor = ConvertToActor(pAlgorithm);
556
557 pActor->GetProperty()->BackfaceCullingOn();
558 if (m_bXRay)
559 pActor->GetProperty()->SetRepresentationToWireframe();
560// pActor->GetProperty()->SetOpacity(0.75);
561// else
562 pActor->GetProperty()->SetOpacity(dOpacity);
563 ApplyColor(pActor, Color);
564
565
566 AddProp(PROP_SURFACE, pActor);
567
568 return pActor;
569}
570
571void CTexGenRenderer::RenderDomain(string TextileName, COLOR Color, double dOpacity)
572{
573 if (TextileName == "")
574 {
575 map<string, CTextile*>::const_iterator itTextile;
576 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
577 {
578 assert(itTextile->first != "");
579 RenderDomain(itTextile->first, Color, dOpacity);
580 }
581 return;
582 }
583 TGLOGINDENT("Adding domain of \"" << TextileName << "\" to renderer");
584 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
585 if (!pTextile)
586 return;
587
588 const CDomain *pDomain = pTextile->GetDomain();
589 if (!pDomain)
590 return;
591
592 RenderDomain(*pDomain, Color, dOpacity);
593}
594
595void CTexGenRenderer::RenderMesh(string TextileName)
596{
597 if (TextileName == "")
598 {
599 map<string, CTextile*>::const_iterator itTextile;
600 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
601 {
602 assert(itTextile->first != "");
603 RenderMesh(itTextile->first);
604 }
605 return;
606 }
607 TGLOGINDENT("Adding textile mesh\"" << TextileName << "\" to renderer");
608 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
609 if (!pTextile)
610 return;
611 RenderMesh(*pTextile);
612}
613
615{
616 const CDomain *pDomain = NULL;
617 if (m_bTrimToDomain)
618 pDomain = Textile.GetDomain();
619
620 vector<CYarn>::iterator itYarn;
621
622 int i;
623 vtkProp* pProp;
624 BeginBatch();
625 for (itYarn = Textile.GetYarns().begin(), i=0; itYarn != Textile.GetYarns().end(); ++itYarn, ++i)
626 {
627 pProp = RenderYarnMesh(*itYarn, pDomain, GetIndexedColor(i));
628 if (pProp)
629 {
630 PROP_YARN_INFO Info;
631 Info.iYarn = i;
632 Info.TextileName = Textile.GetName();
633 m_YarnProps[pProp] = Info;
634 }
635 }
636 EndBatch();
637}
638
639vtkProp* CTexGenRenderer::RenderYarnMesh(CYarn &Yarn, const CDomain *pDomain, COLOR Color)
640{
641 CMesh Mesh;
642
643 TGLOGINDENT("Adding yarn volume mesh to renderer");
644 if (pDomain)
645 Yarn.AddVolumeToMesh(Mesh, *pDomain);
646 else
647 Yarn.AddVolumeToMesh(Mesh);
648
649 if (Mesh.NodesEmpty())
650 return NULL;
651
652 vtkActor *pActor;
653 vtkAlgorithm *pAlgorithm = CalculateNormals(GetPolyData(Mesh));
654
655 pActor = ConvertToActor(pAlgorithm);
656 pActor->GetProperty()->SetRepresentationToWireframe();
657 ApplyColor(pActor, Color);
658
659
660 AddProp(PROP_VOLUME, pActor);
661
662 return pActor;
663}
664
665void CTexGenRenderer::RenderDomain(const CDomain &Domain, COLOR Color, double dOpacity)
666{
667 TGLOGINDENT("Adding domain surface to renderer");
668
669 CDomain* pCopy = Domain.Copy();
670
671 // Get rid of flicker between the ends of the yarns and the domain by growing the domain a little
672 pair<XYZ, XYZ> Limits = Domain.GetMesh().GetAABB();
673 double extend = GetLength(Limits.second - Limits.first)*1e-3;
674 pCopy->Grow(extend);
675 CMesh Mesh = pCopy->GetMesh();
676
677 delete pCopy;
678
679 if (Mesh.NodesEmpty())
680 return;
681
682 vtkActor *pActor;
683 vtkAlgorithm *pAlgorithm = CalculateNormals(GetPolyData(Mesh));
684
685 pActor = ConvertToActor(pAlgorithm);
686
687 pActor->GetProperty()->SetColor(Color.Array());
688 pActor->GetProperty()->BackfaceCullingOn();
689 pActor->GetProperty()->SetOpacity(dOpacity);
690
691 AddProp(PROP_DOMAIN, pActor);
692}
693
694void CTexGenRenderer::RenderDomainAxes(string TextileName)
695{
696 if (TextileName == "")
697 {
698 map<string, CTextile*>::const_iterator itTextile;
699 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
700 {
701 assert(itTextile->first != "");
702 RenderDomainAxes(itTextile->first);
703 }
704 return;
705 }
706 TGLOGINDENT("Adding domain of \"" << TextileName << "\" to renderer");
707 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
708 if (!pTextile)
709 return;
710
711 const CDomain *pDomain = pTextile->GetDomain();
712 if (!pDomain)
713 return;
714
715 RenderDomainAxes(*pDomain);
716}
717
719{
720 pair<XYZ, XYZ> Limits = Domain.GetMesh().GetAABB();
721
722 COLOR AnnotationColor = GetBestAnnotationColor();
723
724 // Create a text property for both cube axes
725 vtkTextProperty *tprop = vtkTextProperty::New();
726 tprop->SetColor(AnnotationColor.Array());
727 tprop->ShadowOn();
728
729 // Create a vtkCubeAxesActor2D. Use the outer edges of the bounding box to
730 // draw the axes. Add the actor to the renderer.
731 vtkCubeAxesActor2D* axes = vtkCubeAxesActor2D::New();
732 axes->SetBounds(Limits.first.x, Limits.second.x, Limits.first.y, Limits.second.y, Limits.first.z, Limits.second.z);
733 axes->SetCamera(m_pRenderer->GetActiveCamera());
734 axes->SetLabelFormat("%6.4g");
735 axes->SetFlyModeToOuterEdges();
736 axes->SetFontFactor(1.5);
737 axes->SetAxisTitleTextProperty(tprop);
738 axes->SetAxisLabelTextProperty(tprop);
739 axes->SetNumberOfLabels(2);
740 axes->GetProperty()->SetColor(AnnotationColor.Array());
741
742 tprop->Delete();
743
745}
746
748{
749 double BackGroundColor[3];
750 m_pRenderer->GetBackground(BackGroundColor);
751 double dIntensity = (BackGroundColor[0]+BackGroundColor[1]+BackGroundColor[2])/3.0;
752 if (dIntensity > 0.5)
753 return COLOR(0, 0, 0);
754 else
755 return COLOR(1, 1, 1);
756}
757
759{
760 COLOR AnnotationColor = GetBestAnnotationColor();
761 typedef multimap<PROP_TYPE, vtkProp*>::iterator PropMapIter;
762 PropMapIter itProp;
763 pair<PropMapIter, PropMapIter> Range = m_Props.equal_range(PROP_DOMAINAXES);
764 for (itProp = Range.first; itProp != Range.second; ++itProp)
765 {
766 vtkCubeAxesActor2D* pAxes = dynamic_cast<vtkCubeAxesActor2D*>(itProp->second);
767 if (pAxes)
768 {
769 pAxes->GetProperty()->SetColor(AnnotationColor.Array());
770 pAxes->GetAxisTitleTextProperty()->SetColor(AnnotationColor.Array());
771 pAxes->GetAxisLabelTextProperty()->SetColor(AnnotationColor.Array());
772 }
773 }
774
775 vtkAxesActor* pAxes = dynamic_cast<vtkAxesActor*>(m_pOrientationMarkerWidget->GetOrientationMarker());
776 if (pAxes)
777 {
778 pAxes->GetXAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(AnnotationColor.Array());
779 pAxes->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(AnnotationColor.Array());
780 pAxes->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(AnnotationColor.Array());
781 }
782}
783
784void CTexGenRenderer::RenderNodes(string TextileName)
785{
786 if (TextileName == "")
787 {
788 map<string, CTextile*>::const_iterator itTextile;
789 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
790 {
791 RenderNodes(*itTextile->second);
792 }
793 return;
794 }
795
796 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
797 if (!pTextile)
798 return;
799
800 RenderNodes(*pTextile);
801}
802
804{
805 BeginBatch();
806 int i;
807 vector<CYarn>::iterator itYarn;
808 for (i=0; i<(int)Textile.GetYarns().size(); ++i)
809 {
810 RenderNodes(Textile, i);
811 }
812 EndBatch();
813}
814
815void CTexGenRenderer::RenderNodes(CTextile &Textile, int iYarn)
816{
817// pair<XYZ, XYZ> Bounds;
818 int i;
819 XYZ Pos;
820 double dRadius = 0.01*Textile.GetApproximateSize();
821 CYarn &Yarn = Textile.GetYarns()[iYarn];
822 const vector<CNode> &Nodes = Yarn.GetMasterNodes();
823 vector<CNode>::const_iterator itNode;
824 BeginBatch();
825 for (itNode = Nodes.begin(), i=0; itNode != Nodes.end(); ++itNode, ++i)
826 {
827 vtkSphereSource* pSphere = vtkSphereSource::New();
828 pSphere->SetRadius(dRadius);
829 pSphere->SetPhiResolution(10);
830 pSphere->SetThetaResolution(10);
831 Pos = itNode->GetPosition();
832 pSphere->SetCenter(Pos.x, Pos.y, Pos.z);
833
834 vtkPolyDataMapper* pSphereMapper = vtkPolyDataMapper::New();
835 pSphereMapper->SetInputConnection(pSphere->GetOutputPort());
836
837 vtkActor* pSphereActor = vtkActor::New();
838 pSphereActor->SetMapper(pSphereMapper);
839 ApplyColor(pSphereActor, GetIndexedColor(iYarn));
840
841 pSphere->Delete();
842 pSphereMapper->Delete();
843
844 PROP_NODE_INFO Info;
845 Info.iYarn = iYarn;
846 Info.iNode = i;
847 Info.TextileName = Textile.GetName();
848 m_NodeProps[pSphereActor] = Info;
849
850 AddProp(PROP_NODE, pSphereActor);
851 }
852 EndBatch();
853}
854
855
856void CTexGenRenderer::RenderPaths(string TextileName)
857{
858 if (TextileName == "")
859 {
860 map<string, CTextile*>::const_iterator itTextile;
861 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
862 {
863 RenderPaths(*itTextile->second);
864 }
865 return;
866 }
867
868 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
869 if (!pTextile)
870 return;
871
872 RenderPaths(*pTextile);
873}
874
876{
877 int i, iNumYarns = (int)Textile.GetYarns().size();
878 BeginBatch();
879 for (i=0; i < iNumYarns; ++i)
880 {
881 RenderPath(Textile, i);
882 }
883 EndBatch();
884}
885
886void CTexGenRenderer::RenderPath(CTextile &Textile, int iYarn)
887{
888 double dRadius;
889// pair<XYZ, XYZ> Bounds;
890 CYarn &Yarn = Textile.GetYarns()[iYarn];
891 CMesh Mesh;
892 Yarn.AddPathToMesh(Mesh);
893 vtkPolyData *pPolyData = GetPolyData(Mesh);
894
895// Bounds = Mesh.GetAABB();
896
897 dRadius = 0.005*Textile.GetApproximateSize();
898
899 vtkTubeFilter* pProfileTubes = vtkTubeFilter::New();
900 pProfileTubes->SetNumberOfSides(8);
901 pProfileTubes->SetInputData(pPolyData);
902 pProfileTubes->SetRadius(dRadius);
903 pProfileTubes->CappingOn();
904
905 vtkPolyDataMapper* pProfileMapper = vtkPolyDataMapper::New();
906 pProfileMapper->SetInputConnection(pProfileTubes->GetOutputPort());
907
908 vtkActor* pProfile = vtkActor::New();
909 pProfile->SetMapper(pProfileMapper);
910 ApplyColor(pProfile, GetIndexedColor(iYarn));
911
912 pPolyData->Delete();
913 pProfileTubes->Delete();
914 pProfileMapper->Delete();
915
916 PROP_YARN_INFO Info;
917 Info.iYarn = iYarn;
918 Info.TextileName = Textile.GetName();
919 m_YarnProps[pProfile] = Info;
920
921 AddProp(PROP_PATH, pProfile);
922}
923
924void CTexGenRenderer::RenderInterference(string TextileName, bool bDepth)
925{
926 if (TextileName == "")
927 {
928 map<string, CTextile*>::const_iterator itTextile;
929 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
930 {
931 RenderInterference(*itTextile->second, bDepth);
932 }
933 return;
934 }
935
936 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
937 if (!pTextile)
938 return;
939
940 RenderInterference(*pTextile, bDepth);
941}
942
944{
945 CMesh InterferingPoints;
946 vector<float> DistToSurface;
947 vector<int> YarnIndices;
948 vector<float>::iterator itDistToSurface;
949 float fMaxDist = 0.0;
950 bool TrimToDomain = Textile.GetDomain() && m_bTrimToDomain ? true : false;
951
952 Textile.DetectInterference(DistToSurface, YarnIndices, TrimToDomain, &InterferingPoints);
953
954 vtkPolyData *pPolyData = GetPolyData(InterferingPoints);
955
956 if ( bDepth )
957 {
958 // Create array containing interference depths
959 vtkFloatArray* pDistance = vtkFloatArray::New();
960 pDistance->SetNumberOfValues( DistToSurface.size() );
961
962 int i;
963
964 for ( itDistToSurface = DistToSurface.begin(), i = 0; itDistToSurface != DistToSurface.end(); ++itDistToSurface, ++i )
965 {
966 float fDist = fabs( *itDistToSurface );
967 if ( fDist > fMaxDist )
968 fMaxDist = fDist; // Get max interference to give display range
969 pDistance->SetValue( i, fDist );
970 }
971 TGLOG("Maximum intersection depth to surface " << fMaxDist << "\"");
972 // Set the scalar values of the points to the distance array - the spheres will be scaled to these values
973 pPolyData->GetPointData()->SetScalars( pDistance );
974 }
975
976// pair<XYZ, XYZ> Bounds = InterferingPoints.GetAABB();
977
978// double dRadius = 0.0025*GetLength(Bounds.first, Bounds.second);
979 const double dRadius = 0.0025*Textile.GetApproximateSize();
980
981 vtkSphereSource* pBalls = vtkSphereSource::New();
982 pBalls->SetRadius(dRadius);
983 pBalls->SetPhiResolution(10);
984 pBalls->SetThetaResolution(10);
985
986 vtkGlyph3D* pGlyphPoints = vtkGlyph3D::New();
987 pGlyphPoints->SetInputData(pPolyData);
988 pGlyphPoints->SetSourceConnection(pBalls->GetOutputPort());
989
990 if ( bDepth )
991 {
992 // Set the glyphs to be scaled to the intereference range
993 pGlyphPoints->SetScaleModeToScaleByScalar();
994 pGlyphPoints->SetColorModeToColorByScale();
995 pGlyphPoints->SetRange( 0.0, fMaxDist );
996 pGlyphPoints->ClampingOn();
997 pGlyphPoints->SetScaleFactor( 1 );
998 }
999
1000 vtkPolyDataMapper* pGlyphMapper = vtkPolyDataMapper::New();
1001 pGlyphMapper->SetInputConnection(pGlyphPoints->GetOutputPort());
1002
1003 vtkActor* pGlyph = vtkActor::New();
1004 pGlyph->SetMapper(pGlyphMapper);
1005
1006 ApplyColor(pGlyph, COLOR(1,1,1));
1007
1008 pPolyData->Delete();
1009 pBalls->Delete();
1010 pGlyphPoints->Delete();
1011 pGlyphMapper->Delete();
1012
1014}
1015
1016void CTexGenRenderer::RenderGrid(string TextileName, int iResX, int iResY, int iResZ, double dLengthModifier)
1017{
1018 if (TextileName == "")
1019 {
1020 map<string, CTextile*>::const_iterator itTextile;
1021 for (itTextile = CTexGen::GetInstance().GetTextiles().begin(); itTextile != CTexGen::GetInstance().GetTextiles().end(); ++itTextile)
1022 {
1023 RenderGrid(*itTextile->second, iResX, iResY, iResZ, dLengthModifier);
1024 }
1025 return;
1026 }
1027
1028 CTextile *pTextile = CTexGen::GetInstance().GetTextile(TextileName);
1029 if (!pTextile)
1030 return;
1031
1032 RenderGrid(*pTextile, iResX, iResY, iResZ, dLengthModifier);
1033}
1034
1035// Render a grid of points within given box domain, each point is rendered as a tangent representing the
1036// yarn tangent at that point
1037void CTexGenRenderer::RenderGrid(CTextile &Textile, int iResX, int iResY, int iResZ, double dLengthModifier)
1038{
1039 const CDomain *pDomain = Textile.GetDomain();
1040
1041 pair<XYZ, XYZ> Limits;
1042
1043 if ( pDomain ) // Use the domain
1044 {
1045 Limits = pDomain->GetMesh().GetAABB();
1046 }
1047 else // Find the limits of the yarns
1048 {
1049 vector<CYarn> Yarns = Textile.GetYarns();
1050 vector<CYarn>::iterator itYarns;
1051
1052 for ( itYarns = Yarns.begin(); itYarns != Yarns.end(); ++itYarns )
1053 {
1054 pair<XYZ, XYZ> YarnLimits = itYarns->GetAABB();
1055 Limits.first = Min( YarnLimits.first, Limits.first );
1056 Limits.second = Max( YarnLimits.second, Limits.second );
1057 }
1058 }
1059
1060 XYZ Min = Limits.first;
1061 XYZ Max = Limits.second;
1062
1063 vector<XYZ> Points;
1064 vector<POINT_INFO> PointInfo;
1065
1066 XYZ Pos;
1067 int i, j, k;
1068 for (i=0; i<iResX; ++i)
1069 {
1070 for (j=0; j<iResY; ++j)
1071 {
1072 for (k=0; k<iResZ; ++k)
1073 {
1074 Pos.x = ((double)i+0.5)/(double(iResX)) * (Max.x-Min.x) + Min.x;
1075 Pos.y = ((double)j+0.5)/(double(iResY)) * (Max.y-Min.y) + Min.y;
1076 Pos.z = ((double)k+0.5)/(double(iResZ)) * (Max.z-Min.z) + Min.z;
1077 Points.push_back(Pos);
1078 }
1079 }
1080 }
1081
1082 Textile.GetPointInformation(Points, PointInfo);
1083
1084 double dLength = 0.02*GetLength(Min, Max)*dLengthModifier;
1085
1086 vtkPoints* pPoints = vtkPoints::New();
1087 vtkFloatArray* pNormals = vtkFloatArray::New();
1088 pNormals->SetNumberOfComponents(3);
1089 for (i=0; i<(int)Points.size(); ++i)
1090 {
1091// if (PointInfo[i].iYarnIndex != -1)
1092// RenderDirection(Points[i], PointInfo[i].YarnTangent, PROP_ORIENTATION, dLength, GetIndexedColor(PointInfo[i].iYarnIndex), false);
1093// else
1094// RenderPoint(Points[i]);
1095 if (PointInfo[i].iYarnIndex != -1)
1096 {
1097 pPoints->InsertNextPoint(Points[i].x, Points[i].y, Points[i].z);
1098 //pNormals->InsertNextTuple3(PointInfo[i].YarnTangent.x, PointInfo[i].YarnTangent.y, PointInfo[i].YarnTangent.z);
1099 pNormals->InsertNextTuple3(PointInfo[i].Orientation.x, PointInfo[i].Orientation.y, PointInfo[i].Orientation.z);
1100 }
1101 }
1102 vtkPolyData* pPolyData = vtkPolyData::New();
1103 pPolyData->SetPoints(pPoints);
1104 pPolyData->GetPointData()->SetVectors(pNormals);
1105
1106 vtkArrowSource *pArrow = vtkArrowSource::New();
1107// pArrow->SetTipRadius(0.2);
1108// pArrow->SetShaftRadius(0.1);
1109// pArrow->SetTipLength(0.1);
1110// pArrow->SetTipResolution(8);
1111// pArrow->SetShaftResolution(8);
1112
1113 vtkGlyph3D* pGlyphPoints = vtkGlyph3D::New();
1114 pGlyphPoints->SetScaleFactor(dLength);
1115 pGlyphPoints->SetVectorModeToUseVector();
1116 pGlyphPoints->SetSourceConnection(pArrow->GetOutputPort());
1117 pGlyphPoints->SetInputData(pPolyData);
1118
1119 vtkPolyDataMapper* pGlyphMapper = vtkPolyDataMapper::New();
1120 pGlyphMapper->SetInputConnection(pGlyphPoints->GetOutputPort());
1121
1122 vtkActor* pGlyph = vtkActor::New();
1123 pGlyph->SetMapper(pGlyphMapper);
1124 ApplyColor(pGlyph, COLOR(1,1,1));
1125
1126 pPolyData->Delete();
1127 pArrow->Delete();
1128 pGlyphPoints->Delete();
1129 pGlyphMapper->Delete();
1130
1131 AddProp(PROP_ORIENTATION, pGlyph);
1132}
1133
1134/*bool CTexGenRenderer::RenderImage(string FileName, double dMaxDim, XYZ Orientation)
1135{
1136 vtkImageReader2* pReader = vtkImageReader2Factory::CreateImageReader2(FileName.c_str());
1137 if (!pReader)
1138 return false;
1139// vtkPNGReader* pReader = vtkPNGReader::New();
1140 pReader->SetFileName(FileName.c_str());
1141 vtkImageActor* pImageActor = vtkImageActor::New();
1142 pImageActor->SetInputData(pReader->GetOutputDataObject(());
1143 double Bounds[6];
1144 pImageActor->GetBounds(Bounds);
1145 double dMaxBound = Bounds[1] - Bounds[0];
1146 dMaxBound = max(dMaxBound, Bounds[2] - Bounds[1]);
1147 dMaxBound = max(dMaxBound, Bounds[3] - Bounds[2]);
1148 pImageActor->SetScale(dMaxDim/dMaxBound);
1149// pImageActor->RotateWXYZ(Orientation.w, Orientation.x, Orientation.y, Orientation.z);
1150 pImageActor->SetOrientation(Orientation.x, Orientation.y, Orientation.z);
1151 pReader->Delete();
1152 PROP_IMAGE_INFO Info;
1153 Info.iImageID = GetUniqueImageID();
1154 m_ImageProps[pImageActor] = Info;
1155 AddProp(PROP_IMAGE, pImageActor);
1156 return true;
1157}*/
1158
1160{
1161 vtkCamera *camera = m_pRenderer->GetActiveCamera();
1162
1163 if (!LookDirection)
1164 {
1165 XYZ Position, FocalPoint;
1166 camera->GetPosition(Position.x, Position.y, Position.z);
1167 camera->GetFocalPoint(FocalPoint.x, FocalPoint.y, FocalPoint.z);
1168 LookDirection = FocalPoint - Position;
1169 }
1170 XYZ ViewUp(0, 0, 1);
1171 if (!CrossProduct(ViewUp, LookDirection))
1172 {
1173 LookDirection = XYZ(0, 1, -0.5);
1174 }
1175 camera->SetFocalPoint(LookDirection.x, LookDirection.y, LookDirection.z);
1176 camera->SetPosition(0, 0, 0);
1177 camera->SetViewUp(ViewUp.x, ViewUp.y, ViewUp.z);
1178// camera->ComputeViewPlaneNormal();
1179
1180 m_pRenderer->ResetCamera();
1181
1182 RefreshView();
1183}
1184
1186{
1187// vtkCamera *camera = m_pRenderer->GetActiveCamera();
1188// camera->ResetCameraClippingRange();
1189 if (m_iBatchCount != 0)
1190 return;
1191
1192 m_pRenderer->Render();
1193 m_pRenderWindowInteractor->Render();
1194
1195 if (m_pCallback)
1196 m_pCallback();
1197}
1198
1200{
1201/* double Bounds[6];
1202 m_pRenderer->ComputeVisiblePropBounds(Bounds);
1203 double dRadius = sqrt((Bounds[1]-Bounds[0])*(Bounds[1]-Bounds[0]) +
1204 (Bounds[3]-Bounds[2])*(Bounds[3]-Bounds[2]) +
1205 (Bounds[5]-Bounds[4])*(Bounds[5]-Bounds[4])) /2.0;*/
1206/* vtkOrientationMarkerWidget* pOrient = vtkOrientationMarkerWidget::New();
1207 vtkAxesActor* pAxes = vtkAxesActor::New();
1208
1209 pOrient->SetOrientationMarker(pAxes);
1210 pOrient->SetInteractor(m_pRenderWindowInteractor);
1211 pOrient->SetOutlineColor(0.93, 0.57, 0.13);
1212 pOrient->SetViewport(0.0, 0.0, 0.15, 0.2);
1213 pOrient->InteractiveOff();*/
1214 m_pOrientationMarkerWidget->SetEnabled(1);
1215 m_pOrientationMarkerWidget->InteractiveOff();
1216 RefreshView();
1217
1218// pOrient->Delete();
1219// pAxes->Delete();
1220
1221// RenderDirection(XYZ(0, 0, 0), XYZ(1, 0, 0), PROP_AXES, 0.1*dRadius, COLOR_RED);
1222// RenderDirection(XYZ(0, 0, 0), XYZ(0, 1, 0), PROP_AXES, 0.1*dRadius, COLOR_GREEN);
1223// RenderDirection(XYZ(0, 0, 0), XYZ(0, 0, 1), PROP_AXES, 0.1*dRadius, COLOR_BLUE);
1224}
1225
1226vtkPolyData *CTexGenRenderer::GetPolyData(const CMesh &Mesh)
1227{
1228 int i, j;
1229
1230 // We'll create the building blocks of polydata including data attributes.
1231 vtkPolyData *pPolyData = vtkPolyData::New();
1232 vtkPoints *pPoints = vtkPoints::New();
1233 vtkCellArray *pPolys = vtkCellArray::New();
1234 vtkCellArray *pLines = vtkCellArray::New();
1235
1236 // Load the point, cell, and data attributes.
1237 vector<XYZ>::const_iterator itNode;
1238 for (itNode = Mesh.NodesBegin(), i=0; itNode != Mesh.NodesEnd(); ++itNode, ++i)
1239 {
1240 pPoints->InsertPoint(i, itNode->x, itNode->y, itNode->z);
1241 }
1242 list<int>::const_iterator itIter;
1243 int iNumNodes, iStartIndex, iEndIndex;
1244 for (j = 0; j < CMesh::NUM_ELEMENT_TYPES; ++j)
1245 {
1246 const list<int> &Indices = Mesh.GetIndices((CMesh::ELEMENT_TYPE)j);
1248 for (itIter = Indices.begin(); itIter != Indices.end(); )
1249 {
1250 if (j == CMesh::POLYLINE)
1251 {
1252 iStartIndex = *(itIter++);
1253 iEndIndex = *(itIter++);
1254 pLines->InsertNextCell(iEndIndex-iStartIndex);
1255 for (i=iStartIndex; i<iEndIndex; ++i)
1256 {
1257 pLines->InsertCellPoint(i);
1258 }
1259 }
1260 else if (j == CMesh::HEX || j == CMesh::WEDGE )
1261 {
1262 vector<int> iFirst;
1263 for ( int side = 0; side < 2; ++side )
1264 {
1265 pPolys->InsertNextCell(iNumNodes/2);
1266 for ( i = 0; i < iNumNodes/2; ++i )
1267 {
1268 if ( side == 0 )
1269 {
1270 iFirst.push_back( *itIter );
1271 }
1272 else
1273 {
1274 pLines->InsertNextCell(2);
1275 pLines->InsertCellPoint( iFirst[i] );
1276 pLines->InsertCellPoint( *itIter );
1277 }
1278 pPolys->InsertCellPoint(*itIter);
1279 ++itIter;
1280 }
1281 }
1282 }
1283 else if ( j != CMesh::POLYGON ) // Don't want to render polygons (at the moment)
1284 {
1285 pPolys->InsertNextCell(iNumNodes);
1286 for (i=0; i<iNumNodes; ++i)
1287 {
1288 pPolys->InsertCellPoint(*itIter);
1289 ++itIter;
1290 }
1291 }
1292 else
1293 {
1294 break; // If POLYGON just continue to next element type
1295 }
1296 }
1297 }
1298 // We now assign the pieces to the vtkPolyData.
1299 pPolyData->SetPoints(pPoints);
1300 pPoints->Delete();
1301 pPolyData->SetPolys(pPolys);
1302 pPolys->Delete();
1303 pPolyData->SetLines(pLines);
1304 pLines->Delete();
1305
1306 return pPolyData;
1307}
1308
1309vtkAlgorithm *CTexGenRenderer::CalculateNormals(vtkPolyData *pInput)
1310{
1311 vtkPolyDataNormals *pPolyDataNormals = vtkPolyDataNormals::New();
1312
1313 pPolyDataNormals->SetFeatureAngle(45);
1314 // The following options don't seem to operate the way they should?!
1315 pPolyDataNormals->ConsistencyOff();
1316 pPolyDataNormals->NonManifoldTraversalOn();
1317 pPolyDataNormals->SplittingOn();
1318 pPolyDataNormals->ComputePointNormalsOn();
1319 pPolyDataNormals->ComputeCellNormalsOn();
1320 pPolyDataNormals->FlipNormalsOff();
1321
1322 pPolyDataNormals->SetInputData(pInput);
1323
1324 pInput->Delete();
1325
1326 return pPolyDataNormals;
1327}
1328
1329void CTexGenRenderer::SetCallback(void (*pCallback)())
1330{
1331 m_pCallback = pCallback;
1332}
1333
1335{
1336 COLOR Color;
1337 const PROP_YARN_INFO *pYarnInfo = GetYarnPropInfo(pActor);
1338 if (pYarnInfo)
1339 {
1340 Color = GetIndexedColor(pYarnInfo->iYarn);
1341 }
1342 const PROP_NODE_INFO *pNodeInfo = GetNodePropInfo(pActor);
1343 if (pNodeInfo)
1344 {
1345 Color = GetIndexedColor(pNodeInfo->iYarn);
1346 }
1347 ApplyColor(pActor, Color);
1348}
1349
1351{
1352 PROP_YARN_INFO YarnInfo;
1353 YarnInfo.iYarn = iYarn;
1354 vector<vtkProp*> Props = GetProps(&YarnInfo, true);
1355 vector<vtkProp*>::iterator itProp;
1356 for (itProp = Props.begin(); itProp != Props.end(); ++itProp)
1357 {
1358 vtkActor* pActor = dynamic_cast<vtkActor*>(*itProp);
1359 if (pActor)
1360 ApplyColor(pActor, Color);
1361 }
1362 RefreshView();
1363}
1364
1365void CTexGenRenderer::ApplyColor(vtkActor *pActor, COLOR Color)
1366{
1367 pActor->GetProperty()->SetDiffuse(0.7);
1368 pActor->GetProperty()->SetDiffuseColor(Color.Array());
1369 pActor->GetProperty()->SetSpecular(0.3);
1370 pActor->GetProperty()->SetSpecularPower(30);
1371 pActor->GetProperty()->SetAmbient(0.3);
1372 pActor->GetProperty()->SetAmbientColor(Color.Array());
1373}
1374
1375bool CTexGenRenderer::SaveTextileToVTK(string FileName, string TextileName, int iExportFlags)
1376{
1377 CMesh Mesh;
1378
1379 vector<CTextile*> Textiles;
1380 if (TextileName == "")
1381 {
1382 map<string, CTextile*>::const_iterator itTextile;
1383 for (itTextile = TEXGEN.GetTextiles().begin(); itTextile != TEXGEN.GetTextiles().end(); ++itTextile)
1384 {
1385 Textiles.push_back(itTextile->second);
1386 }
1387 }
1388 else
1389 {
1390 CTextile *pTextile = TEXGEN.GetTextile(TextileName);
1391 if (pTextile)
1392 Textiles.push_back(pTextile);
1393 }
1394 if (Textiles.empty())
1395 return false;
1396 vector<CTextile*>::iterator itTextile;
1397 for (itTextile = Textiles.begin(); itTextile != Textiles.end(); ++itTextile)
1398 {
1399 if (iExportFlags & EXPORT_NODES)
1400 (*itTextile)->AddNodesToMesh(Mesh);
1401 if (iExportFlags & EXPORT_PATH)
1402 (*itTextile)->AddPathToMesh(Mesh);
1403 if (iExportFlags & EXPORT_SURFACE)
1404 (*itTextile)->AddSurfaceToMesh(Mesh, m_bTrimToDomain);
1405 if (iExportFlags & EXPORT_DOMAIN)
1406 {
1407 const CDomain* pDomain = (*itTextile)->GetDomain();
1408 if (pDomain)
1409 {
1410 Mesh.InsertMesh(pDomain->GetMesh());
1411 }
1412 }
1413 }
1414 return SaveMeshToVTK(FileName, Mesh);
1415}
1416
1417bool CTexGenRenderer::SaveMeshToVTK(string FileName, const CMesh &Mesh)
1418{
1419 if (FileName.size()<4 || FileName.rfind(".vtp") != FileName.size()-4)
1420 FileName += ".vtp";
1421 vtkPolyData* pPolyData = GetPolyData(Mesh);
1422 vtkXMLPolyDataWriter* pPolyDataWriter = vtkXMLPolyDataWriter::New();
1423 pPolyDataWriter->SetInputData(pPolyData);
1424 pPolyDataWriter->SetDataModeToBinary();
1425 pPolyDataWriter->SetFileName(FileName.c_str());
1426 bool bSuccess = pPolyDataWriter->Write()?true:false;
1427
1428 pPolyData->Delete();
1429 pPolyDataWriter->Delete();
1430
1431 return bSuccess;
1432}
1433
1435{
1436 ++m_iBatchCount;
1437}
1438
1440{
1441 --m_iBatchCount;
1442 if (m_iBatchCount == 0)
1443 RefreshView();
1444}
1445
1447{
1448 map<vtkProp*, PROP_IMAGE_INFO>::iterator itImage;
1449 int iPrevID = 0, iID = 0;
1450 do
1451 {
1452 iPrevID = iID;
1453 for (itImage = m_ImageProps.begin(); itImage != m_ImageProps.end(); ++itImage)
1454 {
1455 if (iID == itImage->second.iImageID)
1456 {
1457 ++iID;
1458 }
1459 }
1460 } while (iPrevID != iID);
1461 return iID;
1462}
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
#define TGLOGINDENT(MESSAGE)
Combines the TGLOG macro and TGLOGAUTOINDENT macro in one.
Definition: Logger.h:68
#define TGLOG(MESSAGE)
Definition: Logger.h:36
#define NULL
Definition: ShinyConfig.h:50
#define TEXGEN
Helper macro to get the texgen instance.
Definition: TexGen.h:76
static CCustomInteractorStyle * New()
Abstract base class representing the domain in which a textile cell may lie.
Definition: Domain.h:34
virtual void Grow(double dDistance)=0
Make the domain larger (used mainly for rendering purposes)
const CMesh & GetMesh() const
Get the mesh representing the domain as a surface mesh.
Definition: Domain.h:73
virtual CDomain * Copy() const =0
Defines the nodes and elements of a surface or volume mesh.
Definition: Mesh.h:58
int GetNumNodes() const
Return the number of nodes.
Definition: Mesh.cpp:2646
void InsertMesh(const CMesh &Mesh, XYZ Offset=XYZ(0, 0, 0))
Add the contents of Mesh to this mesh.
Definition: Mesh.cpp:93
const list< int > & GetIndices(ELEMENT_TYPE ElemType) const
Get the element indices of a given element type.
Definition: Mesh.cpp:2671
ELEMENT_TYPE
Each element type is represented by a unique integer value.
Definition: Mesh.h:66
@ NUM_ELEMENT_TYPES
Definition: Mesh.h:77
@ POLYLINE
Definition: Mesh.h:74
@ POLYGON
Definition: Mesh.h:76
pair< XYZ, XYZ > GetAABB(double dGrowDistance=0) const
Get an axis aligned bounding box for the mesh.
Definition: Mesh.cpp:340
vector< XYZ >::const_iterator NodesBegin() const
Definition: Mesh.cpp:2604
const bool NodesEmpty() const
Returns true if the nodes array is empty.
Definition: Mesh.cpp:2651
vector< XYZ >::const_iterator NodesEnd() const
Definition: Mesh.cpp:2609
static CTexGen & GetInstance()
Definition: Singleton.h:40
CTextile * GetTextile(string TextileName="")
Get a textile with given name.
Definition: TexGen.cpp:59
const map< string, CTextile * > & GetTextiles() const
Definition: TexGen.h:155
void UpdateAxesColor()
Updates the axes color based on the background color.
void RefreshView()
Re-render the scene to take into account updates to it.
void TakeScreenShot(string FileName, int iMagnification=1)
Saves the current view as a PNG image on the hard disk.
void SetTrimToDomain(bool bTrim)
Render yarns as transparent.
vector< vtkProp * > GetProps(PROP_TYPE Type)
Get the vtkProps of a given type.
map< vtkProp *, PROP_YARN_INFO > m_YarnProps
void RenderDomainAxes(string TextileName="")
Render the dimensions of the domain.
void RenderPaths(string TextileName="")
Render the paths of each yarn in a textile.
void RenderAxes()
Render axes at the bottom left of the window.
void RenderPath(CTextile &Textile, int iYarn)
Render the path of a yarn in a textile.
void SetYarnColor(int iYarn, COLOR Color)
Set the colors of the yarns.
int GetNumProps(PROP_TYPE Type) const
Find out how many actors of given type exist.
vtkProp * RenderYarnMesh(CYarn &Yarn, const CDomain *pDomain=NULL, COLOR Color=COLOR(1, 1, 1))
Render a single yarn mesh with given color.
vtkPolyData * GetPolyData(const CMesh &Mesh)
vtkProp * RenderYarn(CYarn &Yarn, const CDomain *pDomain=NULL, COLOR Color=COLOR(1, 1, 1), double dOpacity=1)
Render a single yarn with given color.
int GetUniqueImageID()
Return a unique ID assigned to an image.
map< vtkProp *, PROP_IMAGE_INFO > m_ImageProps
const PROP_NODE_INFO * GetNodePropInfo(vtkProp *pProp) const
Get information about the node prop.
void RefreshYarn(PROP_YARN_INFO YarnInfo)
Re-render the yarn after it has been updated.
multimap< PROP_TYPE, vtkProp * > m_Props
This function will render a direction at a given point.
void SetXRay(bool bXRay)
Render yarns as transparent.
void SetPropsColor(PROP_TYPE Type, COLOR Color)
Remove all actors of given type.
void SetCallback(void(*pCallback)())
Set the callback function when an actor is added or deleted.
void AddProp(PROP_TYPE Type, vtkProp *pProp)
Add an actor to the scene.
void RenderGrid(string TextileName="", int iResX=20, int iResY=20, int iResZ=20, double dLengthModifier=1)
vtkAlgorithm * CalculateNormals(vtkPolyData *pInput)
void RefreshTextile(string TextileName)
Re-render the textile after it has been updated.
vector< vtkProp * > GetNodeProps(PROP_YARN_INFO Info, bool bIgnoreTextileName=false)
Get the vtkProps associated with the given object.
void RenderInterference(string TextileName="", bool bDepth=false)
void ClearScene()
Remove all objects being rendered.
bool SaveTextileToVTK(string FileName, string TextileName="", int iExportFlags=EXPORT_NODES|EXPORT_PATH|EXPORT_SURFACE|EXPORT_DOMAIN)
Save textile data to VTK file format.
void EndBatch()
Decrement batch count.
void RenderNodes(string TextileName="")
Render all the master nodes of each yarn in a textile.
void RenderMesh(string TextileName="")
Create the volume mesh and add it to the scene to be rendered.
bool GetParallelProjection() const
Determine if parallel projection or perspective projection is switched on.
map< vtkProp *, PROP_NODE_INFO > m_NodeProps
vtkActor * ConvertToActor(vtkAlgorithm *pAlgorithm)
This function will convert a vtkAlgorithm class into an vtkActor for rendering.
void RemoveProps(PROP_TYPE Type)
Remove all actors of given type.
vtkRenderWindowInteractor * m_pRenderWindowInteractor
vtkOrientationMarkerWidget * m_pOrientationMarkerWidget
void SetParallelProjection(bool bParallelProjection)
Switch between parallel projection and perspective projection.
void BeginBatch()
Increment batch count.
void Start(bool bTakeControl=true, int iWidth=800, int iHeight=600, bool bFullScreen=false)
Create a new render window and render to it (optionally taking control of the thread)
void RenderTextile(string TextileName="", double dOpacity=1)
Create the mesh and add it to the scene to be rendered.
void ApplyDefaultColor(vtkActor *pActor)
Apply the default material color based on the yarn index.
const PROP_IMAGE_INFO * GetImagePropInfo(vtkProp *pProp) const
Get information about the image prop.
void RemoveProp(vtkProp *pProp)
static void ApplyColor(vtkActor *pActor, COLOR Color)
Apply the material properties.
void SetBackgroundColor(COLOR Color)
Render an image.
bool SaveMeshToVTK(string FileName, const CMesh &Mesh)
Save a Mesh to VTK file format.
COLOR GetBestAnnotationColor()
Gets the best text color based on the color of the background.
const PROP_YARN_INFO * GetYarnPropInfo(vtkProp *pProp) const
Get information about the surface prop.
void RenderDomain(string TextileName="", COLOR Color=COLOR(1, 1, 1), double dOpacity=0.5)
Render the domain.
void ResetCamera(XYZ LookDirection=XYZ())
Reset the camera so as to see all objects that are rendered.
vtkRenderWindow * m_pRenderWindow
Represents a textile cell containing yarns.
Definition: Textile.h:39
const CDomain * GetDomain() const
Definition: Textile.h:287
string GetName() const
Get the name associated with this textile.
Definition: Textile.cpp:355
double GetApproximateSize()
Get an approximate size for the textile.
Definition: Textile.cpp:556
void GetPointInformation(const vector< XYZ > &Points, vector< POINT_INFO > &PointsInfo, double dTolerance=1e-9)
Get useful information of a list of points.
Definition: Textile.cpp:410
const vector< CYarn > & GetYarns() const
Definition: Textile.cpp:676
int DetectInterference(vector< float > &DistanceToSurface, vector< int > &YarnIndex, bool bTrimToDomain, CMesh *pInterferingPoints=NULL)
Find out if any of the yarns are interfering with each other.
Definition: Textile.cpp:577
Represents a yarn consisting of master nodes, section and interpolation function.
Definition: Yarn.h:49
bool AddSurfaceToMesh(CMesh &Mesh, bool bAddEndCaps=true) const
Create surface mesh for this yarn and add it to the surface mesh object.
Definition: Yarn.cpp:860
bool AddVolumeToMesh(CMesh &Mesh) const
Create volume mesh for this yarn and add it to the volume mesh object.
Definition: Yarn.cpp:1010
bool AddPathToMesh(CMesh &Mesh) const
Add yarn centerline path to mesh.
Definition: Yarn.cpp:813
const vector< CNode > & GetMasterNodes() const
Definition: Yarn.h:447
Namespace containing a series of customised math operations not found in the standard c++ library.
COLOR GetIndexedColor(int iIndex)
Definition: Misc.cpp:28
double Max(XYZ &Vector)
Get maximum element of vector and return it.
Definition: mymath.h:642
double GetLength(const XYZ &Point1, const XYZ &Point2)
Get the length between two points.
Definition: mymath.h:540
XYZ Min(const XYZ &P1, const XYZ &P2)
Given two points, return a new point who's coordinates are the smaller of the two.
Definition: mymath.h:1142
XYZ CrossProduct(const XYZ &left, const XYZ &right)
Get the cross product of two vectors.
Definition: mymath.h:524
double * Array()
Definition: Misc.h:101
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