1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "XGUI_InspectionPanel.h"
22 #include "XGUI_SelectionMgr.h"
23 #include "XGUI_Selection.h"
24 #include "XGUI_Tools.h"
26 #include <ModuleBase_ViewerPrs.h>
27 #include <ModuleBase_Tools.h>
29 #include <ModelAPI_Result.h>
31 #include <GeomAPI_Ax3.h>
32 #include <GeomAPI_Box.h>
33 #include <GeomAPI_Circ.h>
34 #include <GeomAPI_Cone.h>
35 #include <GeomAPI_Cylinder.h>
36 #include <GeomAPI_Edge.h>
37 #include <GeomAPI_Ellipse.h>
38 #include <GeomAPI_Face.h>
39 #include <GeomAPI_Pln.h>
40 #include <GeomAPI_Pnt.h>
41 #include <GeomAPI_Shell.h>
42 #include <GeomAPI_Solid.h>
43 #include <GeomAPI_Sphere.h>
44 #include <GeomAPI_Torus.h>
45 #include <GeomAPI_Vertex.h>
46 #include <GeomAPI_Wire.h>
49 #include <QScrollArea>
52 #include <QTableWidget>
53 #include <QHeaderView>
54 #include <QTextBrowser>
56 #include <BRepBndLib.hxx>
57 #include <TopoDS_Iterator.hxx>
58 #include <TopTools_MapOfShape.hxx>
59 #include <TopTools_ListOfShape.hxx>
60 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic
62 // ================ Auxiliary functions ================
63 #define TITLE(val) ("<b>" + (val) + "</b>")
65 static void appendPointToParameters(const QString& thePointTitle,
66 const GeomPointPtr& theCoord,
69 theParams += TITLE(thePointTitle) +
70 "<br> X: " + QString::number(theCoord->x()) +
71 "<br> Y: " + QString::number(theCoord->y()) +
72 "<br> Z: " + QString::number(theCoord->z()) +
76 static void appendDirToParameters(const QString& theDirTitle,
77 const GeomDirPtr& theDirection,
80 theParams += TITLE(theDirTitle) +
81 "<br> DX: " + QString::number(theDirection->x()) +
82 "<br> DY: " + QString::number(theDirection->y()) +
83 "<br> DZ: " + QString::number(theDirection->z()) +
87 static void appendGroupNameToParameters(const QString& theGroupTitle, QString& theParams)
89 theParams += TITLE(theGroupTitle) + "<br>";
92 static void appendNamedValueToParameters(const QString& theName,
93 const double theValue,
96 theParams += theName + ": " + QString::number(theValue) + "<br>";
99 static void appendNamedValueToParameters(const QString& theName,
103 theParams += theName + ": " + (theValue ? "True" : "False") + "<br>";
107 // ================ XGUI_InspectionPanel ================
109 XGUI_InspectionPanel::XGUI_InspectionPanel(QWidget* theParent, XGUI_SelectionMgr* theMgr)
110 : QDockWidget(theParent),
111 mySelectionMgr(theMgr)
113 setWindowTitle(tr("Inspection Panel"));
114 setObjectName(INSPECTION_PANEL);
115 setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
117 QScrollArea* aScrollArea = new QScrollArea(this);
118 setWidget(aScrollArea);
120 // Create an internal widget
121 QWidget* aMainWidget = new QWidget(aScrollArea);
123 QVBoxLayout* aMainLayout = new QVBoxLayout(aMainWidget);
124 aMainLayout->setContentsMargins(5, 5, 5, 5);
126 QWidget* aNameWgt = new QWidget(aMainWidget);
127 QHBoxLayout* aNameLayout = new QHBoxLayout(aNameWgt);
128 aNameLayout->setContentsMargins(0, 0, 0, 0);
129 aNameLayout->addWidget(new QLabel(tr("Object"), aNameWgt));
130 myNameEdt = new QLineEdit(aNameWgt);
131 myNameEdt->setReadOnly(true);
132 aNameLayout->addWidget(myNameEdt);
134 aMainLayout->addWidget(aNameWgt);
136 // Table with sub-shapes
137 mySubShapesTab = new QTableWidget(9, 2, aMainWidget);
138 mySubShapesTab->setFocusPolicy(Qt::NoFocus);
139 mySubShapesTab->verticalHeader()->hide();
141 aTitles << tr("Sub-shapes") << tr("Number");
142 mySubShapesTab->setHorizontalHeaderLabels(aTitles);
144 QStringList aSubShapes;
145 aSubShapes << "SHAPE" << "COMPOUND" << "COMPSOLID" <<
146 "SOLID" << "SHELL" << "FACE" << "WIRE" << "EDGE" << "VERTEX";
148 foreach(QString aType, aSubShapes) {
149 QTableWidgetItem* aItem = new QTableWidgetItem(aType);
150 aItem->setFlags(Qt::ItemIsEnabled);
151 mySubShapesTab->setItem(i++, 0, aItem);
153 for (i = 0; i < 9; i++) {
154 QTableWidgetItem* aItem = new QTableWidgetItem("");
155 aItem->setFlags(Qt::ItemIsEnabled);
156 aItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
157 mySubShapesTab->setItem(i, 1, aItem);
159 mySubShapesTab->setColumnWidth(0, 90);
160 mySubShapesTab->setColumnWidth(1, 70);
162 mySubShapesTab->setMaximumWidth(170);
163 mySubShapesTab->setMinimumHeight(300);
165 aMainLayout->addWidget(mySubShapesTab);
168 QWidget* aTypeWgt = new QWidget(aMainWidget);
169 QHBoxLayout* aTypeLayout = new QHBoxLayout(aTypeWgt);
170 aTypeLayout->setContentsMargins(0, 0, 0, 0);
172 aTypeLayout->addWidget(new QLabel(tr("Type:"), aTypeWgt));
173 myTypeLbl = new QLabel("", aTypeWgt);
174 aTypeLayout->addWidget(myTypeLbl);
176 aMainLayout->addWidget(aTypeWgt);
178 myTypeParams = new QTextBrowser(aMainWidget);
179 myTypeParams->setMaximumWidth(170);
180 myTypeParams->setMaximumHeight(160);
181 myTypeParams->setReadOnly(true);
182 myTypeParams->setFocusPolicy(Qt::NoFocus);
183 myTypeParams->setFrameStyle(QFrame::NoFrame);
184 myTypeParams->viewport()->setBackgroundRole(QPalette::Window);
186 aMainLayout->addWidget(myTypeParams);
188 aScrollArea->setWidget(aMainWidget);
190 connect(mySelectionMgr, SIGNAL(selectionChanged()), SLOT(onSelectionChanged()));
193 //********************************************************************
194 XGUI_InspectionPanel::~XGUI_InspectionPanel()
198 //********************************************************************
199 void XGUI_InspectionPanel::setSubShapeValue(SudShape theId, int theVal)
201 mySubShapesTab->item(theId, 1)->setText(QString::number(theVal));
204 //********************************************************************
205 void XGUI_InspectionPanel::clearContent()
208 for (int i = 0; i <= VertexId; i++) {
209 mySubShapesTab->item((SudShape)i, 1)->setText("");
211 myTypeLbl->setText("");
212 myTypeParams->setText("");
215 //********************************************************************
216 void XGUI_InspectionPanel::onSelectionChanged()
219 XGUI_Selection* aSelection = mySelectionMgr->selection();
220 QList<ModuleBase_ViewerPrsPtr> aSelectedList =
221 aSelection->getSelected(ModuleBase_ISelection::Viewer);
222 if (aSelectedList.count() > 0) {
223 ModuleBase_ViewerPrsPtr aPrs = aSelectedList.first();
224 TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
227 setName(XGUI_Tools::generateName(aPrs));
228 setShapeContent(aShape);
229 setShapeParams(aShape);
233 //********************************************************************
234 void XGUI_InspectionPanel::setName(const QString& theName)
236 myNameEdt->setText(theName);
239 //********************************************************************
240 void XGUI_InspectionPanel::setShapeContent(const TopoDS_Shape& theShape)
244 int iType, nbTypes[TopAbs_SHAPE];
245 for (iType = 0; iType < TopAbs_SHAPE; ++iType) {
248 nbTypes[theShape.ShapeType()]++;
250 TopTools_MapOfShape aMapOfShape;
251 aMapOfShape.Add(theShape);
252 TopTools_ListOfShape aListOfShape;
253 aListOfShape.Append(theShape);
255 TopTools_ListIteratorOfListOfShape itL(aListOfShape);
256 for (; itL.More(); itL.Next()) {
257 TopoDS_Shape sp = itL.Value();
258 TopoDS_Iterator it(sp);
259 for (; it.More(); it.Next()) {
260 TopoDS_Shape s = it.Value();
261 if (aMapOfShape.Add(s)) {
262 aListOfShape.Append(s);
263 nbTypes[s.ShapeType()]++;
267 setSubShapeValue(VertexId, nbTypes[TopAbs_VERTEX]);
268 setSubShapeValue(EdgeId, nbTypes[TopAbs_EDGE]);
269 setSubShapeValue(WireId, nbTypes[TopAbs_WIRE]);
270 setSubShapeValue(FaceId, nbTypes[TopAbs_FACE]);
271 setSubShapeValue(ShellId, nbTypes[TopAbs_SHELL]);
272 setSubShapeValue(SolidId, nbTypes[TopAbs_SOLID]);
273 setSubShapeValue(CompsolidId, nbTypes[TopAbs_COMPSOLID]);
274 setSubShapeValue(CompoundId, nbTypes[TopAbs_COMPOUND]);
275 setSubShapeValue(ShapeId, aMapOfShape.Extent());
277 catch (Standard_Failure) {
278 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
279 //SetErrorCode(aFail->GetMessageString());
283 //********************************************************************
284 void XGUI_InspectionPanel::setShapeParams(const TopoDS_Shape& theShape)
286 GeomShapePtr aShape(new GeomAPI_Shape);
287 aShape->setImpl(new TopoDS_Shape(theShape));
289 switch (aShape->shapeType()) {
290 case GeomAPI_Shape::VERTEX:
291 fillVertex(aShape->vertex());
293 case GeomAPI_Shape::EDGE:
294 fillEdge(aShape->edge());
296 case GeomAPI_Shape::FACE:
297 fillFace(aShape->face());
299 case GeomAPI_Shape::SOLID:
300 fillSolid(aShape->solid());
302 case GeomAPI_Shape::WIRE:
303 fillWire(aShape->wire());
305 case GeomAPI_Shape::SHELL:
306 fillShell(aShape->shell());
308 case GeomAPI_Shape::COMPSOLID:
309 case GeomAPI_Shape::COMPOUND:
310 fillContainer(aShape);
315 //********************************************************************
316 void XGUI_InspectionPanel::fillVertex(const GeomVertexPtr& theVertex)
318 GeomPointPtr aPoint = theVertex->point();
320 myTypeLbl->setText(tr("Vertex"));
323 appendPointToParameters(tr("Coordinates"), aPoint, aParams);
324 myTypeParams->setText(aParams);
327 //********************************************************************
328 void XGUI_InspectionPanel::fillEdge(const GeomEdgePtr& theEdge)
331 if (theEdge->isDegenerated())
332 appendNamedValueToParameters(tr("Degenerated"), true, aParams);
334 GeomPointPtr aStartPnt = theEdge->firstPoint();
335 GeomPointPtr aEndPnt = theEdge->lastPoint();
336 bool addStartEndPoints = false;
338 if (theEdge->isLine()) {
339 myTypeLbl->setText(tr("Line segment"));
340 addStartEndPoints = true;
343 GeomCirclePtr aCircle = theEdge->circle();
345 addStartEndPoints = aStartPnt->distance(aEndPnt) >= Precision::Confusion();
346 if (addStartEndPoints)
347 myTypeLbl->setText("Arc of circle");
349 myTypeLbl->setText("Circle");
351 appendPointToParameters(tr("Center"), aCircle->center(), aParams);
352 appendDirToParameters(tr("Normal"), aCircle->normal(), aParams);
353 appendGroupNameToParameters(tr("Dimensions"), aParams);
354 appendNamedValueToParameters(tr("Radius"), aCircle->radius(), aParams);
357 GeomEllipsePtr anEllipse = theEdge->ellipse();
359 addStartEndPoints = aStartPnt->distance(aEndPnt) >= Precision::Confusion();
360 if (addStartEndPoints)
361 myTypeLbl->setText("Arc of ellipse");
363 myTypeLbl->setText("Ellipse");
365 appendPointToParameters(tr("Center"), anEllipse->center(), aParams);
366 appendDirToParameters(tr("Normal"), anEllipse->normal(), aParams);
367 appendGroupNameToParameters(tr("Dimensions"), aParams);
368 appendNamedValueToParameters(tr("Major radius"), anEllipse->majorRadius(), aParams);
369 appendNamedValueToParameters(tr("Minor radius"), anEllipse->minorRadius(), aParams);
373 myTypeLbl->setText(tr("Edge"));
377 if (addStartEndPoints) {
378 appendPointToParameters(tr("Start point"), aStartPnt, aParams);
379 appendPointToParameters(tr("End point"), aEndPnt, aParams);
381 myTypeParams->setText(aParams);
384 //********************************************************************
385 void XGUI_InspectionPanel::fillWire(const GeomWirePtr& theWire)
388 appendNamedValueToParameters(tr("Closed"), theWire->isClosed(), aParams);
390 // check the wire is a polygon
391 std::list<GeomPointPtr> aPolygonPoints;
392 if (theWire->isPolygon(aPolygonPoints)) {
393 myTypeLbl->setText(tr("Polygon"));
394 int aCornerIndex = 0;
395 for (std::list<GeomPointPtr>::const_iterator aPtIt = aPolygonPoints.begin();
396 aPtIt != aPolygonPoints.end(); ++aPtIt)
397 appendPointToParameters(tr("Point") + " " + QString::number(++aCornerIndex),
401 myTypeLbl->setText(tr("Wire"));
403 myTypeParams->setText(aParams);
406 //********************************************************************
407 void XGUI_InspectionPanel::fillFace(const GeomFacePtr& theFace)
410 // 1. Plane and planar faces
411 GeomPlanePtr aPlane = theFace->getPlane();
413 bool isCommonCase = true;
414 // Check face bounded by circle or ellipse
415 std::list<GeomShapePtr> aSubs = theFace->subShapes(GeomAPI_Shape::EDGE);
416 if (aSubs.size() == 1) {
417 GeomEdgePtr anEdge = aSubs.front()->edge();
418 if (anEdge->isCircle() || anEdge->isEllipse()) {
420 isCommonCase = false;
424 // Check face bounded by a single wire which is rectangle
425 aSubs = theFace->subShapes(GeomAPI_Shape::WIRE);
426 if (aSubs.size() == 1) {
427 GeomWirePtr aWire = aSubs.front()->wire();
428 std::list<GeomPointPtr> aCorners;
429 if (aWire->isRectangle(aCorners)) {
430 GeomPointPtr aBaseCorner = aCorners.front();
431 aCorners.pop_front();
433 double aWidth = aBaseCorner->distance(aCorners.front());
434 double aHeight = aBaseCorner->distance(aCorners.back());
436 myTypeLbl->setText(tr("Rectangle"));
437 appendPointToParameters(tr("Corner"), aBaseCorner, aParams);
438 appendDirToParameters(tr("Normal"), aPlane->direction(), aParams);
439 appendGroupNameToParameters(tr("Dimensions"), aParams);
440 appendNamedValueToParameters(tr("Width"), aWidth, aParams);
441 appendNamedValueToParameters(tr("Height"), aHeight, aParams);
442 myTypeParams->setText(aParams);
444 isCommonCase = false;
450 setPlaneType(tr("Plane"), aPlane);
454 GeomSpherePtr aSphere = theFace->getSphere();
456 setSphereType(tr("Sphere"), aSphere);
459 GeomCylinderPtr aCylinder = theFace->getCylinder();
461 setCylinderType(tr("Cylinder"), aCylinder);
464 GeomConePtr aCone = theFace->getCone();
466 setConeType(tr("Cone"), aCone);
469 GeomTorusPtr aTorus = theFace->getTorus();
471 setTorusType(tr("Torus"), aTorus);
474 myTypeLbl->setText(tr("Face"));
481 //********************************************************************
482 void XGUI_InspectionPanel::fillShell(const GeomShellPtr& theShell)
485 GeomSpherePtr aSphere = theShell->getSphere();
487 setSphereType(tr("Sphere"), aSphere);
490 GeomCylinderPtr aCylinder = theShell->getCylinder();
492 setCylinderType(tr("Cylinder"), aCylinder);
495 GeomConePtr aCone = theShell->getCone();
497 setConeType(tr("Cone"), aCone);
500 GeomTorusPtr aTorus = theShell->getTorus();
502 setTorusType(tr("Torus"), aTorus);
504 // 5. Axis-aligned/Rotated Box
505 GeomBoxPtr aBox = theShell->getParallelepiped();
507 if (aBox->isAxesAligned())
508 setBoxType(tr("Box"), aBox);
510 setRotatedBoxType(tr("Rotated Box"), aBox);
514 myTypeLbl->setText(tr("Shell"));
521 //********************************************************************
522 void XGUI_InspectionPanel::fillSolid(const GeomSolidPtr& theSolid)
525 GeomSpherePtr aSphere = theSolid->getSphere();
527 setSphereType(tr("Sphere"), aSphere);
530 GeomCylinderPtr aCylinder = theSolid->getCylinder();
532 setCylinderType(tr("Cylinder"), aCylinder);
535 GeomConePtr aCone = theSolid->getCone();
537 setConeType(tr("Cone"), aCone);
540 GeomTorusPtr aTorus = theSolid->getTorus();
542 setTorusType(tr("Torus"), aTorus);
544 // 5. Axis-aligned/Rotated Box
545 GeomBoxPtr aBox = theSolid->getParallelepiped();
547 if (aBox->isAxesAligned())
548 setBoxType(tr("Box"), aBox);
550 setRotatedBoxType(tr("Rotated Box"), aBox);
554 myTypeLbl->setText(tr("Solid"));
561 //********************************************************************
562 void XGUI_InspectionPanel::fillContainer(const GeomShapePtr& theShape)
564 if (theShape->shapeType() == GeomAPI_Shape::COMPSOLID)
565 myTypeLbl->setText("CompSolid");
566 else if (theShape->shapeType() == GeomAPI_Shape::COMPOUND)
567 myTypeLbl->setText("Compound");
571 BRepBndLib::Add(theShape->impl<TopoDS_Shape>(), aBB);
573 gp_Pnt aMinPnt = aBB.CornerMin();
574 GeomPointPtr aMinPoint(new GeomAPI_Pnt(aMinPnt.X(), aMinPnt.Y(), aMinPnt.Z()));
576 gp_Pnt aMaxPnt = aBB.CornerMax();
577 GeomPointPtr aMaxPoint(new GeomAPI_Pnt(aMaxPnt.X(), aMaxPnt.Y(), aMaxPnt.Z()));
580 appendGroupNameToParameters(tr("Bounding box"), aParams);
581 appendPointToParameters(tr("Minimal corner"), aMinPoint, aParams);
582 appendPointToParameters(tr("Maximal corner"), aMaxPoint, aParams);
585 void XGUI_InspectionPanel::setPlaneType(const QString& theTitle,
586 const std::shared_ptr<GeomAPI_Pln>& thePlane)
588 myTypeLbl->setText(theTitle);
590 appendPointToParameters(tr("Origin"), thePlane->location(), aParams);
591 appendDirToParameters(tr("Normal"), thePlane->direction(), aParams);
592 myTypeParams->setText(aParams);
595 void XGUI_InspectionPanel::setSphereType(const QString& theTitle,
596 const std::shared_ptr<GeomAPI_Sphere>& theSphere)
598 myTypeLbl->setText(theTitle);
600 appendPointToParameters(tr("Center"), theSphere->center(), aParams);
601 appendGroupNameToParameters(tr("Dimensions"), aParams);
602 appendNamedValueToParameters(tr("Radius"), theSphere->radius(), aParams);
603 myTypeParams->setText(aParams);
606 void XGUI_InspectionPanel::setCylinderType(const QString& theTitle,
607 const std::shared_ptr<GeomAPI_Cylinder>& theCyl)
609 myTypeLbl->setText(theTitle);
611 appendPointToParameters(tr("Position"), theCyl->location(), aParams);
612 appendDirToParameters(tr("Axis"), theCyl->axis(), aParams);
613 appendGroupNameToParameters(tr("Dimensions"), aParams);
614 appendNamedValueToParameters(tr("Radius"), theCyl->radius(), aParams);
615 appendNamedValueToParameters(tr("Height"), theCyl->height(), aParams);
616 myTypeParams->setText(aParams);
619 void XGUI_InspectionPanel::setConeType(const QString& theTitle,
620 const std::shared_ptr<GeomAPI_Cone>& theCone)
622 myTypeLbl->setText(theTitle);
624 appendPointToParameters(tr("Position"), theCone->location(), aParams);
625 appendDirToParameters(tr("Axis"), theCone->axis(), aParams);
626 appendGroupNameToParameters(tr("Dimensions"), aParams);
627 appendNamedValueToParameters(tr("Radius 1"), theCone->radius1(), aParams);
628 appendNamedValueToParameters(tr("Radius 2"), theCone->radius2(), aParams);
629 appendNamedValueToParameters(tr("Height"), theCone->height(), aParams);
630 myTypeParams->setText(aParams);
633 void XGUI_InspectionPanel::setTorusType(const QString& theTitle,
634 const std::shared_ptr<GeomAPI_Torus>& theTorus)
636 myTypeLbl->setText(theTitle);
638 appendPointToParameters(tr("Center"), theTorus->center(), aParams);
639 appendDirToParameters(tr("Axis"), theTorus->direction(), aParams);
640 appendGroupNameToParameters(tr("Dimensions"), aParams);
641 appendNamedValueToParameters(tr("Major radius"), theTorus->majorRadius(), aParams);
642 appendNamedValueToParameters(tr("Minor radius"), theTorus->minorRadius(), aParams);
643 myTypeParams->setText(aParams);
646 void XGUI_InspectionPanel::setBoxType(const QString& theTitle,
647 const std::shared_ptr<GeomAPI_Box>& theBox)
649 myTypeLbl->setText(theTitle);
651 appendPointToParameters(tr("Position"), theBox->axes()->origin(), aParams);
652 appendGroupNameToParameters(tr("Dimensions"), aParams);
653 appendNamedValueToParameters(tr("Width"), theBox->width(), aParams);
654 appendNamedValueToParameters(tr("Depth"), theBox->depth(), aParams);
655 appendNamedValueToParameters(tr("Height"), theBox->height(), aParams);
656 myTypeParams->setText(aParams);
659 void XGUI_InspectionPanel::setRotatedBoxType(const QString& theTitle,
660 const std::shared_ptr<GeomAPI_Box>& theBox)
662 myTypeLbl->setText(theTitle);
664 std::shared_ptr<GeomAPI_Ax3> anAxes = theBox->axes();
665 appendPointToParameters(tr("Position"), anAxes->origin(), aParams);
666 appendDirToParameters(tr("Z axis"), anAxes->normal(), aParams);
667 appendDirToParameters(tr("X axis"), anAxes->dirX(), aParams);
668 appendGroupNameToParameters(tr("Dimensions"), aParams);
669 appendNamedValueToParameters(tr("Width"), theBox->width(), aParams);
670 appendNamedValueToParameters(tr("Depth"), theBox->depth(), aParams);
671 appendNamedValueToParameters(tr("Height"), theBox->height(), aParams);
672 myTypeParams->setText(aParams);