FreeCAD
810 строк · 28.9 Кб
1/***************************************************************************
2* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
3* *
4* This file is part of the FreeCAD CAx development system. *
5* *
6* This library is free software; you can redistribute it and/or *
7* modify it under the terms of the GNU Library General Public *
8* License as published by the Free Software Foundation; either *
9* version 2 of the License, or (at your option) any later version. *
10* *
11* This library is distributed in the hope that it will be useful, *
12* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14* GNU Library General Public License for more details. *
15* *
16* You should have received a copy of the GNU Library General Public *
17* License along with this library; see the file COPYING.LIB. If not, *
18* write to the Free Software Foundation, Inc., 59 Temple Place, *
19* Suite 330, Boston, MA 02111-1307, USA *
20* *
21***************************************************************************/
22
23#include "PreCompiled.h"24
25#ifndef _PreComp_26#include <QApplication>27#include <QMenu>28#include <QMessageBox>29
30#include <Inventor/SoPickedPoint.h>31#include <Inventor/actions/SoRayPickAction.h>32#include <Inventor/actions/SoSearchAction.h>33#include <Inventor/details/SoFaceDetail.h>34#include <Inventor/errors/SoDebugError.h>35#include <Inventor/events/SoButtonEvent.h>36#include <Inventor/events/SoKeyboardEvent.h>37#include <Inventor/events/SoMouseButtonEvent.h>38#include <Inventor/nodes/SoCoordinate3.h>39#include <Inventor/nodes/SoDrawStyle.h>40#include <Inventor/nodes/SoIndexedFaceSet.h>41#include <Inventor/nodes/SoIndexedLineSet.h>42#include <Inventor/nodes/SoMaterial.h>43#include <Inventor/nodes/SoMaterialBinding.h>44#include <Inventor/nodes/SoNormal.h>45#include <Inventor/nodes/SoPointSet.h>46#include <Inventor/nodes/SoShapeHints.h>47#endif48
49#include <App/GeoFeature.h>50#include <Gui/Application.h>51#include <Gui/Document.h>52#include <Gui/Flag.h>53#include <Gui/MainWindow.h>54#include <Gui/SoFCColorBar.h>55#include <Gui/SoFCColorBarNotifier.h>56#include <Gui/View3DInventorViewer.h>57#include <Gui/Widgets.h>58#include <Mod/Inspection/App/InspectionFeature.h>59#include <Mod/Points/App/Properties.h>60
61#include "ViewProviderInspection.h"62
63
64using namespace InspectionGui;65
66
67bool ViewProviderInspection::addflag = false;68App::PropertyFloatConstraint::Constraints ViewProviderInspection::floatRange = {1.0, 64.0, 1.0};69
70PROPERTY_SOURCE(InspectionGui::ViewProviderInspection, Gui::ViewProviderDocumentObject)71
72ViewProviderInspection::ViewProviderInspection()73{
74ADD_PROPERTY_TYPE(OutsideGrayed,75(false),76"",77(App::PropertyType)(App::Prop_Output | App::Prop_Hidden),78"");79ADD_PROPERTY_TYPE(PointSize,80(1.0),81"Display",82(App::PropertyType)(App::Prop_None /*App::Prop_Hidden*/),83"");84PointSize.setConstraints(&floatRange);85
86pcColorRoot = new SoSeparator();87pcColorRoot->ref();88pcMatBinding = new SoMaterialBinding;89pcMatBinding->ref();90pcColorMat = new SoMaterial;91pcColorMat->ref();92pcColorStyle = new SoDrawStyle();93pcColorRoot->addChild(pcColorStyle);94pcCoords = new SoCoordinate3;95pcCoords->ref();96// simple color bar97pcColorBar = new Gui::SoFCColorBar;98pcColorBar->Attach(this);99Gui::SoFCColorBarNotifier::instance().attach(pcColorBar);100pcColorBar->ref();101pcColorBar->setRange(-0.1f, 0.1f, 3);102pcLinkRoot = new SoGroup;103pcLinkRoot->ref();104
105pcPointStyle = new SoDrawStyle();106pcPointStyle->ref();107pcPointStyle->style = SoDrawStyle::POINTS;108pcPointStyle->pointSize = PointSize.getValue();109SelectionStyle.setValue(1); // BBOX110}
111
112ViewProviderInspection::~ViewProviderInspection()113{
114pcColorRoot->unref();115pcCoords->unref();116pcMatBinding->unref();117pcColorMat->unref();118deleteColorBar();119pcLinkRoot->unref();120pcPointStyle->unref();121}
122
123void ViewProviderInspection::onChanged(const App::Property* prop)124{
125if (prop == &OutsideGrayed) {126if (pcColorBar) {127pcColorBar->setOutsideGrayed(OutsideGrayed.getValue());128pcColorBar->Notify(0);129}130}131else if (prop == &PointSize) {132pcPointStyle->pointSize = PointSize.getValue();133}134else {135inherited::onChanged(prop);136}137}
138
139void ViewProviderInspection::hide()140{
141inherited::hide();142pcColorStyle->style = SoDrawStyle::INVISIBLE;143}
144
145void ViewProviderInspection::show()146{
147inherited::show();148pcColorStyle->style = SoDrawStyle::FILLED;149}
150
151void ViewProviderInspection::deleteColorBar()152{
153Gui::SoFCColorBarNotifier::instance().detach(pcColorBar);154pcColorBar->Detach(this);155pcColorBar->unref();156}
157
158void ViewProviderInspection::attach(App::DocumentObject* pcFeat)159{
160// creates the standard viewing modes161inherited::attach(pcFeat);162
163SoShapeHints* flathints = new SoShapeHints;164flathints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;165flathints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;166
167SoGroup* pcColorShadedRoot = new SoGroup();168pcColorShadedRoot->addChild(flathints);169
170// color shaded ------------------------------------------171SoDrawStyle* pcFlatStyle = new SoDrawStyle();172pcFlatStyle->style = SoDrawStyle::FILLED;173pcColorShadedRoot->addChild(pcFlatStyle);174
175pcColorShadedRoot->addChild(pcColorMat);176pcColorShadedRoot->addChild(pcMatBinding);177pcColorShadedRoot->addChild(pcLinkRoot);178
179addDisplayMaskMode(pcColorShadedRoot, "ColorShaded");180
181// Check for an already existing color bar182Gui::SoFCColorBar* pcBar =183((Gui::SoFCColorBar*)findFrontRootOfType(Gui::SoFCColorBar::getClassTypeId()));184if (pcBar) {185float fMin = pcColorBar->getMinValue();186float fMax = pcColorBar->getMaxValue();187
188// Attach to the foreign color bar and delete our own bar189pcBar->Attach(this);190pcBar->ref();191pcBar->setRange(fMin, fMax, 3);192pcBar->Notify(0);193deleteColorBar();194pcColorBar = pcBar;195}196
197pcColorRoot->addChild(pcColorBar);198}
199
200bool ViewProviderInspection::setupFaces(const Data::ComplexGeoData* data)201{
202std::vector<Base::Vector3d> points;203std::vector<Data::ComplexGeoData::Facet> faces;204
205// set the Distance property to the correct size to sync size of material node with number206// of vertices/points of the referenced geometry207double accuracy = data->getAccuracy();208data->getFaces(points, faces, accuracy);209if (faces.empty()) {210return false;211}212
213setupCoords(points);214setupFaceIndexes(faces);215return true;216}
217
218bool ViewProviderInspection::setupLines(const Data::ComplexGeoData* data)219{
220std::vector<Base::Vector3d> points;221std::vector<Data::ComplexGeoData::Line> lines;222
223double accuracy = data->getAccuracy();224data->getLines(points, lines, accuracy);225if (lines.empty()) {226return false;227}228
229setupCoords(points);230setupLineIndexes(lines);231return true;232}
233
234bool ViewProviderInspection::setupPoints(const Data::ComplexGeoData* data,235App::PropertyContainer* container)236{
237std::vector<Base::Vector3d> points;238std::vector<Base::Vector3f> normals;239std::vector<Base::Vector3d> normals_d;240double accuracy = data->getAccuracy();241data->getPoints(points, normals_d, accuracy);242if (points.empty()) {243return false;244}245
246normals.reserve(normals_d.size());247std::transform(normals_d.cbegin(),248normals_d.cend(),249std::back_inserter(normals),250[](const Base::Vector3d& p) {251return Base::toVector<float>(p);252});253
254// If getPoints() doesn't deliver normals check a second property255if (normals.empty() && container) {256App::Property* propN = container->getPropertyByName("Normal");257if (propN && propN->isDerivedFrom<Points::PropertyNormalList>()) {258normals = static_cast<Points::PropertyNormalList*>(propN)->getValues();259}260}261
262setupCoords(points);263if (!normals.empty() && normals.size() == points.size()) {264setupNormals(normals);265}266
267this->pcLinkRoot->addChild(this->pcPointStyle);268this->pcLinkRoot->addChild(new SoPointSet());269
270return true;271}
272
273void ViewProviderInspection::setupCoords(const std::vector<Base::Vector3d>& points)274{
275this->pcLinkRoot->addChild(this->pcCoords);276this->pcCoords->point.setNum(points.size());277SbVec3f* pts = this->pcCoords->point.startEditing();278for (size_t i = 0; i < points.size(); i++) {279const Base::Vector3d& p = points[i];280pts[i].setValue((float)p.x, (float)p.y, (float)p.z);281}282this->pcCoords->point.finishEditing();283}
284
285void ViewProviderInspection::setupNormals(const std::vector<Base::Vector3f>& normals)286{
287SoNormal* normalNode = new SoNormal();288normalNode->vector.setNum(normals.size());289SbVec3f* norm = normalNode->vector.startEditing();290
291std::size_t i = 0;292for (const auto& it : normals) {293norm[i++].setValue(it.x, it.y, it.z);294}295
296normalNode->vector.finishEditing();297this->pcLinkRoot->addChild(normalNode);298}
299
300void ViewProviderInspection::setupLineIndexes(const std::vector<Data::ComplexGeoData::Line>& lines)301{
302SoIndexedLineSet* line = new SoIndexedLineSet();303this->pcLinkRoot->addChild(line);304line->coordIndex.setNum(3 * lines.size());305int32_t* indices = line->coordIndex.startEditing();306unsigned long j = 0;307for (const auto& it : lines) {308indices[3 * j + 0] = it.I1;309indices[3 * j + 1] = it.I2;310indices[3 * j + 2] = SO_END_LINE_INDEX;311j++;312}313line->coordIndex.finishEditing();314}
315
316void ViewProviderInspection::setupFaceIndexes(const std::vector<Data::ComplexGeoData::Facet>& faces)317{
318SoIndexedFaceSet* face = new SoIndexedFaceSet();319this->pcLinkRoot->addChild(face);320face->coordIndex.setNum(4 * faces.size());321int32_t* indices = face->coordIndex.startEditing();322unsigned long j = 0;323for (const auto& it : faces) {324indices[4 * j + 0] = it.I1;325indices[4 * j + 1] = it.I2;326indices[4 * j + 2] = it.I3;327indices[4 * j + 3] = SO_END_FACE_INDEX;328j++;329}330face->coordIndex.finishEditing();331}
332
333void ViewProviderInspection::updateData(const App::Property* prop)334{
335// set to the expected size336if (prop->isDerivedFrom<App::PropertyLink>()) {337App::GeoFeature* object =338static_cast<const App::PropertyLink*>(prop)->getValue<App::GeoFeature*>();339const App::PropertyComplexGeoData* propData =340object ? object->getPropertyOfGeometry() : nullptr;341if (propData) {342Gui::coinRemoveAllChildren(this->pcLinkRoot);343
344const Data::ComplexGeoData* data = propData->getComplexData();345if (!setupFaces(data)) {346if (!setupLines(data)) {347setupPoints(data, object);348}349}350}351}352else if (prop->is<Inspection::PropertyDistanceList>()) {353// force an update of the Inventor data nodes354if (this->pcObject) {355App::Property* link = this->pcObject->getPropertyByName("Actual");356if (link) {357updateData(link);358}359setDistances();360}361}362else if (prop->is<App::PropertyFloat>()) {363if (strcmp(prop->getName(), "SearchRadius") == 0) {364float fSearchRadius = ((App::PropertyFloat*)prop)->getValue();365this->search_radius = fSearchRadius;366pcColorBar->setRange(-fSearchRadius, fSearchRadius, 4);367pcColorBar->Notify(0);368}369}370}
371
372SoSeparator* ViewProviderInspection::getFrontRoot() const373{
374return pcColorRoot;375}
376
377void ViewProviderInspection::setDistances()378{
379if (!pcObject) {380return;381}382
383App::Property* pDistances = pcObject->getPropertyByName("Distances");384if (!pDistances) {385SoDebugError::post("ViewProviderInspection::setDistances", "Unknown property 'Distances'");386return;387}388if (pDistances->getTypeId() != Inspection::PropertyDistanceList::getClassTypeId()) {389SoDebugError::post(390"ViewProviderInspection::setDistances",391"Property 'Distances' has type %s (Inspection::PropertyDistanceList was expected)",392pDistances->getTypeId().getName());393return;394}395
396// distance values397const std::vector<float>& fValues =398static_cast<Inspection::PropertyDistanceList*>(pDistances)->getValues();399if ((int)fValues.size() != this->pcCoords->point.getNum()) {400pcMatBinding->value = SoMaterialBinding::OVERALL;401return;402}403
404if (pcColorMat->diffuseColor.getNum() != static_cast<int>(fValues.size())) {405pcColorMat->diffuseColor.setNum(static_cast<int>(fValues.size()));406}407if (pcColorMat->transparency.getNum() != static_cast<int>(fValues.size())) {408pcColorMat->transparency.setNum(static_cast<int>(fValues.size()));409}410
411SbColor* cols = pcColorMat->diffuseColor.startEditing();412float* tran = pcColorMat->transparency.startEditing();413
414unsigned long j = 0;415for (std::vector<float>::const_iterator jt = fValues.begin(); jt != fValues.end(); ++jt, j++) {416App::Color col = pcColorBar->getColor(*jt);417cols[j] = SbColor(col.r, col.g, col.b);418if (pcColorBar->isVisible(*jt)) {419tran[j] = 0.0f;420}421else {422tran[j] = 0.8f;423}424}425
426pcColorMat->diffuseColor.finishEditing();427pcColorMat->transparency.finishEditing();428pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;429}
430
431QIcon ViewProviderInspection::getIcon() const432{
433// Get the icon of the view provider to the associated feature434QIcon px = inherited::getIcon();435App::Property* pActual = pcObject->getPropertyByName("Actual");436if (pActual && pActual->isDerivedFrom<App::PropertyLink>()) {437App::DocumentObject* docobj = ((App::PropertyLink*)pActual)->getValue();438if (docobj) {439Gui::Document* doc = Gui::Application::Instance->getDocument(docobj->getDocument());440Gui::ViewProvider* view = doc->getViewProvider(docobj);441px = view->getIcon();442}443}444
445return px;446}
447
448void ViewProviderInspection::setDisplayMode(const char* ModeName)449{
450if (strcmp("Visual Inspection", ModeName) == 0) {451setDistances();452setDisplayMaskMode("ColorShaded");453}454
455inherited::setDisplayMode(ModeName);456}
457
458std::vector<std::string> ViewProviderInspection::getDisplayModes() const459{
460// add modes461std::vector<std::string> StrList;462StrList.emplace_back("Visual Inspection");463return StrList;464}
465
466void ViewProviderInspection::OnChange(Base::Subject<int>& /*rCaller*/, int /*rcReason*/)467{
468setActiveMode();469}
470
471namespace InspectionGui472{
473// Proxy class that receives an asynchronous custom event
474class ViewProviderProxyObject: public QObject475{
476public:477explicit ViewProviderProxyObject(QWidget* w)478: QObject(nullptr)479, widget(w)480{}481~ViewProviderProxyObject() override = default;482void customEvent(QEvent*) override483{484if (!widget.isNull()) {485QList<Gui::Flag*> flags = widget->findChildren<Gui::Flag*>();486if (!flags.isEmpty()) {487int ret =488QMessageBox::question(Gui::getMainWindow(),489QObject::tr("Remove annotations"),490QObject::tr("Do you want to remove all annotations?"),491QMessageBox::Yes,492QMessageBox::No);493if (ret == QMessageBox::Yes) {494for (auto it : flags) {495it->deleteLater();496}497}498}499}500
501this->deleteLater();502}503
504static void505addFlag(Gui::View3DInventorViewer* view, const QString& text, const SoPickedPoint* point)506{507Gui::Flag* flag = new Gui::Flag;508QPalette p;509p.setColor(QPalette::Window, QColor(85, 0, 127));510p.setColor(QPalette::Text, QColor(220, 220, 220));511flag->setPalette(p);512flag->setText(text);513flag->setOrigin(point->getPoint());514Gui::GLFlagWindow* flags = nullptr;515std::list<Gui::GLGraphicsItem*> glItems =516view->getGraphicsItemsOfType(Gui::GLFlagWindow::getClassTypeId());517if (glItems.empty()) {518flags = new Gui::GLFlagWindow(view);519view->addGraphicsItem(flags);520}521else {522flags = static_cast<Gui::GLFlagWindow*>(glItems.front());523}524flags->addFlag(flag, Gui::FlagLayout::BottomLeft);525}526
527private:528QPointer<QWidget> widget;529};530} // namespace InspectionGui531
532void ViewProviderInspection::inspectCallback(void* ud, SoEventCallback* n)533{
534Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(n->getUserData());535const SoEvent* ev = n->getEvent();536if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {537const SoMouseButtonEvent* mbe = static_cast<const SoMouseButtonEvent*>(ev);538
539// Mark all incoming mouse button events as handled, especially, to deactivate the selection540// node541n->getAction()->setHandled();542n->setHandled();543if (mbe->getButton() == SoMouseButtonEvent::BUTTON2544&& mbe->getState() == SoButtonEvent::UP) {545n->setHandled();546// context-menu547QMenu menu;548QAction* fl = menu.addAction(QObject::tr("Annotation"));549fl->setCheckable(true);550fl->setChecked(addflag);551QAction* cl = menu.addAction(QObject::tr("Leave info mode"));552QAction* id = menu.exec(QCursor::pos());553if (fl == id) {554addflag = fl->isChecked();555}556else if (cl == id) {557// post an event to a proxy object to make sure to avoid problems558// when opening a modal dialog559QApplication::postEvent(new ViewProviderProxyObject(view->getGLWidget()),560new QEvent(QEvent::User));561view->setEditing(false);562view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));563view->setRedirectToSceneGraph(false);564view->setRedirectToSceneGraphEnabled(false);565view->setSelectionEnabled(true);566view->removeEventCallback(SoButtonEvent::getClassTypeId(), inspectCallback, ud);567}568}569else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1570&& mbe->getState() == SoButtonEvent::UP) {571const SoPickedPoint* point = n->getPickedPoint();572if (!point) {573Base::Console().Message("No point picked.\n");574return;575}576
577n->setHandled();578
579// check if we have picked one a node of the view provider we are insterested in580Gui::ViewProvider* vp = view->getViewProviderByPathFromTail(point->getPath());581if (vp && vp->isDerivedFrom<ViewProviderInspection>()) {582ViewProviderInspection* that = static_cast<ViewProviderInspection*>(vp);583QString info = that->inspectDistance(point);584Gui::getMainWindow()->setPaneText(1, info);585if (addflag) {586ViewProviderProxyObject::addFlag(view, info, point);587}588else {589Gui::ToolTip::showText(QCursor::pos(), info);590}591}592else {593// the nearest picked point was not part of the view provider594SoRayPickAction action(view->getSoRenderManager()->getViewportRegion());595action.setPickAll(true);596action.setPoint(mbe->getPosition());597action.apply(view->getSoRenderManager()->getSceneGraph());598
599const SoPickedPointList& pps = action.getPickedPointList();600for (int i = 0; i < pps.getLength(); ++i) {601const SoPickedPoint* point = pps[i];602vp = view->getViewProviderByPathFromTail(point->getPath());603if (vp && vp->isDerivedFrom<ViewProviderInspection>()) {604ViewProviderInspection* self = static_cast<ViewProviderInspection*>(vp);605QString info = self->inspectDistance(point);606Gui::getMainWindow()->setPaneText(1, info);607if (addflag) {608ViewProviderProxyObject::addFlag(view, info, point);609}610else {611Gui::ToolTip::showText(QCursor::pos(), info);612}613break;614}615}616}617}618}619// toggle between inspection and navigation mode620else if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {621const SoKeyboardEvent* const ke = static_cast<const SoKeyboardEvent*>(ev);622if (ke->getState() == SoButtonEvent::DOWN && ke->getKey() == SoKeyboardEvent::ESCAPE) {623SbBool toggle = view->isRedirectedToSceneGraph();624view->setRedirectToSceneGraph(!toggle);625n->setHandled();626}627}628}
629
630namespace InspectionGui631{
632float calcArea(const SbVec3f& v1, const SbVec3f& v2, const SbVec3f& v3)633{
634SbVec3f a = v2 - v1;635SbVec3f b = v3 - v1;636return a.cross(b).length() / 2.0f;637}
638
639bool calcWeights(const SbVec3f& v1,640const SbVec3f& v2,641const SbVec3f& v3,642const SbVec3f& p,643float& w0,644float& w1,645float& w2)646{
647float fAreaABC = calcArea(v1, v2, v3);648float fAreaPBC = calcArea(p, v2, v3);649float fAreaPCA = calcArea(p, v3, v1);650float fAreaPAB = calcArea(p, v1, v2);651
652w0 = fAreaPBC / fAreaABC;653w1 = fAreaPCA / fAreaABC;654w2 = fAreaPAB / fAreaABC;655
656return fabs(w0 + w1 + w2 - 1.0f) < 0.001f;657}
658} // namespace InspectionGui659
660QString ViewProviderInspection::inspectDistance(const SoPickedPoint* pp) const661{
662QString info;663const SoDetail* detail = pp->getDetail(pp->getPath()->getTail());664if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {665// get the distances of the three points of the picked facet666const SoFaceDetail* facedetail = static_cast<const SoFaceDetail*>(detail);667App::Property* pDistance = this->pcObject->getPropertyByName("Distances");668if (pDistance && pDistance->is<Inspection::PropertyDistanceList>()) {669Inspection::PropertyDistanceList* dist =670static_cast<Inspection::PropertyDistanceList*>(pDistance);671int index1 = facedetail->getPoint(0)->getCoordinateIndex();672int index2 = facedetail->getPoint(1)->getCoordinateIndex();673int index3 = facedetail->getPoint(2)->getCoordinateIndex();674float fVal1 = (*dist)[index1];675float fVal2 = (*dist)[index2];676float fVal3 = (*dist)[index3];677
678App::Property* pActual = this->pcObject->getPropertyByName("Actual");679if (pActual && pActual->isDerivedFrom<App::PropertyLink>()) {680float fSearchRadius = this->search_radius;681if (fVal1 > fSearchRadius || fVal2 > fSearchRadius || fVal3 > fSearchRadius) {682info = QObject::tr("Distance: > %1").arg(fSearchRadius);683}684else if (fVal1 < -fSearchRadius || fVal2 < -fSearchRadius685|| fVal3 < -fSearchRadius) {686info = QObject::tr("Distance: < %1").arg(-fSearchRadius);687}688else {689SoSearchAction searchAction;690searchAction.setType(SoCoordinate3::getClassTypeId());691searchAction.setInterest(SoSearchAction::FIRST);692searchAction.apply(pp->getPath()->getNodeFromTail(1));693SoPath* selectionPath = searchAction.getPath();694
695if (selectionPath) {696SoCoordinate3* coords =697static_cast<SoCoordinate3*>(selectionPath->getTail());698const SbVec3f& v1 = coords->point[index1];699const SbVec3f& v2 = coords->point[index2];700const SbVec3f& v3 = coords->point[index3];701const SbVec3f& p = pp->getObjectPoint();702// get the weights703float w1, w2, w3;704calcWeights(v1, v2, v3, p, w1, w2, w3);705float fVal = w1 * fVal1 + w2 * fVal2 + w3 * fVal3;706info = QObject::tr("Distance: %1").arg(fVal);707}708}709}710}711}712else if (detail && detail->getTypeId() == SoPointDetail::getClassTypeId()) {713// safe downward cast, know the type714const SoPointDetail* pointdetail = static_cast<const SoPointDetail*>(detail);715
716// get the distance of the picked point717int index = pointdetail->getCoordinateIndex();718App::Property* prop = this->pcObject->getPropertyByName("Distances");719if (prop && prop->is<Inspection::PropertyDistanceList>()) {720Inspection::PropertyDistanceList* dist =721static_cast<Inspection::PropertyDistanceList*>(prop);722float fVal = (*dist)[index];723info = QObject::tr("Distance: %1").arg(fVal);724}725}726
727return info;728}
729
730// -----------------------------------------------
731
732PROPERTY_SOURCE(InspectionGui::ViewProviderInspectionGroup, Gui::ViewProviderDocumentObjectGroup)733
734
735/**
736* Creates the view provider for an object group.
737*/
738ViewProviderInspectionGroup::ViewProviderInspectionGroup() = default;739
740ViewProviderInspectionGroup::~ViewProviderInspectionGroup() = default;741
742/**
743* Returns the pixmap for the opened list item.
744*/
745QIcon ViewProviderInspectionGroup::getIcon() const746{
747// clang-format off748static const char * const ScanViewOpen[]={749"16 16 10 1",750"c c #000000",751". c None",752"h c #808000",753"# c #808080",754"a c #ffff00",755"r c #ff0000",756"o c #ffff00",757"g c #00ff00",758"t c #00ffff",759"b c #0000ff",760"................",761"...#####........",762"..#hhhhh#.......",763".#hhhhhhh######.",764".#hhhhhhhhhhhh#c",765".#hhhhhhhhhhhh#c",766".#hhhhhhhhhhhh#c",767"#############h#c",768"#aaaaaaaaaa##h#c",769"#aarroggtbbac##c",770".#arroggtbbaac#c",771".#aarroggtbbac#c",772"..#aaaaaaaaaa#cc",773"..#############c",774"...ccccccccccccc",775"................"};776
777static const char * const ScanViewClosed[] = {778"16 16 9 1",779"c c #000000",780". c None",781"# c #808080",782"a c #ffff00",783"r c #ff0000",784"o c #ffff00",785"g c #00ff00",786"t c #00ffff",787"b c #0000ff",788"................",789"...#####........",790"..#aaaaa#.......",791".#aaaaaaa######.",792".#aaaaaaaaaaaa#c",793".#aarroggtbbaa#c",794".#aarroggtbbaa#c",795".#aarroggtbbaa#c",796".#aarroggtbbaa#c",797".#aarroggtbbaa#c",798".#aarroggtbbaa#c",799".#aarroggtbbaa#c",800".#aaaaaaaaaaaa#c",801".##############c",802"..cccccccccccccc",803"................"};804// clang-format on805
806QIcon groupIcon;807groupIcon.addPixmap(QPixmap(ScanViewClosed), QIcon::Normal, QIcon::Off);808groupIcon.addPixmap(QPixmap(ScanViewOpen), QIcon::Normal, QIcon::On);809return groupIcon;810}
811