FreeCAD / src /Mod /Inspection /Gui /ViewProviderInspection.cpp
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include <QApplication>
#include <QMenu>
#include <QMessageBox>
#include <Inventor/SoPickedPoint.h>
#include <Inventor/actions/SoRayPickAction.h>
#include <Inventor/actions/SoSearchAction.h>
#include <Inventor/details/SoFaceDetail.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/events/SoButtonEvent.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoIndexedFaceSet.h>
#include <Inventor/nodes/SoIndexedLineSet.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoMaterialBinding.h>
#include <Inventor/nodes/SoNormal.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/nodes/SoShapeHints.h>
#include <App/GeoFeature.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/Flag.h>
#include <Gui/MainWindow.h>
#include <Gui/SoFCColorBar.h>
#include <Gui/SoFCColorBarNotifier.h>
#include <Gui/View3DInventorViewer.h>
#include <Gui/Widgets.h>
#include <Mod/Inspection/App/InspectionFeature.h>
#include <Mod/Points/App/Properties.h>
#include "ViewProviderInspection.h"
using namespace InspectionGui;
bool ViewProviderInspection::addflag = false;
App::PropertyFloatConstraint::Constraints ViewProviderInspection::floatRange = {1.0, 64.0, 1.0};
PROPERTY_SOURCE(InspectionGui::ViewProviderInspection, Gui::ViewProviderDocumentObject)
ViewProviderInspection::ViewProviderInspection()
{
ADD_PROPERTY_TYPE(
OutsideGrayed,
(false),
"",
(App::PropertyType)(App::Prop_Output | App::Prop_Hidden),
""
);
ADD_PROPERTY_TYPE(
PointSize,
(1.0),
"Display",
(App::PropertyType)(App::Prop_None /*App::Prop_Hidden*/),
""
);
PointSize.setConstraints(&floatRange);
pcColorRoot = new SoSeparator();
pcColorRoot->ref();
pcMatBinding = new SoMaterialBinding;
pcMatBinding->ref();
pcColorMat = new SoMaterial;
pcColorMat->ref();
pcColorStyle = new SoDrawStyle();
pcColorRoot->addChild(pcColorStyle);
pcCoords = new SoCoordinate3;
pcCoords->ref();
// simple color bar
pcColorBar = new Gui::SoFCColorBar;
pcColorBar->Attach(this);
Gui::SoFCColorBarNotifier::instance().attach(pcColorBar);
pcColorBar->ref();
pcColorBar->setRange(-0.1f, 0.1f, 3);
pcLinkRoot = new SoGroup;
pcLinkRoot->ref();
pcPointStyle = new SoDrawStyle();
pcPointStyle->ref();
pcPointStyle->style = SoDrawStyle::POINTS;
pcPointStyle->pointSize = PointSize.getValue();
SelectionStyle.setValue(1); // BBOX
}
ViewProviderInspection::~ViewProviderInspection()
{
try {
pcColorRoot->unref();
pcCoords->unref();
pcMatBinding->unref();
pcColorMat->unref();
pcLinkRoot->unref();
pcPointStyle->unref();
deleteColorBar();
}
catch (Base::Exception& e) {
Base::Console().destructorError(
"ViewProviderInspection",
"ViewProviderInspection::deleteColorBar() threw an exception: %s\n",
e.what()
);
}
catch (...) {
Base::Console().destructorError(
"ViewProviderInspection",
"ViewProviderInspection destructor threw an unknown exception"
);
}
}
void ViewProviderInspection::onChanged(const App::Property* prop)
{
if (prop == &OutsideGrayed) {
if (pcColorBar) {
pcColorBar->setOutsideGrayed(OutsideGrayed.getValue());
pcColorBar->Notify(0);
}
}
else if (prop == &PointSize) {
pcPointStyle->pointSize = PointSize.getValue();
}
else {
inherited::onChanged(prop);
}
}
void ViewProviderInspection::hide()
{
inherited::hide();
pcColorStyle->style = SoDrawStyle::INVISIBLE;
}
void ViewProviderInspection::show()
{
inherited::show();
pcColorStyle->style = SoDrawStyle::FILLED;
}
void ViewProviderInspection::deleteColorBar()
{
Gui::SoFCColorBarNotifier::instance().detach(pcColorBar);
pcColorBar->Detach(this);
pcColorBar->unref();
}
void ViewProviderInspection::attach(App::DocumentObject* pcFeat)
{
// creates the standard viewing modes
inherited::attach(pcFeat);
SoShapeHints* flathints = new SoShapeHints;
flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
SoGroup* pcColorShadedRoot = new SoGroup();
pcColorShadedRoot->addChild(flathints);
// color shaded ------------------------------------------
SoDrawStyle* pcFlatStyle = new SoDrawStyle();
pcFlatStyle->style = SoDrawStyle::FILLED;
pcColorShadedRoot->addChild(pcFlatStyle);
pcColorShadedRoot->addChild(pcColorMat);
pcColorShadedRoot->addChild(pcMatBinding);
pcColorShadedRoot->addChild(pcLinkRoot);
addDisplayMaskMode(pcColorShadedRoot, "ColorShaded");
// Check for an already existing color bar
Gui::SoFCColorBar* pcBar
= ((Gui::SoFCColorBar*)findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId()));
if (pcBar) {
float fMin = pcColorBar->getMinValue();
float fMax = pcColorBar->getMaxValue();
// Attach to the foreign color bar and delete our own bar
pcBar->Attach(this);
pcBar->ref();
pcBar->setRange(fMin, fMax, 3);
pcBar->Notify(0);
deleteColorBar();
pcColorBar = pcBar;
}
pcColorRoot->addChild(pcColorBar);
}
bool ViewProviderInspection::setupFaces(const Data::ComplexGeoData* data)
{
std::vector<Base::Vector3d> points;
std::vector<Data::ComplexGeoData::Facet> faces;
// set the Distance property to the correct size to sync size of material node with number
// of vertices/points of the referenced geometry
double accuracy = data->getAccuracy();
data->getFaces(points, faces, accuracy);
if (faces.empty()) {
return false;
}
setupCoords(points);
setupFaceIndexes(faces);
return true;
}
bool ViewProviderInspection::setupLines(const Data::ComplexGeoData* data)
{
std::vector<Base::Vector3d> points;
std::vector<Data::ComplexGeoData::Line> lines;
double accuracy = data->getAccuracy();
data->getLines(points, lines, accuracy);
if (lines.empty()) {
return false;
}
setupCoords(points);
setupLineIndexes(lines);
return true;
}
bool ViewProviderInspection::setupPoints(
const Data::ComplexGeoData* data,
App::PropertyContainer* container
)
{
std::vector<Base::Vector3d> points;
std::vector<Base::Vector3f> normals;
std::vector<Base::Vector3d> normals_d;
double accuracy = data->getAccuracy();
data->getPoints(points, normals_d, accuracy);
if (points.empty()) {
return false;
}
normals.reserve(normals_d.size());
std::transform(
normals_d.cbegin(),
normals_d.cend(),
std::back_inserter(normals),
[](const Base::Vector3d& p) { return Base::toVector<float>(p); }
);
// If getPoints() doesn't deliver normals check a second property
if (normals.empty() && container) {
App::Property* propN = container->getPropertyByName("Normal");
if (propN && propN->isDerivedFrom<Points::PropertyNormalList>()) {
normals = static_cast<Points::PropertyNormalList*>(propN)->getValues();
}
}
setupCoords(points);
if (!normals.empty() && normals.size() == points.size()) {
setupNormals(normals);
}
this->pcLinkRoot->addChild(this->pcPointStyle);
this->pcLinkRoot->addChild(new SoPointSet());
return true;
}
void ViewProviderInspection::setupCoords(const std::vector<Base::Vector3d>& points)
{
this->pcLinkRoot->addChild(this->pcCoords);
this->pcCoords->point.setNum(points.size());
SbVec3f* pts = this->pcCoords->point.startEditing();
for (size_t i = 0; i < points.size(); i++) {
const Base::Vector3d& p = points[i];
pts[i].setValue((float)p.x, (float)p.y, (float)p.z);
}
this->pcCoords->point.finishEditing();
}
void ViewProviderInspection::setupNormals(const std::vector<Base::Vector3f>& normals)
{
SoNormal* normalNode = new SoNormal();
normalNode->vector.setNum(normals.size());
SbVec3f* norm = normalNode->vector.startEditing();
std::size_t i = 0;
for (const auto& it : normals) {
norm[i++].setValue(it.x, it.y, it.z);
}
normalNode->vector.finishEditing();
this->pcLinkRoot->addChild(normalNode);
}
void ViewProviderInspection::setupLineIndexes(const std::vector<Data::ComplexGeoData::Line>& lines)
{
SoIndexedLineSet* line = new SoIndexedLineSet();
this->pcLinkRoot->addChild(line);
line->coordIndex.setNum(3 * lines.size());
int32_t* indices = line->coordIndex.startEditing();
unsigned long j = 0;
for (const auto& it : lines) {
indices[3 * j + 0] = it.I1;
indices[3 * j + 1] = it.I2;
indices[3 * j + 2] = SO_END_LINE_INDEX;
j++;
}
line->coordIndex.finishEditing();
}
void ViewProviderInspection::setupFaceIndexes(const std::vector<Data::ComplexGeoData::Facet>& faces)
{
SoIndexedFaceSet* face = new SoIndexedFaceSet();
this->pcLinkRoot->addChild(face);
face->coordIndex.setNum(4 * faces.size());
int32_t* indices = face->coordIndex.startEditing();
unsigned long j = 0;
for (const auto& it : faces) {
indices[4 * j + 0] = it.I1;
indices[4 * j + 1] = it.I2;
indices[4 * j + 2] = it.I3;
indices[4 * j + 3] = SO_END_FACE_INDEX;
j++;
}
face->coordIndex.finishEditing();
}
void ViewProviderInspection::updateData(const App::Property* prop)
{
// set to the expected size
if (prop->isDerivedFrom<App::PropertyLink>()) {
App::GeoFeature* object
= static_cast<const App::PropertyLink*>(prop)->getValue<App::GeoFeature*>();
const App::PropertyComplexGeoData* propData = object ? object->getPropertyOfGeometry()
: nullptr;
if (propData) {
Gui::coinRemoveAllChildren(this->pcLinkRoot);
const Data::ComplexGeoData* data = propData->getComplexData();
if (!setupFaces(data)) {
if (!setupLines(data)) {
setupPoints(data, object);
}
}
}
}
else if (prop->is<Inspection::PropertyDistanceList>()) {
// force an update of the Inventor data nodes
if (this->pcObject) {
App::Property* link = this->pcObject->getPropertyByName("Actual");
if (link) {
updateData(link);
}
setDistances();
}
}
else if (prop->is<App::PropertyFloat>()) {
if (strcmp(prop->getName(), "SearchRadius") == 0) {
float fSearchRadius = ((App::PropertyFloat*)prop)->getValue();
this->search_radius = fSearchRadius;
pcColorBar->setRange(-fSearchRadius, fSearchRadius, 4);
pcColorBar->Notify(0);
}
}
}
SoSeparator* ViewProviderInspection::getFrontRoot() const
{
return pcColorRoot;
}
void ViewProviderInspection::setDistances()
{
if (!pcObject) {
return;
}
App::Property* pDistances = pcObject->getPropertyByName("Distances");
if (!pDistances) {
SoDebugError::post("ViewProviderInspection::setDistances", "Unknown property 'Distances'");
return;
}
if (!pDistances->is<Inspection::PropertyDistanceList>()) {
SoDebugError::post(
"ViewProviderInspection::setDistances",
"Property 'Distances' has type %s (Inspection::PropertyDistanceList was expected)",
pDistances->getTypeId().getName()
);
return;
}
// distance values
const std::vector<float>& fValues
= static_cast<Inspection::PropertyDistanceList*>(pDistances)->getValues();
if ((int)fValues.size() != this->pcCoords->point.getNum()) {
pcMatBinding->value = SoMaterialBinding::OVERALL;
return;
}
if (pcColorMat->diffuseColor.getNum() != static_cast<int>(fValues.size())) {
pcColorMat->diffuseColor.setNum(static_cast<int>(fValues.size()));
}
if (pcColorMat->transparency.getNum() != static_cast<int>(fValues.size())) {
pcColorMat->transparency.setNum(static_cast<int>(fValues.size()));
}
SbColor* cols = pcColorMat->diffuseColor.startEditing();
float* tran = pcColorMat->transparency.startEditing();
unsigned long j = 0;
for (std::vector<float>::const_iterator jt = fValues.begin(); jt != fValues.end(); ++jt, j++) {
Base::Color col = pcColorBar->getColor(*jt);
cols[j] = SbColor(col.r, col.g, col.b);
if (pcColorBar->isVisible(*jt)) {
tran[j] = 0.0f;
}
else {
tran[j] = 0.8f;
}
}
pcColorMat->diffuseColor.finishEditing();
pcColorMat->transparency.finishEditing();
pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
}
QIcon ViewProviderInspection::getIcon() const
{
// Get the icon of the view provider to the associated feature
QIcon px = inherited::getIcon();
App::Property* pActual = pcObject->getPropertyByName("Actual");
if (pActual && pActual->isDerivedFrom<App::PropertyLink>()) {
App::DocumentObject* docobj = ((App::PropertyLink*)pActual)->getValue();
if (docobj) {
Gui::Document* doc = Gui::Application::Instance->getDocument(docobj->getDocument());
Gui::ViewProvider* view = doc->getViewProvider(docobj);
px = view->getIcon();
}
}
return px;
}
void ViewProviderInspection::setDisplayMode(const char* ModeName)
{
if (strcmp("Visual Inspection", ModeName) == 0) {
setDistances();
setDisplayMaskMode("ColorShaded");
}
inherited::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderInspection::getDisplayModes() const
{
// add modes
std::vector<std::string> StrList;
StrList.emplace_back("Visual Inspection");
return StrList;
}
void ViewProviderInspection::OnChange(Base::Subject<int>& /*rCaller*/, int /*rcReason*/)
{
setActiveMode();
}
namespace InspectionGui
{
// Proxy class that receives an asynchronous custom event
class ViewProviderProxyObject: public QObject
{
public:
explicit ViewProviderProxyObject(QWidget* w)
: QObject(nullptr)
, widget(w)
{}
~ViewProviderProxyObject() override = default;
void customEvent(QEvent*) override
{
if (!widget.isNull()) {
QList<Gui::Flag*> flags = widget->findChildren<Gui::Flag*>();
if (!flags.isEmpty()) {
int ret = QMessageBox::question(
Gui::getMainWindow(),
QObject::tr("Remove annotations"),
QObject::tr("Do you want to remove all annotations?"),
QMessageBox::Yes,
QMessageBox::No
);
if (ret == QMessageBox::Yes) {
for (auto it : flags) {
it->deleteLater();
}
}
}
}
this->deleteLater();
}
static void addFlag(Gui::View3DInventorViewer* view, const QString& text, const SoPickedPoint* point)
{
Gui::Flag* flag = new Gui::Flag;
QPalette p;
p.setColor(QPalette::Window, QColor(85, 0, 127));
p.setColor(QPalette::Text, QColor(220, 220, 220));
flag->setPalette(p);
flag->setText(text);
flag->setOrigin(point->getPoint());
Gui::GLFlagWindow* flags = nullptr;
std::list<Gui::GLGraphicsItem*> glItems = view->getGraphicsItemsOfType(
Gui::GLFlagWindow::getClassTypeId()
);
if (glItems.empty()) {
flags = new Gui::GLFlagWindow(view);
view->addGraphicsItem(flags);
}
else {
flags = static_cast<Gui::GLFlagWindow*>(glItems.front());
}
flags->addFlag(flag, Gui::FlagLayout::BottomLeft);
}
private:
QPointer<QWidget> widget;
};
} // namespace InspectionGui
void ViewProviderInspection::inspectCallback(void* ud, SoEventCallback* n)
{
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());
const SoEvent* ev = n->getEvent();
if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(ev);
// Mark all incoming mouse button events as handled, especially, to deactivate the selection
// node
n->getAction()->setHandled();
n->setHandled();
if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
n->setHandled();
// context-menu
QMenu menu;
QAction* fl = menu.addAction(QObject::tr("Annotation"));
fl->setCheckable(true);
fl->setChecked(addflag);
QAction* cl = menu.addAction(QObject::tr("Leave Info Mode"));
QAction* id = menu.exec(QCursor::pos());
if (fl == id) {
addflag = fl->isChecked();
}
else if (cl == id) {
// post an event to a proxy object to make sure to avoid problems
// when opening a modal dialog
QApplication::postEvent(
new ViewProviderProxyObject(view->getGLWidget()),
new QEvent(QEvent::User)
);
view->setEditing(false);
view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
view->setRedirectToSceneGraph(false);
view->setRedirectToSceneGraphEnabled(false);
view->setSelectionEnabled(true);
view->removeEventCallback(SoButtonEvent::getClassTypeId(), inspectCallback, ud);
}
}
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1
&& mbe->getState() == SoButtonEvent::UP) {
const SoPickedPoint* point = n->getPickedPoint();
if (!point) {
Base::Console().message("No point picked.\n");
return;
}
n->setHandled();
// check if we have picked one a node of the view provider we are insterested in
Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());
if (vp && vp->isDerivedFrom<ViewProviderInspection>()) {
ViewProviderInspection* that = static_cast<ViewProviderInspection*>(vp);
QString info = that->inspectDistance(point);
Gui::getMainWindow()->setPaneText(1, info);
if (addflag) {
ViewProviderProxyObject::addFlag(view, info, point);
}
else {
Gui::ToolTip::showText(QCursor::pos(), info);
}
}
else {
// the nearest picked point was not part of the view provider
SoRayPickAction action(view->getSoRenderManager()->getViewportRegion());
action.setPickAll(true);
action.setPoint(mbe->getPosition());
action.apply(view->getSoRenderManager()->getSceneGraph());
const SoPickedPointList& pps = action.getPickedPointList();
for (int i = 0; i < pps.getLength(); ++i) {
const SoPickedPoint* point = pps[i];
vp = view->getViewProviderByPathFromTail(point->getPath());
if (vp && vp->isDerivedFrom<ViewProviderInspection>()) {
ViewProviderInspection* self = static_cast<ViewProviderInspection*>(vp);
QString info = self->inspectDistance(point);
Gui::getMainWindow()->setPaneText(1, info);
if (addflag) {
ViewProviderProxyObject::addFlag(view, info, point);
}
else {
Gui::ToolTip::showText(QCursor::pos(), info);
}
break;
}
}
}
}
}
// toggle between inspection and navigation mode
else if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
const SoKeyboardEvent* const ke = static_cast<const SoKeyboardEvent*>(ev);
if (ke->getState() == SoButtonEvent::DOWN && ke->getKey() == SoKeyboardEvent::ESCAPE) {
SbBool toggle = view->isRedirectedToSceneGraph();
view->setRedirectToSceneGraph(!toggle);
n->setHandled();
}
}
}
namespace InspectionGui
{
float calcArea(const SbVec3f& v1, const SbVec3f& v2, const SbVec3f& v3)
{
SbVec3f a = v2 - v1;
SbVec3f b = v3 - v1;
return a.cross(b).length() / 2.0f;
}
bool calcWeights(
const SbVec3f& v1,
const SbVec3f& v2,
const SbVec3f& v3,
const SbVec3f& p,
float& w0,
float& w1,
float& w2
)
{
float fAreaABC = calcArea(v1, v2, v3);
float fAreaPBC = calcArea(p, v2, v3);
float fAreaPCA = calcArea(p, v3, v1);
float fAreaPAB = calcArea(p, v1, v2);
w0 = fAreaPBC / fAreaABC;
w1 = fAreaPCA / fAreaABC;
w2 = fAreaPAB / fAreaABC;
return fabs(w0 + w1 + w2 - 1.0f) < 0.001f;
}
} // namespace InspectionGui
QString ViewProviderInspection::inspectDistance(const SoPickedPoint* pp) const
{
QString info;
const SoDetail* detail = pp->getDetail(pp->getPath()->getTail());
if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
// get the distances of the three points of the picked facet
const SoFaceDetail* facedetail = static_cast<const SoFaceDetail*>(detail);
App::Property* pDistance = this->pcObject->getPropertyByName("Distances");
if (pDistance && pDistance->is<Inspection::PropertyDistanceList>()) {
Inspection::PropertyDistanceList* dist = static_cast<Inspection::PropertyDistanceList*>(
pDistance
);
int index1 = facedetail->getPoint(0)->getCoordinateIndex();
int index2 = facedetail->getPoint(1)->getCoordinateIndex();
int index3 = facedetail->getPoint(2)->getCoordinateIndex();
float fVal1 = (*dist)[index1];
float fVal2 = (*dist)[index2];
float fVal3 = (*dist)[index3];
App::Property* pActual = this->pcObject->getPropertyByName("Actual");
if (pActual && pActual->isDerivedFrom<App::PropertyLink>()) {
float fSearchRadius = this->search_radius;
if (fVal1 > fSearchRadius || fVal2 > fSearchRadius || fVal3 > fSearchRadius) {
info = QObject::tr("Distance: > %1").arg(fSearchRadius);
}
else if (fVal1 < -fSearchRadius || fVal2 < -fSearchRadius || fVal3 < -fSearchRadius) {
info = QObject::tr("Distance: < %1").arg(-fSearchRadius);
}
else {
SoSearchAction searchAction;
searchAction.setType(SoCoordinate3::getClassTypeId());
searchAction.setInterest(SoSearchAction::FIRST);
searchAction.apply(pp->getPath()->getNodeFromTail(1));
SoPath* selectionPath = searchAction.getPath();
if (selectionPath) {
SoCoordinate3* coords = static_cast<SoCoordinate3*>(selectionPath->getTail());
const SbVec3f& v1 = coords->point[index1];
const SbVec3f& v2 = coords->point[index2];
const SbVec3f& v3 = coords->point[index3];
const SbVec3f& p = pp->getObjectPoint();
// get the weights
float w1, w2, w3;
calcWeights(v1, v2, v3, p, w1, w2, w3);
float fVal = w1 * fVal1 + w2 * fVal2 + w3 * fVal3;
info = QObject::tr("Distance: %1").arg(fVal);
}
}
}
}
}
else if (detail && detail->getTypeId() == SoPointDetail::getClassTypeId()) {
// safe downward cast, know the type
const SoPointDetail* pointdetail = static_cast<const SoPointDetail*>(detail);
// get the distance of the picked point
int index = pointdetail->getCoordinateIndex();
App::Property* prop = this->pcObject->getPropertyByName("Distances");
if (prop && prop->is<Inspection::PropertyDistanceList>()) {
Inspection::PropertyDistanceList* dist = static_cast<Inspection::PropertyDistanceList*>(
prop
);
float fVal = (*dist)[index];
info = QObject::tr("Distance: %1").arg(fVal);
}
}
return info;
}
// -----------------------------------------------
PROPERTY_SOURCE(InspectionGui::ViewProviderInspectionGroup, Gui::ViewProviderDocumentObjectGroup)
/**
* Creates the view provider for an object group.
*/
ViewProviderInspectionGroup::ViewProviderInspectionGroup() = default;
ViewProviderInspectionGroup::~ViewProviderInspectionGroup() = default;
/**
* Returns the pixmap for the opened list item.
*/
QIcon ViewProviderInspectionGroup::getIcon() const
{
// clang-format off
static const char * const ScanViewOpen[]={
"16 16 10 1",
"c c #000000",
". c None",
"h c #808000",
"# c #808080",
"a c #ffff00",
"r c #ff0000",
"o c #ffff00",
"g c #00ff00",
"t c #00ffff",
"b c #0000ff",
"................",
"...#####........",
"..#hhhhh#.......",
".#hhhhhhh######.",
".#hhhhhhhhhhhh#c",
".#hhhhhhhhhhhh#c",
".#hhhhhhhhhhhh#c",
"#############h#c",
"#aaaaaaaaaa##h#c",
"#aarroggtbbac##c",
".#arroggtbbaac#c",
".#aarroggtbbac#c",
"..#aaaaaaaaaa#cc",
"..#############c",
"...ccccccccccccc",
"................"};
static const char * const ScanViewClosed[] = {
"16 16 9 1",
"c c #000000",
". c None",
"# c #808080",
"a c #ffff00",
"r c #ff0000",
"o c #ffff00",
"g c #00ff00",
"t c #00ffff",
"b c #0000ff",
"................",
"...#####........",
"..#aaaaa#.......",
".#aaaaaaa######.",
".#aaaaaaaaaaaa#c",
".#aarroggtbbaa#c",
".#aarroggtbbaa#c",
".#aarroggtbbaa#c",
".#aarroggtbbaa#c",
".#aarroggtbbaa#c",
".#aarroggtbbaa#c",
".#aarroggtbbaa#c",
".#aaaaaaaaaaaa#c",
".##############c",
"..cccccccccccccc",
"................"};
// clang-format on
QIcon groupIcon;
groupIcon.addPixmap(QPixmap(ScanViewClosed), QIcon::Normal, QIcon::Off);
groupIcon.addPixmap(QPixmap(ScanViewOpen), QIcon::Normal, QIcon::On);
return groupIcon;
}