From 48aafc3f8b36ded8dc80fbf83ec608898ed16d4a Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 15 Sep 2022 11:46:20 +0200 Subject: [PATCH] Inspection: support display of lines, avoid explicit type checks --- src/Mod/Inspection/App/InspectionFeature.cpp | 12 +- .../Inspection/Gui/ViewProviderInspection.cpp | 223 +++++++++++------- .../Inspection/Gui/ViewProviderInspection.h | 10 + src/Mod/Part/App/TopoShape.cpp | 4 +- 4 files changed, 157 insertions(+), 92 deletions(-) diff --git a/src/Mod/Inspection/App/InspectionFeature.cpp b/src/Mod/Inspection/App/InspectionFeature.cpp index 8acfa1f2a4..72d9aa15f2 100644 --- a/src/Mod/Inspection/App/InspectionFeature.cpp +++ b/src/Mod/Inspection/App/InspectionFeature.cpp @@ -116,14 +116,18 @@ void InspectActualShape::fetchPoints(double deflection) TopTools_IndexedMapOfShape mapOfShapes; TopExp::MapShapes(_rShape.getShape(), TopAbs_FACE, mapOfShapes); if (!mapOfShapes.IsEmpty()) { - std::vector f; - _rShape.getFaces(points, f, deflection); + std::vector faces; + _rShape.getFaces(points, faces, deflection); } else { TopExp::MapShapes(_rShape.getShape(), TopAbs_EDGE, mapOfShapes); if (!mapOfShapes.IsEmpty()) { - std::vector n; - _rShape.getPoints(points, n, deflection); + std::vector lines; + _rShape.getLines(points, lines, deflection); + } + else { + std::vector normals; + _rShape.getPoints(points, normals, deflection); } } } diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp index 0ed7208875..00c6e4501a 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -182,101 +183,149 @@ void ViewProviderInspection::attach(App::DocumentObject *pcFeat) pcColorRoot->addChild(pcColorBar); } +bool ViewProviderInspection::setupFaces(const Data::ComplexGeoData* data) +{ + std::vector points; + std::vector 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 points; + std::vector 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 points; + std::vector normals; + std::vector 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(p); + }); + + // If getPoints() doesn't deliver normals check a second property + if (normals.empty() && container) { + App::Property* propN = container->getPropertyByName("Normal"); + if (propN && propN->getTypeId().isDerivedFrom(Points::PropertyNormalList::getClassTypeId())) { + normals = static_cast(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& 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& normals) +{ + SoNormal* normalNode = new SoNormal(); + normalNode->vector.setNum(normals.size()); + SbVec3f* norm = normalNode->vector.startEditing(); + + std::size_t i=0; + for (std::vector::const_iterator it = normals.begin(); it != normals.end(); ++it) { + norm[i++].setValue(it->x, it->y, it->z); + } + + normalNode->vector.finishEditing(); + this->pcLinkRoot->addChild(normalNode); +} + +void ViewProviderInspection::setupLineIndexes(const std::vector& 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& 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->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId())) { App::GeoFeature* object = static_cast(prop)->getValue(); - if (object) { - double accuracy = 0.0; - Base::Type meshId = Base::Type::fromName("Mesh::Feature"); - Base::Type shapeId = Base::Type::fromName("Part::Feature"); - Base::Type pointId = Base::Type::fromName("Points::Feature"); - Base::Type propId = App::PropertyComplexGeoData::getClassTypeId(); - - std::vector points; - std::vector normals; - std::vector faces; - - // set the Distance property to the correct size to sync size of material node with number - // of vertices/points of the referenced geometry - if (object->getTypeId().isDerivedFrom(meshId)) { - App::Property* propM = object->getPropertyByName("Mesh"); - if (propM && propM->getTypeId().isDerivedFrom(propId)) { - const Data::ComplexGeoData* data = static_cast(propM)->getComplexData(); - data->getFaces(points, faces, accuracy); - } - } - else if (object->getTypeId().isDerivedFrom(shapeId)) { - App::Property* propS = object->getPropertyByName("Shape"); - if (propS && propS->getTypeId().isDerivedFrom(propId)) { - const Data::ComplexGeoData* data = static_cast(propS)->getComplexData(); - accuracy = data->getAccuracy(); - data->getFaces(points, faces, accuracy); - if (points.empty()) { - std::vector normals_d; - data->getPoints(points, normals_d, accuracy); - normals.reserve(normals_d.size()); - std::transform(normals_d.cbegin(), normals_d.cend(), std::back_inserter(normals), [](const Base::Vector3d& p){ - return Base::toVector(p); - }); - } - } - } - else if (object->getTypeId().isDerivedFrom(pointId)) { - App::Property* propP = object->getPropertyByName("Points"); - if (propP && propP->getTypeId().isDerivedFrom(propId)) { - const Data::ComplexGeoData* data = static_cast(propP)->getComplexData(); - std::vector normals; - data->getPoints(points, normals, accuracy); - } - App::Property* propN = object->getPropertyByName("Normal"); - if (propN && propN->getTypeId().isDerivedFrom(Points::PropertyNormalList::getClassTypeId())) { - normals = static_cast(propN)->getValues(); - } - } - + const App::PropertyComplexGeoData* propData = object ? object->getPropertyOfGeometry() : nullptr; + if (propData) { Gui::coinRemoveAllChildren(this->pcLinkRoot); - 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(); - if (!faces.empty()) { - SoIndexedFaceSet* face = new SoIndexedFaceSet(); - this->pcLinkRoot->addChild(face); - face->coordIndex.setNum(4*faces.size()); - int32_t* indices = face->coordIndex.startEditing(); - unsigned long j=0; - std::vector::iterator it; - for (it = faces.begin(); it != faces.end(); ++it,j++) { - 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; + const Data::ComplexGeoData* data = propData->getComplexData(); + if (!setupFaces(data)) { + if (!setupLines(data)) { + setupPoints(data, object); } - face->coordIndex.finishEditing(); - } - else { - if (!normals.empty() && normals.size() == points.size()) { - SoNormal* normalNode = new SoNormal(); - normalNode->vector.setNum(normals.size()); - SbVec3f* norm = normalNode->vector.startEditing(); - - std::size_t i=0; - for (std::vector::const_iterator it = normals.begin(); it != normals.end(); ++it) { - norm[i++].setValue(it->x, it->y, it->z); - } - - normalNode->vector.finishEditing(); - this->pcLinkRoot->addChild(normalNode); - } - this->pcLinkRoot->addChild(this->pcPointStyle); - this->pcLinkRoot->addChild(new SoPointSet()); } } } diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.h b/src/Mod/Inspection/Gui/ViewProviderInspection.h index 61d2fe1c87..b8cc3189a1 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.h +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.h @@ -25,6 +25,7 @@ #define INSPECTIOGUI_VIEWPROVIDERINSPECTION_H #include +#include #include #include @@ -82,6 +83,15 @@ protected: void setDistances(); QString inspectDistance(const SoPickedPoint* pp) const; +private: + bool setupFaces(const Data::ComplexGeoData*); + bool setupLines(const Data::ComplexGeoData*); + bool setupPoints(const Data::ComplexGeoData*, App::PropertyContainer* container); + void setupCoords(const std::vector&); + void setupNormals(const std::vector&); + void setupLineIndexes(const std::vector&); + void setupFaceIndexes(const std::vector&); + protected: SoMaterial * pcColorMat; SoMaterialBinding* pcMatBinding; diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 72f8807583..babf0d76dc 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -3491,7 +3491,9 @@ double TopoShape::getAccuracy() const { double deviation = 0.2; Base::BoundBox3d bbox = getBoundBox(); - return ((bbox.LengthX() + bbox.LengthY() + bbox.LengthZ())/300.0 * deviation); + if (bbox.IsValid()) + return ((bbox.LengthX() + bbox.LengthY() + bbox.LengthZ())/300.0 * deviation); + return ComplexGeoData::getAccuracy(); } void TopoShape::getFaces(std::vector &aPoints,