Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
NetworkLoopActor.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_NetworkLoopActor_cpp_
10#define model_NetworkLoopActor_cpp_
11
12#include <DislocationNetwork.h>
13#include <iostream>
14#include <map>
15#include <deque>
16#include <string>
17
18#include <vtkVersion.h>
19#include <vtkSmartPointer.h>
20#include <vtkPolyData.h>
21#include <vtkPolyDataMapper.h>
22#include <vtkActor.h>
23#include <vtkMath.h>
24#include <vtkProperty.h>
25#include <vtkTubeFilter.h>
26#include <vtkPolyLine.h>
27#include <vtkSphereSource.h>
28#include <vtkArrowSource.h>
29#include <vtkGlyph3D.h>
30#include <vtkDoubleArray.h>
31#include <vtkPointData.h>
32#include <vtkLabeledDataMapper.h>
33#include <vtkFloatArray.h>
34#include <vtkTextProperty.h>
35#include <vtkActor2D.h>
36#include <vtkProperty2D.h>
37#include <vtkRenderer.h>
38#include <vtkLine.h>
39#include <vtkCellData.h>
40#include <vtkPolygon.h>
41#include <vtkCellArray.h>
42#include <vtkTriangle.h>
43#include <vtkUnsignedCharArray.h>
44#include <QLabel>
45
47#include <MeshPlane.h>
48#include <NetworkLoopActor.h>
51
52#include <DDqtControls.h>
53
54namespace model
55{
56
57
58/**********************************************************************/
59NetworkLoopActor::NetworkLoopActor(vtkGenericOpenGLRenderWindow* const renWin,vtkRenderer* const renderer,
60 const DefectiveCrystal<3>& defectiveCrystal_in) :
61/* init */ renderWindow(renWin)
62/* init */,mainLayout(new QGridLayout(this))
63/* init */,showLoops(new QCheckBox(this))
64/* init */,colorScheme(new QComboBox(this))
65/* init */,manualColorButton(new QPushButton("Choose color…", this))
66/* init */,slippedAreaBox(new controls::GroupBox(tr("&Slipped Area")))
67/* init */,sliderSlippedArea(new QSlider(this))
68/* init */,meshAreaBox(new controls::GroupBox(tr("&Slipped Mesh")))
69/* init */,nodePolyData(vtkSmartPointer<vtkPolyData>::New())
70/* init */,nodeGlyphs(vtkSmartPointer<vtkGlyph3D>::New())
71/* init */,nodeMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
72/* init */,nodeActor(vtkSmartPointer<vtkActor>::New())
73/* init */,labelPolyData(vtkSmartPointer<vtkPolyData>::New())
74/* init */,labelMapper(vtkSmartPointer<vtkLabeledDataMapper>::New())
75/* init */,labelActor(vtkSmartPointer<vtkActor2D>::New())
76/* init */,loopPolyData(vtkSmartPointer<vtkPolyData>::New())
77/* init */,loopMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
78/* init */,loopActor(vtkSmartPointer<vtkActor>::New())
79/* init */,areaPolyData(vtkSmartPointer<vtkPolyData>::New())
80/* init */,areaMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
81/* init */,areaActor(vtkSmartPointer<vtkActor>::New())
82/* init */,meshPolydata(vtkSmartPointer<vtkPolyData>::New())
83/* init */,meshMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
84/* init */,meshActor(vtkSmartPointer<vtkActor>::New())
85/* init */,globalMeshSizeEdit(new QLineEdit("100000000"))
86/* init */,localMeshSizeEdit(new QLineEdit("1.0"))
87/* init */,defectiveCrystal(defectiveCrystal_in)
88/* init */,dislocationNetwork(defectiveCrystal.template getUniqueTypedMicrostructure<DislocationNetwork<3>>())
89{
90
91 nodeGlyphs->SetInputData(nodePolyData);
92 nodeGlyphs->SetSourceConnection(vtkSmartPointer<vtkSphereSource>::New()->GetOutputPort());
93 nodeGlyphs->ScalingOn();
94 nodeGlyphs->SetScaleModeToScaleByVector();
95 nodeGlyphs->SetScaleFactor(10);
96 nodeGlyphs->SetColorModeToColorByScalar();
97 nodeGlyphs->Update();
98 nodeMapper->SetInputConnection(nodeGlyphs->GetOutputPort());
99 nodeActor->SetMapper(nodeMapper);
100 nodeActor->SetVisibility(false);
101
102 // Labels
103 labelMapper->SetInputData(labelPolyData);
104 labelMapper->SetLabelModeToLabelScalars();
105 labelMapper->SetLabelFormat("%1.0f");
106 labelMapper->GetLabelTextProperty()->SetFontSize(20);
107 labelActor->SetMapper(labelMapper);
108 labelActor->GetProperty()->SetColor(0.0, 0.0, 0.0); //(R,G,B)
109 labelActor->SetVisibility(false);
110
111
112 showLoops->setChecked(false);
113 showLoops->setText("Loops");
114
115 slippedAreaBox->setCheckable(true);
116 slippedAreaBox->setChecked(false);
117
118 meshAreaBox->setCheckable(true);
119 meshAreaBox->setChecked(false);
120
121
122 // showSlippedArea->setChecked(false);
123 // showSlippedArea->setText("SlippedArea");
124 // sliderSlippedArea->setEnabled(false);
125 sliderSlippedArea->setMinimum(0);
126 sliderSlippedArea->setMaximum(10);
127 sliderSlippedArea->setValue(5);
128 sliderSlippedArea->setOrientation(Qt::Horizontal);
129
130 // colorSlippedArea->setWindowFlags(Qt::Widget );
131
132 QGridLayout *slippedAreaLayout = new QGridLayout();
133 controls::field(slippedAreaLayout, 0, "Opacity", sliderSlippedArea,
134 "Opacity of slipped-area polygons: 0 is transparent and 10 is opaque.");
135
136 // slippedAreaLayout->addWidget(colorSlippedArea);
137 slippedAreaBox->setLayout(slippedAreaLayout);
138
139 /* a few options that we must set for it to work nicely */
140 // colorSlippedArea->setOptions(
141 // /* do not use native dialog */
142 // QColorDialog::DontUseNativeDialog
143 // /* you don't need to set it, but if you don't set this
144 // the "OK" and "Cancel" buttons will show up, I don't
145 // think you'd want that. */
147 // );
148
149 // QGroupBox *groupBox = new QGroupBox(tr("&Push Buttons"));
150 // groupBox->setCheckable(true);
151 // groupBox->setChecked(true);
152
153 QGridLayout *meshAreaLayout = new QGridLayout();
155 meshAreaLayout, 0, "Global size", globalMeshSizeEdit,
156 "Maximum triangle area away from the loop boundary, in b squared. Press Enter to rebuild the slipped mesh.");
157 controls::field(meshAreaLayout, 1, "Local size", localMeshSizeEdit,
158 "Spacing between refinement points along dislocation segments, in Burgers-vector units. Press "
159 "Enter to rebuild the slipped mesh.");
160
161 meshAreaBox->setLayout(meshAreaLayout);
162
163 auto *loopsBox =
164 controls::box("Loops", this, "Show or hide loop outlines, loop nodes and loop-node IDs.", showLoops);
165 auto *appearanceBox = controls::box(
166 "Appearance", this, "Color settings shared by outlines, node markers, slipped areas and slipped meshes.");
167 mainLayout->addWidget(loopsBox, 0, 0, 1, 2);
168 colorScheme->setObjectName("loopColorScheme");
169 colorScheme->addItems({"Manual", "Slip system"});
170 manualColorButton->setObjectName("loopManualColor");
171 controls::field(controls::grid(appearanceBox), 0, "Coloring", colorScheme,
172 "Manual uses one chosen color. Slip system follows the SlipSystems palette and its live updates.");
173 controls::grid(appearanceBox)->addWidget(manualColorButton, 1, 0, 1, 2);
174 manualColorButton->setToolTip("Choose the manual color for all loop geometry. Default is light green.");
175 mainLayout->addWidget(appearanceBox, 1, 0, 1, 2);
176 mainLayout->addWidget(slippedAreaBox, 2, 0, 1, 2);
177 mainLayout->addWidget(meshAreaBox, 3, 0, 1, 2);
178 mainLayout->setRowStretch(4, 1);
179 slippedAreaBox->setToolTip("Show or hide the area swept by each dislocation loop.");
180 meshAreaBox->setToolTip("Show or hide triangulated slipped areas; enabling this group builds the mesh.");
181 connect(colorScheme, &QComboBox::currentIndexChanged, this,
182 [this](int)
183 {
184 applyColors();
185 modify();
186 });
187 connect(manualColorButton, &QPushButton::clicked, this,
188 [this]()
189 {
190 const QColor chosen = QColorDialog::getColor(manualColor, this, "Loop color");
191 if(chosen.isValid())
192 {
193 setManualColor(chosen);
194 }
195 });
196
197 // mainLayout->addWidget(sliderSlippedArea,1,1,1,1);
198 // mainLayout->addWidget(colorSlippedArea,1,2,1,1);
199
200
201 this->setLayout(mainLayout);
202
203 connect(showLoops,SIGNAL(stateChanged(int)), this, SLOT(modify()));
204 // connect(slippedAreaBox,SIGNAL(stateChanged(int)), this, SLOT(modify()));
205 connect(slippedAreaBox,SIGNAL(toggled(bool)), this, SLOT(modify()));
206 const auto refreshMesh = [this]()
207 {
208 if(meshAreaBox->isChecked())
209 {
210 updateConfiguration(slipSystemColors);
211 }
212 modify();
213 };
214 connect(meshAreaBox, &QGroupBox::toggled, this, refreshMesh);
215 connect(globalMeshSizeEdit, &QLineEdit::returnPressed, this, refreshMesh);
216 connect(localMeshSizeEdit, &QLineEdit::returnPressed, this, refreshMesh);
217
218 connect(sliderSlippedArea,SIGNAL(valueChanged(int)), this, SLOT(modify()));
219// connect(globalMeshSizeEdit,SIGNAL(returnPressed()), this, SLOT(updateConfiguration()));
220// connect(localMeshSizeEdit,SIGNAL(returnPressed()), this, SLOT(updateConfiguration()));
221
222
223 loopMapper->SetInputData(loopPolyData);
224 loopActor->SetMapper(loopMapper);
225 loopActor->GetProperty()->SetColor(0.0, 0.0, 1.0); //(R,G,B)
226 loopActor->SetVisibility(false);
227
228 areaMapper->SetInputData(areaPolyData);
229 areaActor->SetMapper(areaMapper);
230// areaActor->GetProperty()->SetColor(0.0, 1.0, 1.0); //(R,G,B)
231 areaActor->SetVisibility(false);
232
233 meshPolydata->Allocate();
234 meshMapper->SetInputData(meshPolydata);
235 meshActor->SetMapper ( meshMapper );
236 meshActor->SetVisibility(false);
237 meshActor->GetProperty()->SetOpacity(0.8); //Make the mesh have some transparency.
238
239 renderer->AddActor(nodeActor);
240 renderer->AddActor(labelActor);
241 renderer->AddActor(loopActor);
242 renderer->AddActor(areaActor);
243 renderer->AddActor(meshActor);
244 applyColors();
245
246 // std::vector<Eigen::Vector2d> clippedPolygonTemp(SutherlandHodgman::clip(polygon2d,box2d));
247
248}
249
250
251
253{
254 std::cout<<"Updating loops..."<<std::flush;
255 const auto t0= std::chrono::system_clock::now();
257 {
258 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
259 vtkSmartPointer<vtkDoubleArray> nodeLabels(vtkSmartPointer<vtkDoubleArray>::New());
260 nodeLabels->SetNumberOfComponents(1);
261 nodeLabels->SetName("node IDs");
262
263 // Loop occurrences remain distinct even when they share a network node.
264 // Record the actual VTK point index; never retain it across frame updates.
265 std::map<size_t,vtkIdType> loopNodeIndices;
266 nodeSlipSystems.clear();
267 for(const auto& weakNode : dislocationNetwork->loopNodes())
268 {
269 const auto& loopNode(weakNode.second.lock());
270 const auto& P(loopNode->get_P());
271 loopNodeIndices.emplace(loopNode->sID,points->InsertNextPoint(P.data()));
272 nodeLabels->InsertNextTuple1(loopNode->sID);
273 nodeSlipSystems.push_back(loopNode->loop()->slipSystem().get());
274 }
275
276 nodePolyData->SetPoints(points);
277// nodePolyData->GetPointData()->SetScalars(nodeColors);
278 nodePolyData->Modified();
279
280 labelPolyData->SetPoints(points);
281 labelPolyData->GetPointData()->SetScalars(nodeLabels);
282 labelPolyData->Modified();
283
284
285 vtkSmartPointer<vtkCellArray> cells(vtkSmartPointer<vtkCellArray>::New());
286 lineSlipSystems.clear();
287 areaSlipSystems.clear();
288 for(const auto& loopLink : dislocationNetwork->loopLinks())
289 {
290 vtkSmartPointer<vtkLine> line(vtkSmartPointer<vtkLine>::New());
291 line->GetPointIds()->SetId(0, loopNodeIndices.at(loopLink.second.source->sID)); // the second 0 is the index of the Origin in linesPolyData's points
292 line->GetPointIds()->SetId(1, loopNodeIndices.at(loopLink.second.sink->sID));
293 cells->InsertNextCell(line);
294 lineSlipSystems.push_back(loopLink.second.loop->slipSystem().get());
295
296
297 }
298 loopPolyData->SetPoints(points);
299 loopPolyData->SetLines(cells);
300 loopPolyData->Modified();
301
302 // Slipped area
303 vtkNew<vtkPoints> areaPoints;
304 vtkNew<vtkCellArray> areaPolygons;
305
306
307 areaPoints->SetDataTypeToDouble();
308 for(const auto& weakloop : dislocationNetwork->loops())
309 {
310 const auto& loop(weakloop.second.lock());
311 for(const auto& pair : loop->patches().localPatches())
312 {
313 for(const auto& triangle : triangulateLoopArea(pair.second))
314 {
315 vtkIdType ids[3];
316 for(size_t i=0;i<3;++i)
317 {
318 const Eigen::Vector3d position=pair.first->glidePlane->globalPosition(triangle[i]);
319 ids[i]=areaPoints->InsertNextPoint(position.data());
320 }
321 areaPolygons->InsertNextCell(3,ids);
322 areaSlipSystems.push_back(loop->slipSystem().get());
323 }
324 }
325 }
326 areaPolyData->SetPoints(areaPoints);
327 areaPolyData->SetPolys(areaPolygons);
328 areaPolyData->Modified();
329 areaMapper->SetScalarModeToUseCellData();
330
331
332
333
334 if(meshAreaBox->isChecked())
335 {
336 vtkSmartPointer<vtkPoints> meshPts(vtkSmartPointer<vtkPoints>::New());
337 vtkSmartPointer<vtkCellArray> meshTriangles(vtkSmartPointer<vtkCellArray>::New());
338 meshSlipSystems.clear();
339
340 const double meshSize(std::atof(globalMeshSizeEdit->text() .toStdString().c_str()));
341 const double localMeshSize(std::atof(localMeshSizeEdit->text() .toStdString().c_str()));
342 size_t ptsIncrement(0);
343 for(const auto& weakloop : dislocationNetwork->loops())
344 {
345 const auto& loop(weakloop.second.lock());
346 for(const auto& patchMesh : loop->meshed(meshSize,localMeshSize))
347 {
348 for(const auto& point3d : patchMesh.points)
349 {
350 meshPts->InsertNextPoint(point3d(0),point3d(1),point3d(2));
351 }
352 for(const auto& tri : patchMesh.triangles)
353 {
354 vtkSmartPointer<vtkTriangle> triangle = vtkSmartPointer<vtkTriangle>::New();
355 triangle->GetPointIds()->SetId (0,tri(0)+ptsIncrement);
356 triangle->GetPointIds()->SetId (1,tri(1)+ptsIncrement);
357 triangle->GetPointIds()->SetId (2,tri(2)+ptsIncrement);
358 meshTriangles->InsertNextCell ( triangle );
359 meshSlipSystems.push_back(loop->slipSystem().get());
360
361 }
362 ptsIncrement+=patchMesh.points.size();
363 }
364 }
365 meshPolydata->SetPoints ( meshPts );
366 meshPolydata->SetPolys ( meshTriangles );
367 meshPolydata->Modified();
368 meshMapper->SetScalarModeToUseCellData();
369// renWin->Render();
370
371
372 }
373// renderWindow->Render();
374 }
375 updateColors(sscm);
376 std::cout<<magentaColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<defaultColor<<std::endl;
377}
378
379void NetworkLoopActor::applyColors()
380{
381 const bool manual = colorScheme->currentIndex() == 0;
382 manualColorButton->setVisible(manual);
383 manualColorButton->setStyleSheet(QString("background-color: %1; color: %2;")
384 .arg(manualColor.name(), manualColor.lightness() > 128 ? "black" : "white"));
385 const auto apply = [&](vtkPolyData* data, vtkPolyDataMapper* mapper, vtkActor* actor,
386 const std::vector<const SlipSystem*>& systems, bool pointData)
387 {
388 actor->GetProperty()->SetColor(manualColor.redF(), manualColor.greenF(), manualColor.blueF());
389 mapper->SetScalarVisibility(!manual);
390 if(!manual)
391 {
392 auto colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
393 colors->SetNumberOfComponents(3);
394 colors->SetName("Slip system colors");
395 for(const auto* system : systems)
396 {
397 Eigen::Vector3i color(255, 255, 255);
398 const auto found = slipSystemColors.find(system);
399 if(found != slipSystemColors.end())
400 {
401 color = found->second->rgb();
402 }
403 colors->InsertNextTuple3(color.x(), color.y(), color.z());
404 }
405 if(pointData)
406 {
407 data->GetPointData()->SetScalars(colors);
408 mapper->SetScalarModeToUsePointData();
409 }
410 else
411 {
412 data->GetCellData()->SetScalars(colors);
413 mapper->SetScalarModeToUseCellData();
414 }
415 data->Modified();
416 mapper->SetColorModeToDirectScalars();
417 }
418 };
419 apply(nodePolyData, nodeMapper, nodeActor, nodeSlipSystems, true);
420 apply(loopPolyData, loopMapper, loopActor, lineSlipSystems, false);
421 apply(areaPolyData, areaMapper, areaActor, areaSlipSystems, false);
422 apply(meshPolydata, meshMapper, meshActor, meshSlipSystems, false);
423
424 nodeGlyphs->Update();
425}
426
427void NetworkLoopActor::setManualColor(const QColor& color)
428{
429 if(color.isValid())
430 {
431 manualColor = color;
432 applyColors();
433 modify();
434 }
435}
436
438{
439 slipSystemColors = sscm;
440 applyColors();
441}
442
443void NetworkLoopActor::modify()
444{
445 nodeGlyphs->SetScaleFactor(10);
446// sliderNodeRadius->setEnabled(showNodes->isChecked());
447 nodeActor->SetVisibility(showLoops->isChecked());
448 labelActor->SetVisibility(showLoops->isChecked());
449
450
451 loopActor->SetVisibility(showLoops->isChecked());
452 areaActor->SetVisibility(slippedAreaBox->isChecked());
453 meshActor->SetVisibility(meshAreaBox->isChecked());
454 areaActor->GetProperty()->SetOpacity(sliderSlippedArea->value()/10.0);
455
456 if(renderWindow->GetReadyForRendering())
457 {
458 renderWindow->Render();
459 }
460}
461
462} // namespace model
463#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::vector< std::array< Eigen::Vector2d, 3 > > triangulateLoopArea(const std::vector< Eigen::Vector2d > &contour)
void updateColors(const SlipSystemTab::SlipSystemColorMapType &sscm)
const std::shared_ptr< DislocationNetwork< 3 > > dislocationNetwork
const DefectiveCrystal< 3 > & defectiveCrystal
NetworkLoopActor(vtkGenericOpenGLRenderWindow *const, vtkRenderer *const, const DefectiveCrystal< 3 > &defectiveCrystal_in)
void updateConfiguration(const SlipSystemTab::SlipSystemColorMapType &sscm)
void setManualColor(const QColor &color)
std::map< const SlipSystem *, SlipSystemButton * > SlipSystemColorMapType
newotri tri
REAL ** triangle
Definition triangle.cpp:508
REAL t0
int i