From 0ad93186b59c1e695ae709665876ac50c5fbe66e Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 3 Jan 2017 17:02:50 +0100 Subject: [PATCH] compute signed distances of points to shape, show results of visual inspection for point clouds --- src/Mod/Inspection/App/InspectionFeature.cpp | 57 ++++++++++++- src/Mod/Inspection/App/InspectionFeature.h | 1 + .../Inspection/Gui/ViewProviderInspection.cpp | 82 +++++++++++-------- 3 files changed, 104 insertions(+), 36 deletions(-) diff --git a/src/Mod/Inspection/App/InspectionFeature.cpp b/src/Mod/Inspection/App/InspectionFeature.cpp index 4aac4d76e..18e789f1f 100644 --- a/src/Mod/Inspection/App/InspectionFeature.cpp +++ b/src/Mod/Inspection/App/InspectionFeature.cpp @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include @@ -419,10 +422,24 @@ float InspectNominalPoints::getDistance(const Base::Vector3f& point) // ---------------------------------------------------------------- -InspectNominalShape::InspectNominalShape(const TopoDS_Shape& shape, float /*radius*/) : _rShape(shape) +InspectNominalShape::InspectNominalShape(const TopoDS_Shape& shape, float /*radius*/) + : _rShape(shape) + , isSolid(false) { distss = new BRepExtrema_DistShapeShape(); distss->LoadS1(_rShape); + + // When having a solid then use its shell because otherwise the distance + // for inner points will always be zero + if (!_rShape.IsNull() && _rShape.ShapeType() == TopAbs_SOLID) { + TopExp_Explorer xp; + xp.Init(_rShape, TopAbs_SHELL); + if (xp.More()) { + distss->LoadS1(xp.Current()); + isSolid = true; + } + + } //distss->SetDeflection(radius); } @@ -433,11 +450,45 @@ InspectNominalShape::~InspectNominalShape() float InspectNominalShape::getDistance(const Base::Vector3f& point) { - BRepBuilderAPI_MakeVertex mkVert(gp_Pnt(point.x,point.y,point.z)); + gp_Pnt pnt3d(point.x,point.y,point.z); + BRepBuilderAPI_MakeVertex mkVert(pnt3d); distss->LoadS2(mkVert.Vertex()); + float fMinDist=FLT_MAX; - if (distss->Perform() && distss->NbSolution() > 0) + if (distss->Perform() && distss->NbSolution() > 0) { fMinDist = (float)distss->Value(); + // the shape is a solid, check if the vertex is inside + if (isSolid) { + const Standard_Real tol = 0.001; + BRepClass3d_SolidClassifier classifier(_rShape); + classifier.Perform(pnt3d, tol); + if (classifier.State() == TopAbs_IN) { + fMinDist = -fMinDist; + } + + } + else if (fMinDist > 0) { + // check if the distance was compued from a face + for (Standard_Integer index = 1; index <= distss->NbSolution(); index++) { + if (distss->SupportTypeShape1(index) == BRepExtrema_IsInFace) { + TopoDS_Shape face = distss->SupportOnShape1(index); + Standard_Real u, v; + distss->ParOnFaceS1(index, u, v); + //gp_Pnt pnt = distss->PointOnShape1(index); + BRepGProp_Face props(TopoDS::Face(face)); + gp_Vec normal; + gp_Pnt center; + props.Normal(u, v, center, normal); + gp_Vec dir(center, pnt3d); + Standard_Real scalar = normal.Dot(dir); + if (scalar < 0) { + fMinDist = -fMinDist; + } + break; + } + } + } + } return fMinDist; } diff --git a/src/Mod/Inspection/App/InspectionFeature.h b/src/Mod/Inspection/App/InspectionFeature.h index d859b7b80..f2fd7761c 100644 --- a/src/Mod/Inspection/App/InspectionFeature.h +++ b/src/Mod/Inspection/App/InspectionFeature.h @@ -151,6 +151,7 @@ public: private: BRepExtrema_DistShapeShape* distss; const TopoDS_Shape& _rShape; + bool isSolid; }; class InspectionExport PropertyDistanceList: public App::PropertyLists diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp index f8a644e34..9a6d0dd94 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -191,68 +192,83 @@ void ViewProviderInspection::updateData(const App::Property* prop) 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 - const Data::ComplexGeoData* data = 0; if (object->getTypeId().isDerivedFrom(meshId)) { App::Property* prop = object->getPropertyByName("Mesh"); if (prop && prop->getTypeId().isDerivedFrom(propId)) { - data = static_cast(prop)->getComplexData(); + const Data::ComplexGeoData* data = static_cast(prop)->getComplexData(); + data->getFaces(points, faces, accuracy); } } else if (object->getTypeId().isDerivedFrom(shapeId)) { App::Property* prop = object->getPropertyByName("Shape"); if (prop && prop->getTypeId().isDerivedFrom(propId)) { - data = static_cast(prop)->getComplexData(); + const Data::ComplexGeoData* data = static_cast(prop)->getComplexData(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/Mod/Part"); float deviation = hGrp->GetFloat("MeshDeviation",0.2); Base::BoundBox3d bbox = data->getBoundBox(); accuracy = (float)((bbox.LengthX() + bbox.LengthY() + bbox.LengthZ())/300.0 * deviation); + data->getFaces(points, faces, accuracy); } } else if (object->getTypeId().isDerivedFrom(pointId)) { App::Property* prop = object->getPropertyByName("Points"); if (prop && prop->getTypeId().isDerivedFrom(propId)) { - data = static_cast(prop)->getComplexData(); + const Data::ComplexGeoData* data = static_cast(prop)->getComplexData(); + data->getPoints(points, normals, accuracy); } } - if (data) { - this->pcLinkRoot->removeAllChildren(); - std::vector points; - std::vector faces; - data->getFaces(points, faces, accuracy); + this->pcLinkRoot->removeAllChildren(); + 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(); - 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); + 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; } - this->pcCoords->point.finishEditing(); + 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(); - 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; + std::size_t i=0; + for (std::vector::const_iterator it = normals.begin(); it != normals.end(); ++it) { + norm[i++].setValue(static_cast(it->x), + static_cast(it->y), + static_cast(it->z)); } - face->coordIndex.finishEditing(); - } - else { - this->pcLinkRoot->addChild(this->pcPointStyle); - this->pcLinkRoot->addChild(new SoPointSet()); + + normalNode->vector.finishEditing(); + this->pcLinkRoot->addChild(normalNode); } + this->pcLinkRoot->addChild(this->pcPointStyle); + this->pcLinkRoot->addChild(new SoPointSet()); } } }