Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
NetworkLinkActor.cpp
Go to the documentation of this file.
1/* This file is part of MODEL, the Mechanics Of Defect Evolution Library.
2 *
3 * Copyright (C) 2011 by Giacomo Po <gpo@ucla.edu>.
4 *
5 * model is distributed without any warranty under the
6 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
7 */
8
9#ifndef model_NetworkLinkActor_cpp_
10#define model_NetworkLinkActor_cpp_
11
12#include <DislocationNetwork.h>
13#include <numbers>
14#include <map>
15#include <iostream>
16#include <deque>
17#include <string>
18
19#include <vtkVersion.h>
20#include <vtkSmartPointer.h>
21#include <vtkPolyData.h>
22#include <vtkPolyDataMapper.h>
23#include <vtkActor.h>
24#include <vtkMath.h>
25#include <vtkProperty.h>
26#include <vtkTubeFilter.h>
27#include <vtkPolyLine.h>
28#include <vtkSphereSource.h>
29#include <vtkArrowSource.h>
30#include <vtkGlyph3D.h>
31#include <vtkDoubleArray.h>
32#include <vtkPointData.h>
33#include <vtkLabeledDataMapper.h>
34#include <vtkFloatArray.h>
35#include <vtkTextProperty.h>
36#include <vtkActor2D.h>
37#include <vtkProperty2D.h>
38#include <vtkRenderer.h>
39#include <vtkLine.h>
40#include <vtkCellData.h>
41
42//#include <IDreader.h>
44#include <MeshPlane.h>
45#include <NetworkLinkActor.h>
46#include <Vector2Color.h>
47
48#include <DDqtControls.h>
49
50namespace model
51{
52
53 NetworkLinkActor::NetworkLinkActor(vtkGenericOpenGLRenderWindow* const renWin,vtkRenderer* const renderer,const DefectiveCrystal<3>& defectiveCrystal_in) :
54 /* init */ renderWindow(renWin)
55 /* init */,mainLayout(new QGridLayout(this))
56 /* init */,showLinks(new QCheckBox(this))
57 /* init */,sliderLinksRadius(new QSlider(this))
58 /* init */,sliderNormalOpacity(new QSlider(Qt::Horizontal,this))
59 /* init */,sliderZeroOpacity(new QSlider(Qt::Horizontal,this))
60 /* init */,sliderBoundaryOpacity(new QSlider(Qt::Horizontal,this))
61 /* init */,linksColorBox(new QComboBox(this))
62 /* init */,clr(ColorScheme::colorBurgers)
63 /* init */,polyData(vtkSmartPointer<vtkPolyData>::New())
64 /* init */,polyDataBnd(vtkSmartPointer<vtkPolyData>::New())
65 /* init */,polyData0(vtkSmartPointer<vtkPolyData>::New())
66 /* init */,tubeFilter(vtkSmartPointer<vtkTubeFilter>::New())
67 /* init */,tubeFilterBnd(vtkSmartPointer<vtkTubeFilter>::New())
68 /* init */,tubeFilter0(vtkSmartPointer<vtkTubeFilter>::New())
69 /* init */,tubeMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
70 /* init */,tubeActor(vtkSmartPointer<vtkActor>::New())
71 /* init */,tubeMapperBnd(vtkSmartPointer<vtkPolyDataMapper>::New())
72 /* init */,tubeActorBnd(vtkSmartPointer<vtkActor>::New())
73 /* init */,tubeMapper0(vtkSmartPointer<vtkPolyDataMapper>::New())
74 /* init */,tubeActor0(vtkSmartPointer<vtkActor>::New())
75 /* init */,defectiveCrystal(defectiveCrystal_in)
76 /* init */,dislocationNetwork(defectiveCrystal.template getUniqueTypedMicrostructure<DislocationNetwork<3>>())
77 {
78 showLinks->setObjectName("showSegments");
79 showLinks->setChecked(true);
80 showLinks->setText("links");
81 sliderLinksRadius->setEnabled(true);
82 sliderLinksRadius->setMinimum(0);
83 sliderLinksRadius->setMaximum(30);
84 sliderLinksRadius->setValue(5);
85 sliderLinksRadius->setOrientation(Qt::Horizontal);
86
87 sliderNormalOpacity->setObjectName("normalSegmentOpacity");
88 sliderNormalOpacity->setRange(0,100);
89 sliderNormalOpacity->setValue(100);
90 sliderZeroOpacity->setObjectName("zeroBurgersOpacity");
91 sliderBoundaryOpacity->setObjectName("boundarySegmentOpacity");
92 for(auto* slider : {sliderZeroOpacity,sliderBoundaryOpacity})
93 {
94 slider->setRange(0,100);
95 slider->setValue(0);
96 }
97 tubeActor0->SetVisibility(false);
98 tubeActorBnd->SetVisibility(false);
99
100 linksColorBox->addItem("Burgers vector");
101 linksColorBox->addItem("plane normal");
102 linksColorBox->addItem("glissile/sessile");
103 linksColorBox->addItem("edge/screw");
104 linksColorBox->addItem("slip system");
105
106 auto *segmentsBox = controls::box("Segments", this, "Show or hide dislocation segments.", showLinks);
107 controls::field(controls::grid(segmentsBox), 0, "Radius", sliderLinksRadius,
108 "Tube radius in simulation length units b. Changes apply immediately.");
110 controls::grid(segmentsBox), 1, "Coloring", linksColorBox,
111 "Choose which dislocation property determines segment color. Slip system uses the SlipSystems palette.");
112 controls::field(controls::grid(segmentsBox), 2, "Normal opacity", sliderNormalOpacity,
113 "Opacity of nonzero-Burgers segments away from external and grain boundaries. 0 is transparent; 100 is opaque.");
114 controls::field(controls::grid(segmentsBox), 3, "Zero-Burgers opacity", sliderZeroOpacity,
115 "Opacity of segments with zero net Burgers vector, including those on boundaries. 0 is transparent; 100 is opaque.");
116 controls::field(controls::grid(segmentsBox), 4, "Boundary/GB opacity", sliderBoundaryOpacity,
117 "Opacity of nonzero-Burgers segments on external boundaries or grain boundaries, including periodic grain boundaries. 0 is transparent; 100 is opaque.");
118 mainLayout->addWidget(segmentsBox, 0, 0);
119 mainLayout->setRowStretch(1, 1);
120 this->setLayout(mainLayout);
121
122 connect(showLinks,SIGNAL(stateChanged(int)), this, SLOT(modify()));
123 connect(sliderNormalOpacity,SIGNAL(valueChanged(int)), this, SLOT(modify()));
124 connect(sliderZeroOpacity,SIGNAL(valueChanged(int)), this, SLOT(modify()));
125 connect(sliderBoundaryOpacity,SIGNAL(valueChanged(int)), this, SLOT(modify()));
126 connect(sliderLinksRadius,SIGNAL(valueChanged(int)), this, SLOT(modify()));
127
128 tubeFilter->SetInputData(polyData);
129 tubeFilter->SetRadius(5.0); // this must be a function similar to setColor
130 tubeFilter->SetNumberOfSides(10);
131 tubeFilter->Update();
132 tubeMapper->SetInputConnection(tubeFilter->GetOutputPort());
133 tubeMapper->ScalarVisibilityOn();
134 tubeMapper->SetScalarModeToUseCellFieldData();
135 tubeMapper->SelectColorArray("Colors");
136 tubeActor->SetMapper(tubeMapper);
137
138 // Boundary segments
139 tubeFilterBnd->SetInputData(polyDataBnd);
140 tubeFilterBnd->SetRadius(5.0); // this must be a function similar to setColor
141 tubeFilterBnd->SetNumberOfSides(10);
142 tubeFilterBnd->Update();
143 tubeMapperBnd->SetInputConnection(tubeFilterBnd->GetOutputPort());
144 tubeMapperBnd->ScalarVisibilityOn();
145 tubeActorBnd->SetMapper(tubeMapperBnd);
146 tubeActorBnd->GetProperty()->SetOpacity(0.0); //(R,G,B)
147
148 // Zero-Burgers Segments
149 tubeFilter0->SetInputData(polyData0);
150 tubeFilter0->SetRadius(5.0); // this must be a function similar to setColor
151 tubeFilter0->SetNumberOfSides(10);
152 tubeFilter0->Update();
153 tubeMapper0->SetInputConnection(tubeFilter0->GetOutputPort());
154 tubeMapper0->ScalarVisibilityOn();
155 tubeActor0->SetMapper(tubeMapper0);
156 tubeActor0->GetProperty()->SetColor(0.5, 0.5, 0.5); //(R,G,B)
157 tubeActor0->GetProperty()->SetOpacity(0.0); //(R,G,B)
158
159 renderer->AddActor(tubeActor);
160 renderer->AddActor(tubeActorBnd);
161 renderer->AddActor(tubeActor0);
162 }
163
164 void NetworkLinkActor::updateConfiguration(vtkPolyData* const nodePolyData,const SlipSystemTab::SlipSystemColorMapType& sscm )
165 {// https://stackoverflow.com/questions/6878263/remove-individual-points-from-vtkpoints
166 std::cout<<"Updating links..."<<std::flush;
167 const auto t0= std::chrono::system_clock::now();
169 {
170 vtkSmartPointer<vtkFloatArray> radii(vtkSmartPointer<vtkFloatArray>::New());
171 vtkSmartPointer<vtkUnsignedCharArray> colors(vtkSmartPointer<vtkUnsignedCharArray>::New());
172 vtkSmartPointer<vtkUnsignedCharArray> colorsBnd(vtkSmartPointer<vtkUnsignedCharArray>::New());
173 radii->SetName("TubeRadius");
174 colors->SetName("Colors");
175 colorsBnd->SetNumberOfComponents(3);
176 colors->SetNumberOfComponents(3);
177 vtkSmartPointer<vtkCellArray> cells(vtkSmartPointer<vtkCellArray>::New());
178 vtkSmartPointer<vtkCellArray> cellsBnd(vtkSmartPointer<vtkCellArray>::New());
179 vtkSmartPointer<vtkCellArray> cells0(vtkSmartPointer<vtkCellArray>::New());
180
181 // Match the network-node point ordering, rebuilding for every frame.
182 std::map<size_t,vtkIdType> nodeIndices;
183 for(const auto& entry : dislocationNetwork->networkNodes())
184 {
185 nodeIndices.emplace(entry.first,static_cast<vtkIdType>(nodeIndices.size()));
186 }
187
188 for (const auto& link : dislocationNetwork->networkLinks())
189 {
190
191
192
193 vtkSmartPointer<vtkLine> line(vtkSmartPointer<vtkLine>::New());
194 line->GetPointIds()->SetId(0, nodeIndices.at(link.second.lock()->source->sID)); // the second 0 is the index of the Origin in linesPolyData's points
195 line->GetPointIds()->SetId(1, nodeIndices.at(link.second.lock()->sink->sID));
196
197 if(link.second.lock()->hasZeroBurgers())
198 {
199 cells0->InsertNextCell(line);
200 }
201 else
202 {
203 Eigen::Matrix<int,3,1> colorVector=computeColor(link.second.lock()->burgers(),link.second.lock()->chord(),link.second.lock()->slipSystem(),sscm);
204 unsigned char lineClr[3]={(unsigned char) colorVector(0),(unsigned char) colorVector(1),(unsigned char) colorVector(2)};
205
206 if(link.second.lock()->isGrainBoundarySegment() || link.second.lock()->isBoundarySegment())
207 {
208 cellsBnd->InsertNextCell(line);
209 colorsBnd->InsertNextTypedTuple(lineClr);
210 }
211 else
212 {
213 cells->InsertNextCell(line);
214 colors->InsertNextTypedTuple(lineClr);
215 radii->InsertNextValue(link.second.lock()->burgers().norm()*sliderLinksRadius->value());
216 }
217
218
219// if(link.second.meshLocation!=0)
220// {// 0=MeshLocation::insideMesh
221// cellsBnd->InsertNextCell(line);
222// // polyDataBnd->InsertNextCell(VTK_LINE,2,connectivity); //Connects the first and fourth point we inserted into a line
223// colorsBnd->InsertNextTypedTuple(lineClr);
224// }
225// else
226// {// internal segment
227// // polyData->InsertNextCell(VTK_LINE,2,connectivity); //Connects the first and fourth point we inserted into a line
228// cells->InsertNextCell(line);
229// if(link.second.meshLocation==2 /*&& blackGrainBoundarySegments*/)
230// {
231// unsigned char lineClr1[3]={1,1,1};
232// colors->InsertNextTypedTuple(lineClr1);
233// }
234// else
235// {
236// colors->InsertNextTypedTuple(lineClr);
237// }
238//
239// radii->InsertNextValue(burgersNorm*sliderLinksRadius->value());
240// }
241
242 }
243
244
245// auto itSource(configFields.configIO.nodeMap().find(link.second.sourceID)); //source
246// if(itSource!=configFields.configIO.nodeMap().end())
247// {
248// auto itSink(configFields.configIO.nodeMap().find(link.second.sinkID)); //sink
249// if(itSink!=configFields.configIO.nodeMap().end())
250// {
251// vtkSmartPointer<vtkLine> line(vtkSmartPointer<vtkLine>::New());
252// line->GetPointIds()->SetId(0, std::distance(configFields.configIO.nodeMap().begin(),itSource)); // the second 0 is the index of the Origin in linesPolyData's points
253// line->GetPointIds()->SetId(1, std::distance(configFields.configIO.nodeMap().begin(),itSink));
254//
255// const auto chord(configFields.configIO.nodes()[itSink->second].P-configFields.configIO.nodes()[itSource->second].P);
256// const double burgersNorm(link.second.b.norm());
257// if(burgersNorm>FLT_EPSILON)
258// {
259// Eigen::Matrix<int,3,1> colorVector=computeColor(link.second.b,chord,link.second.n);
260// unsigned char lineClr[3]={(unsigned char) colorVector(0),(unsigned char) colorVector(1),(unsigned char) colorVector(2)};
261//
262// if(link.second.meshLocation!=0)
263// {// 0=MeshLocation::insideMesh
264// cellsBnd->InsertNextCell(line);
265// // polyDataBnd->InsertNextCell(VTK_LINE,2,connectivity); //Connects the first and fourth point we inserted into a line
266// colorsBnd->InsertNextTypedTuple(lineClr);
267// }
268// else
269// {
270// // polyData->InsertNextCell(VTK_LINE,2,connectivity); //Connects the first and fourth point we inserted into a line
271// cells->InsertNextCell(line);
272// if(link.second.meshLocation==2 /*&& blackGrainBoundarySegments*/)
273// {
274// unsigned char lineClr1[3]={1,1,1};
275// colors->InsertNextTypedTuple(lineClr1);
276// }
277// else
278// {
279// colors->InsertNextTypedTuple(lineClr);
280// }
281//
282// radii->InsertNextValue(burgersNorm*sliderLinksRadius->value());
283// }
284// }
285// else
286// {
287// cells0->InsertNextCell(line);
288// // polyData0->InsertNextCell(VTK_LINE,2,connectivity); //Connects the first and fourth point we inserted into a line
289// }
290// }
291// else
292// {
293// throw std::runtime_error("SINK VERTEX NOT FOUND IN nodeMap");
294// }
295// }
296// else
297// {
298// throw std::runtime_error("SOURCE VERTEX NOT FOUND IN nodeMap");
299// }
300 }
301
302 polyData->SetPoints(nodePolyData->GetPoints());
303 polyData->SetLines(cells);
304 polyData->GetCellData()->AddArray(colors);
305 polyData->GetPointData()->AddArray(radii);
306 polyData->GetPointData()->SetActiveScalars("TubeRadius");
307 polyData->Modified();
308
309 polyDataBnd->SetPoints(nodePolyData->GetPoints());
310 polyDataBnd->SetLines(cellsBnd);
311 polyDataBnd->GetCellData()->SetScalars(colorsBnd);
312 polyDataBnd->Modified();
313
314 polyData0->SetPoints(nodePolyData->GetPoints());
315 polyData0->SetLines(cells0);
316 polyData0->Modified();
317 }
318 std::cout<<magentaColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<defaultColor<<std::endl;
319 }
320
321 /**********************************************************************/
322 void NetworkLinkActor::modify()
323 {
324 sliderLinksRadius->setEnabled(showLinks->isChecked());
325 tubeActor->SetVisibility(showLinks->isChecked() && sliderNormalOpacity->value()>0);
326 tubeActor->GetProperty()->SetOpacity(sliderNormalOpacity->value()/100.0);
327 tubeActorBnd->SetVisibility(showLinks->isChecked() && sliderBoundaryOpacity->value()>0);
328 tubeActorBnd->GetProperty()->SetOpacity(sliderBoundaryOpacity->value()/100.0);
329 tubeActor0->GetProperty()->SetOpacity(sliderZeroOpacity->value()/100.0);
330 linksColorBox->setEnabled(showLinks->isChecked());
331 tubeActor0->SetVisibility(showLinks->isChecked() && sliderZeroOpacity->value()>0);
332 tubeFilter->SetRadius(sliderLinksRadius->value()); // this must be a function similar to setColor
333 tubeFilterBnd->SetRadius(sliderLinksRadius->value()); // this must be a function similar to setColor
334 tubeFilter0->SetRadius(sliderLinksRadius->value()); // this must be a function similar to setColor
335 if(renderWindow->GetReadyForRendering())
336 {
337 renderWindow->Render();
338 }
339 }
340
341// Eigen::Matrix<int,3,1> NetworkLinkActor::vector2Clr(VectorDim clrVector) const
342// {
343// float clrTol=100.0*FLT_EPSILON;
344// if(clrVector(0)<-clrTol)
345// {// first component not zero but begative, flip color
346// clrVector*=-1.0;
347// }
348// else if(fabs(clrVector(0))<=clrTol)
349// {// first component is zero, use second component
350// if(clrVector(1)<-clrTol)
351// {// second component not zero but begative, flip color
352// clrVector*=-1.0;
353// }
354// else if(fabs(clrVector(1))<=clrTol)
355// {// second component is zero, use third component
356// if(clrVector(2)<-clrTol)
357// {
358// clrVector*=-1.0;
359// }
360// }
361// }
362//
363// clrVector = (clrVector + VectorDim::Ones(dim) * clrVector.norm()).eval();
364// clrVector.normalize();
365// return (clrVector*255).cast<int>();
366// }
367
368 /*********************************************************************/
369 Eigen::Matrix<int,3,1> NetworkLinkActor::computeColor(const VectorDim& burgers, const VectorDim& chord, const std::shared_ptr<SlipSystem>& slipSystem,const SlipSystemTab::SlipSystemColorMapType& sscm) const
370 {
371
372 VectorDim clrVector(VectorDim::Zero());
373
374
375
376 switch (linksColorBox->currentIndex())
377 {
378
379 default:
380 {
381 clrVector = burgers.normalized();
382 // flipColor(colorVector);
383 break;
384 }
385
386 case 1:
387 {
388 if(slipSystem)
389 {
390 clrVector=slipSystem->unitNormal;
391 }
392 break;
393 }
394
395 case 2:
396 {
397// const bool isSessile= planeNormal.squaredNorm()<FLT_EPSILON || fabs(burgers.dot(planeNormal))>FLT_EPSILON;
398// const bool isSessile((slipSystem));
399 clrVector(0)= slipSystem? 1.0 : 0.1;
400 clrVector(1)= slipSystem? 0.5 : 0.4;
401 clrVector(2)= slipSystem? 0.0 : 0.9;
402 break;
403 }
404
405 case 3:
406 {
407 const float u = acos(std::fabs(chord.normalized().dot(burgers.normalized())))*2.0/std::numbers::pi;
408 // RGBcolor rgb(RGBmap::getColor(std::fabs(tubeTangents.col(k).normalized().dot(burgers.normalized())),0,1));
409 // colorVector << rgb.r, rgb.g, rgb.b;
410// clrVector=(VectorDim()<<1.0,0.647,0.0).finished()*u+VectorDim::UnitZ()*(1.0-u);
411 clrVector=VectorDim::UnitX()*u+VectorDim::UnitZ()*(1.0-u);
412 break;
413 }
414
415 case 4:
416 {
417 clrVector=VectorDim::Zero();
418
419 if(slipSystem)
420 {
421 const auto ssIter(sscm.find(slipSystem.get()));
422 if(ssIter!=sscm.end())
423 {
424 clrVector=ssIter->second->rgb().template cast<double>()/255.0;
425 }
426 }
427 break;
428 }
429 // break;
430
431 }
432
433 return Vector2Color::v2c(clrVector);
434 }
435
436
437} // namespace model
438#endif
QGridLayout * grid(QGroupBox *group)
QGroupBox * box(const QString &title, QWidget *parent, const QString &description, QCheckBox *toggle=nullptr)
void field(QGridLayout *layout, int row, const QString &title, QWidget *input, const QString &description)
size_t InstanceCount< Derived >::count
static std::string magentaColor
static std::string defaultColor
std::map< const SlipSystem *, SlipSystemButton * > SlipSystemColorMapType
static Eigen::Matrix< int, 3, 1 > v2c(Eigen::Matrix< double, 3, 1 > clrVector)
REAL t0
REAL u[4]