]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_InspectionPanel.cpp
Salome HOME
Issue #2556: "What is" window
[modules/shaper.git] / src / XGUI / XGUI_InspectionPanel.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "XGUI_InspectionPanel.h"
22 #include "XGUI_SelectionMgr.h"
23 #include "XGUI_Selection.h"
24 #include "XGUI_Tools.h"
25
26 #include <ModuleBase_ViewerPrs.h>
27 #include <ModuleBase_Tools.h>
28
29 #include <ModelAPI_Result.h>
30
31 #include <QLayout>
32 #include <QScrollArea>
33 #include <QLabel>
34 #include <QLineEdit>
35 #include <QTableWidget>
36 #include <QHeaderView>
37 #include <QTextBrowser>
38
39 #include <BRep_Tool.hxx>
40 #include <GeomAbs_CurveType.hxx>
41 #include <GeomAdaptor_Curve.hxx>
42 #include <Geom_BSplineCurve.hxx>
43 #include <gp_Circ.hxx>
44 #include <gp_Elips.hxx>
45 #include <TopTools_MapOfShape.hxx>
46 #include <TopTools_ListOfShape.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Vertex.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic
52
53 XGUI_InspectionPanel::XGUI_InspectionPanel(QWidget* theParent, XGUI_SelectionMgr* theMgr)
54   : QDockWidget(theParent),
55   mySelectionMgr(theMgr)
56 {
57   setWindowTitle(tr("Inspection Panel"));
58   setObjectName(INSPECTION_PANEL);
59   setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
60
61   QScrollArea* aScrollArea = new QScrollArea(this);
62   setWidget(aScrollArea);
63
64   // Create an internal widget
65   QWidget* aMainWidget = new QWidget(aScrollArea);
66
67   QVBoxLayout* aMainLayout = new QVBoxLayout(aMainWidget);
68   aMainLayout->setContentsMargins(5, 5, 5, 5);
69
70   QWidget* aNameWgt = new QWidget(aMainWidget);
71   QHBoxLayout* aNameLayout = new QHBoxLayout(aNameWgt);
72   aNameLayout->setContentsMargins(0, 0, 0, 0);
73   aNameLayout->addWidget(new QLabel(tr("Object"), aNameWgt));
74   myNameEdt = new QLineEdit(aNameWgt);
75   myNameEdt->setReadOnly(true);
76   aNameLayout->addWidget(myNameEdt);
77
78   aMainLayout->addWidget(aNameWgt);
79
80   // Table with sub-shapes
81   mySubShapesTab = new QTableWidget(9, 2, aMainWidget);
82   mySubShapesTab->setFocusPolicy(Qt::NoFocus);
83   mySubShapesTab->verticalHeader()->hide();
84   QStringList aTitles;
85   aTitles << tr("Sub-shapes") << tr("Number");
86   mySubShapesTab->setHorizontalHeaderLabels(aTitles);
87
88   QStringList aSubShapes;
89   aSubShapes << "SHAPE" << "COMPOUND" << "COMPSOLID" <<
90     "SOLID" << "SHELL" << "FACE" << "WIRE" << "EDGE" << "VERTEX";
91   int i = 0;
92   foreach(QString aType, aSubShapes) {
93     QTableWidgetItem* aItem = new QTableWidgetItem(aType);
94     aItem->setFlags(Qt::ItemIsEnabled);
95     mySubShapesTab->setItem(i++, 0, aItem);
96   }
97   for (i = 0; i < 9; i++) {
98     QTableWidgetItem* aItem = new QTableWidgetItem("");
99     aItem->setFlags(Qt::ItemIsEnabled);
100     aItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
101     mySubShapesTab->setItem(i, 1, aItem);
102   }
103   mySubShapesTab->setColumnWidth(0, 90);
104   mySubShapesTab->setColumnWidth(1, 70);
105
106   mySubShapesTab->setMaximumWidth(170);
107   mySubShapesTab->setMinimumHeight(300);
108
109   aMainLayout->addWidget(mySubShapesTab);
110
111   // Type of object
112   QWidget* aTypeWgt = new QWidget(aMainWidget);
113   QHBoxLayout* aTypeLayout = new QHBoxLayout(aTypeWgt);
114   aTypeLayout->setContentsMargins(0, 0, 0, 0);
115
116   aTypeLayout->addWidget(new QLabel(tr("Type:"), aTypeWgt));
117   myTypeLbl = new QLabel("", aTypeWgt);
118   aTypeLayout->addWidget(myTypeLbl);
119
120   aMainLayout->addWidget(aTypeWgt);
121
122   myTypeParams = new QTextBrowser(aMainWidget);
123   myTypeParams->setMaximumWidth(170);
124   myTypeParams->setMaximumHeight(160);
125   myTypeParams->setReadOnly(true);
126   myTypeParams->setFocusPolicy(Qt::NoFocus);
127   myTypeParams->setFrameStyle(QFrame::NoFrame);
128   myTypeParams->viewport()->setBackgroundRole(QPalette::Window);
129
130   aMainLayout->addWidget(myTypeParams);
131
132   aScrollArea->setWidget(aMainWidget);
133
134   connect(mySelectionMgr, SIGNAL(selectionChanged()), SLOT(onSelectionChanged()));
135 }
136
137 //********************************************************************
138 XGUI_InspectionPanel::~XGUI_InspectionPanel()
139 {
140 }
141
142 //********************************************************************
143 void XGUI_InspectionPanel::setSubShapeValue(SudShape theId, int theVal)
144 {
145   mySubShapesTab->item(theId, 1)->setText(QString::number(theVal));
146 }
147
148 //********************************************************************
149 void XGUI_InspectionPanel::clearContent()
150 {
151   setName("");
152   for (int i = 0; i <= VertexId; i++) {
153     mySubShapesTab->item((SudShape)i, 1)->setText("");
154   }
155   myTypeLbl->setText("");
156   myTypeParams->setText("");
157 }
158
159 //********************************************************************
160 void XGUI_InspectionPanel::onSelectionChanged()
161 {
162   clearContent();
163   XGUI_Selection* aSelection = mySelectionMgr->selection();
164   QList<ModuleBase_ViewerPrsPtr> aSelectedList = aSelection->getSelected(ModuleBase_ISelection::Viewer);
165   if (aSelectedList.count() > 0) {
166     ModuleBase_ViewerPrsPtr aPrs = aSelectedList.first();
167     setName(XGUI_Tools::generateName(aPrs));
168
169     TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
170     setShapeContent(aShape);
171     setShapeParams(aShape);
172   }
173 }
174
175 //********************************************************************
176 void XGUI_InspectionPanel::setName(const QString& theName)
177 {
178   myNameEdt->setText(theName);
179 }
180
181 //********************************************************************
182 void XGUI_InspectionPanel::setShapeContent(const TopoDS_Shape& theShape)
183 {
184   try {
185     OCC_CATCH_SIGNALS;
186     int iType, nbTypes[TopAbs_SHAPE];
187     for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
188       nbTypes[iType] = 0;
189     }
190     nbTypes[theShape.ShapeType()]++;
191
192     TopTools_MapOfShape aMapOfShape;
193     aMapOfShape.Add(theShape);
194     TopTools_ListOfShape aListOfShape;
195     aListOfShape.Append(theShape);
196
197     TopTools_ListIteratorOfListOfShape itL(aListOfShape);
198     for (; itL.More(); itL.Next()) {
199       TopoDS_Shape sp = itL.Value();
200       TopoDS_Iterator it(sp);
201       for (; it.More(); it.Next()) {
202         TopoDS_Shape s = it.Value();
203         if (aMapOfShape.Add(s)) {
204           aListOfShape.Append(s);
205           nbTypes[s.ShapeType()]++;
206         }
207       }
208     }
209     setSubShapeValue(VertexId, nbTypes[TopAbs_VERTEX]);
210     setSubShapeValue(EdgeId, nbTypes[TopAbs_EDGE]);
211     setSubShapeValue(WireId, nbTypes[TopAbs_WIRE]);
212     setSubShapeValue(FaceId, nbTypes[TopAbs_FACE]);
213     setSubShapeValue(ShellId, nbTypes[TopAbs_SHELL]);
214     setSubShapeValue(SolidId, nbTypes[TopAbs_SOLID]);
215     setSubShapeValue(CompsolidId, nbTypes[TopAbs_COMPSOLID]);
216     setSubShapeValue(CompoundId, nbTypes[TopAbs_COMPOUND]);
217     setSubShapeValue(ShapeId, aMapOfShape.Extent());
218   }
219   catch (Standard_Failure) {
220     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
221     //SetErrorCode(aFail->GetMessageString());
222   }
223 }
224
225 //********************************************************************
226 void XGUI_InspectionPanel::setShapeParams(const TopoDS_Shape& theShape)
227 {
228   switch (theShape.ShapeType()) {
229   case TopAbs_VERTEX:
230     fillVertex(theShape);
231     break;
232   case TopAbs_EDGE:
233     fillEdge(theShape);
234     break;
235   case TopAbs_FACE:
236     fillFace(theShape);
237     break;
238   case TopAbs_SOLID:
239     fillSolid(theShape);
240     break;
241   case TopAbs_WIRE:
242   case TopAbs_SHELL:
243   case TopAbs_COMPSOLID:
244   case TopAbs_COMPOUND:
245     fillContainer(theShape);
246     break;
247   }
248 }
249
250 //********************************************************************
251 void XGUI_InspectionPanel::fillVertex(const TopoDS_Shape& theShape)
252 {
253   TopoDS_Vertex aV = TopoDS::Vertex(theShape);
254   gp_Pnt aP = BRep_Tool::Pnt(aV);
255   setVertexType(aP.XYZ());
256 }
257
258 //********************************************************************
259 void XGUI_InspectionPanel::fillEdge(const TopoDS_Shape& theShape)
260 {
261   TopoDS_Edge aE = TopoDS::Edge(theShape);
262
263   bool bDegenerated = BRep_Tool::Degenerated(aE);
264
265   double aT1, aT2;
266   Handle(Geom_Curve) aC3D = BRep_Tool::Curve(aE, aT1, aT2);
267   GeomAdaptor_Curve aGAC(aC3D);
268   GeomAbs_CurveType aCT = aGAC.GetType();
269
270   if (aCT == GeomAbs_Line) { // Line
271     gp_Pnt aP1, aP2;
272     aGAC.D0(aT1, aP1);
273     aGAC.D0(aT2, aP2);
274     setLineType(aP1.XYZ(), aP2.XYZ());
275
276   } else if (aCT == GeomAbs_Circle) {
277     gp_Circ aCirc = aGAC.Circle();
278     gp_Pnt aP = aCirc.Location();
279     gp_Ax2 aAx2 = aCirc.Position();
280     double aR1 = aCirc.Radius();
281     gp_Dir aDir = aAx2.Axis().Direction();
282
283     bool isArc = (Abs(aT2 - aT1 - aC3D->Period()) >= Precision::PConfusion());
284     if (isArc) {
285       gp_Pnt aP1, aP2;
286       aGAC.D0(aT1, aP1);
287       aGAC.D0(aT2, aP2);
288       setArcType(aP.XYZ(), aDir.XYZ(), aR1, aP1.XYZ(), aP2.XYZ());
289     } else
290       setCircleType(aP.XYZ(), aDir.XYZ(), aR1);
291
292   } else if (aCT == GeomAbs_Ellipse) {
293     gp_Elips aElips = aGAC.Ellipse();
294     gp_Pnt aP = aElips.Location();
295     gp_Ax2 aAx2 = aElips.Position();
296     double aR1 = aElips.MajorRadius();
297     double aR2 = aElips.MinorRadius();
298     gp_Dir aDir = aAx2.Axis().Direction();
299     gp_Pnt aP1, aP2;
300     aGAC.D0(aT1, aP1);
301     aGAC.D0(aT2, aP2);
302     bool isArc = aP1.Distance(aP2) > Precision::Confusion();
303     if (isArc)
304       setEllipseArcType(aP.XYZ(), aDir.XYZ(), aR1, aR2, aP1.XYZ(), aP2.XYZ());
305     else
306       setEllipseType(aP.XYZ(), aDir.XYZ(), aR1, aR2);
307   }
308 }
309
310 //********************************************************************
311 void XGUI_InspectionPanel::fillFace(const TopoDS_Shape& theShape)
312 {
313
314 }
315
316 //********************************************************************
317 void XGUI_InspectionPanel::fillSolid(const TopoDS_Shape& theShape)
318 {
319
320 }
321
322 //********************************************************************
323 void XGUI_InspectionPanel::fillContainer(const TopoDS_Shape& theShape)
324 {
325
326 }
327
328 //********************************************************************
329 #define TITLE(val) ("<b>" + val + "</b>")
330
331 void XGUI_InspectionPanel::setCylinderType(double theX, double theY, double theZ,
332   double theDX, double theDY, double theDZ, double theRadius, double theHeight)
333 {
334   myTypeLbl->setText(tr("Cylinder"));
335   QString aParams = TITLE(tr("Center")) +
336     "<br> X: " + QString::number(theX) +
337     "<br> Y: " + QString::number(theY) +
338     "<br> Z: " + QString::number(theZ) +
339     "<br>" + TITLE(tr("Axis")) +
340     "<br> DX: " + QString::number(theDX) +
341     "<br> DY: " + QString::number(theDY) +
342     "<br> DZ: " + QString::number(theDZ) +
343     "<br>" + TITLE(tr("Dimensions")) +
344     "<br>" + tr("Radius:") + QString::number(theRadius) +
345     "<br>" + tr("Height") + QString::number(theHeight);
346
347   myTypeParams->setText(aParams);
348 }
349
350 //********************************************************************
351 void XGUI_InspectionPanel::setSphereType(double theX, double theY, double theZ, double theRadius)
352 {
353   myTypeLbl->setText(tr("Sphere"));
354   QString aParams = TITLE(tr("Center")) +
355     "<br> X: " + QString::number(theX) +
356     "<br> Y: " + QString::number(theY) +
357     "<br> Z: " + QString::number(theZ) +
358     "<br>" + TITLE(tr("Dimensions")) +
359     "<br>" + tr("Radius:") + QString::number(theRadius);
360   myTypeParams->setText(aParams);
361 }
362
363 //********************************************************************
364 void XGUI_InspectionPanel::setBoxType(double theX, double theY, double theZ,
365   double theXsize, double theYsize, double theZsize)
366 {
367   myTypeLbl->setText(tr("Box"));
368   QString aParams = TITLE(tr("Position")) +
369     "<br> X: " + QString::number(theX) +
370     "<br> Y: " + QString::number(theY) +
371     "<br> Z: " + QString::number(theZ) +
372     "<br>" + TITLE(tr("Dimensions")) +
373     "<br>" + "Ax :" + QString::number(theXsize) +
374     "<br>" + "Ay :" + QString::number(theYsize) +
375     "<br>" + "Az :" + QString::number(theZsize);
376   myTypeParams->setText(aParams);
377 }
378
379 //********************************************************************
380 void XGUI_InspectionPanel::setRotatedBoxType(double theX, double theY, double theZ,
381   double theZaxisX, double theZaxisY, double theZaxisZ,
382   double theXaxisX, double theXaxisY, double theXaxisZ,
383   double theXsize, double theYsize, double theZsize)
384 {
385   myTypeLbl->setText(tr("Box"));
386   QString aParams = TITLE(tr("Position")) +
387     "<br> X: " + QString::number(theX) +
388     "<br> Y: " + QString::number(theY) +
389     "<br> Z: " + QString::number(theZ) +
390     "<br>" + TITLE(tr("Z axis")) +
391     "<br> DX: " + QString::number(theZaxisX) +
392     "<br> DY: " + QString::number(theZaxisY) +
393     "<br> DZ: " + QString::number(theZaxisZ) +
394     "<br>" + TITLE(tr("X axis")) +
395     "<br> DX: " + QString::number(theXaxisX) +
396     "<br> DY: " + QString::number(theXaxisY) +
397     "<br> DZ: " + QString::number(theXaxisZ) +
398     "<br>" + TITLE(tr("Dimensions")) +
399     "<br>" + "Ax :" + QString::number(theXsize) +
400     "<br>" + "Ay :" + QString::number(theYsize) +
401     "<br>" + "Az :" + QString::number(theZsize);
402   myTypeParams->setText(aParams);
403 }
404
405 //********************************************************************
406 void XGUI_InspectionPanel::setPlaneType(double theX, double theY, double theZ,
407   double theDX, double theDY, double theDZ)
408 {
409   myTypeLbl->setText(tr("Plane"));
410   QString aParams = TITLE(tr("Center")) +
411     "<br> X: " + QString::number(theX) +
412     "<br> Y: " + QString::number(theY) +
413     "<br> Z: " + QString::number(theZ) +
414     "<br>" + TITLE(tr("Normal")) +
415     "<br> DX: " + QString::number(theDX) +
416     "<br> DY: " + QString::number(theDY) +
417     "<br> DZ: " + QString::number(theDZ);
418   myTypeParams->setText(aParams);
419 }
420
421 //********************************************************************
422 void XGUI_InspectionPanel::setVertexType(const gp_XYZ& theLoc)
423 {
424   myTypeLbl->setText(tr("Vertex"));
425   QString aParams = TITLE(tr("Coordinates")) +
426     "<br> X: " + QString::number(theLoc.X()) +
427     "<br> Y: " + QString::number(theLoc.Y()) +
428     "<br> Z: " + QString::number(theLoc.Z());
429   myTypeParams->setText(aParams);
430 }
431
432 //********************************************************************
433 void XGUI_InspectionPanel::setCircleType(const gp_XYZ& theLoc, const gp_XYZ& theDir,
434   double theRadius)
435 {
436   myTypeLbl->setText(tr("Circle"));
437   QString aParams = TITLE(tr("Center")) +
438     "<br> X: " + QString::number(theLoc.X()) +
439     "<br> Y: " + QString::number(theLoc.Y()) +
440     "<br> Z: " + QString::number(theLoc.Z()) +
441     "<br>" + TITLE(tr("Normal")) +
442     "<br> DX: " + QString::number(theDir.X()) +
443     "<br> DY: " + QString::number(theDir.Y()) +
444     "<br> DZ: " + QString::number(theDir.Z()) +
445     "<br>" + TITLE(tr("Dimensions")) +
446     "<br>" + tr("Radius:") + QString::number(theRadius);
447   myTypeParams->setText(aParams);
448 }
449
450 //********************************************************************
451 void XGUI_InspectionPanel::setArcType(const gp_XYZ& theLoc, const gp_XYZ& theDir,
452   double theRadius, const gp_XYZ& theP1, const gp_XYZ& theP2)
453 {
454   myTypeLbl->setText(tr("Arc"));
455   QString aParams = TITLE(tr("Center")) +
456     "<br> X: " + QString::number(theLoc.X()) +
457     "<br> Y: " + QString::number(theLoc.Y()) +
458     "<br> Z: " + QString::number(theLoc.Z()) +
459     "<br>" + TITLE(tr("Normal")) +
460     "<br> DX: " + QString::number(theDir.X()) +
461     "<br> DY: " + QString::number(theDir.Y()) +
462     "<br> DZ: " + QString::number(theDir.Z()) +
463     "<br>" + TITLE(tr("Dimensions")) +
464     "<br>" + tr("Radius:") + QString::number(theRadius) +
465     "<br>" + TITLE(tr("Point 1")) +
466     "<br> X: " + QString::number(theP1.X()) +
467     "<br> Y: " + QString::number(theP1.Y()) +
468     "<br> Z: " + QString::number(theP1.Z()) +
469     "<br>" + TITLE(tr("Point 2")) +
470     "<br> X: " + QString::number(theP2.X()) +
471     "<br> Y: " + QString::number(theP2.Y()) +
472     "<br> Z: " + QString::number(theP2.Z());
473   myTypeParams->setText(aParams);
474 }
475
476 //********************************************************************
477 void XGUI_InspectionPanel::setEllipseType(const gp_XYZ& theLoc, const gp_XYZ& theDir,
478   double theMajorRad, double theMinorRad)
479 {
480   myTypeLbl->setText(tr("Ellipse"));
481   QString aParams = TITLE(tr("Center")) +
482     "<br> X: " + QString::number(theLoc.X()) +
483     "<br> Y: " + QString::number(theLoc.Y()) +
484     "<br> Z: " + QString::number(theLoc.Z()) +
485     "<br>" + TITLE(tr("Normal")) +
486     "<br> DX: " + QString::number(theDir.X()) +
487     "<br> DY: " + QString::number(theDir.Y()) +
488     "<br> DZ: " + QString::number(theDir.Z()) +
489     "<br>" + TITLE(tr("Dimensions")) +
490     "<br>" + tr("Major radius:") + QString::number(theMajorRad) +
491     "<br>" + tr("Minor radius:") + QString::number(theMinorRad);
492   myTypeParams->setText(aParams);
493 }
494
495 //********************************************************************
496 void XGUI_InspectionPanel::setEllipseArcType(const gp_XYZ& theLoc, const gp_XYZ& theDir,
497   double theMajorRad, double theMinorRad, const gp_XYZ& theP1, const gp_XYZ& theP2)
498 {
499   myTypeLbl->setText(tr("Elliptical arc"));
500   QString aParams = TITLE(tr("Center")) +
501     "<br> X: " + QString::number(theLoc.X()) +
502     "<br> Y: " + QString::number(theLoc.Y()) +
503     "<br> Z: " + QString::number(theLoc.Z()) +
504     "<br>" + TITLE(tr("Normal")) +
505     "<br> DX: " + QString::number(theDir.X()) +
506     "<br> DY: " + QString::number(theDir.Y()) +
507     "<br> DZ: " + QString::number(theDir.Z()) +
508     "<br>" + TITLE(tr("Dimensions")) +
509     "<br>" + tr("Major radius:") + QString::number(theMajorRad) +
510     "<br>" + tr("Minor radius:") + QString::number(theMinorRad) +
511     "<br>" + TITLE(tr("Point 1")) +
512     "<br> X: " + QString::number(theP1.X()) +
513     "<br> Y: " + QString::number(theP1.Y()) +
514     "<br> Z: " + QString::number(theP1.Z()) +
515     "<br>" + TITLE(tr("Point 2")) +
516     "<br> X: " + QString::number(theP2.X()) +
517     "<br> Y: " + QString::number(theP2.Y()) +
518     "<br> Z: " + QString::number(theP2.Z());
519   myTypeParams->setText(aParams);
520 }
521
522 void XGUI_InspectionPanel::setLineType(const gp_XYZ& theP1, const gp_XYZ& theP2)
523 {
524   myTypeLbl->setText(tr("Line"));
525   QString aParams = TITLE(tr("Point 1")) +
526     "<br> X: " + QString::number(theP1.X()) +
527     "<br> Y: " + QString::number(theP1.Y()) +
528     "<br> Z: " + QString::number(theP1.Z()) +
529     "<br>" + TITLE(tr("Point 2")) +
530     "<br> X: " + QString::number(theP2.X()) +
531     "<br> Y: " + QString::number(theP2.Y()) +
532     "<br> Z: " + QString::number(theP2.Z());
533   myTypeParams->setText(aParams);
534 }