compute signed distances of points to shape, show results of visual inspection for point clouds

This commit is contained in:
wmayer 2017-01-03 17:02:50 +01:00
parent 7943ce4ce4
commit 0ad93186b5
3 changed files with 104 additions and 36 deletions

View File

@ -25,6 +25,9 @@
#include <gp_Pnt.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepGProp_Face.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <QEventLoop>
@ -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;
}

View File

@ -151,6 +151,7 @@ public:
private:
BRepExtrema_DistShapeShape* distss;
const TopoDS_Shape& _rShape;
bool isSolid;
};
class InspectionExport PropertyDistanceList: public App::PropertyLists

View File

@ -41,6 +41,7 @@
#include <Inventor/nodes/SoShapeHints.h>
#include <Inventor/nodes/SoOrthographicCamera.h>
#include <Inventor/nodes/SoMaterialBinding.h>
#include <Inventor/nodes/SoNormal.h>
#include <Inventor/errors/SoDebugError.h>
#include <Base/Exception.h>
@ -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<Base::Vector3d> points;
std::vector<Base::Vector3d> normals;
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
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<App::PropertyComplexGeoData*>(prop)->getComplexData();
const Data::ComplexGeoData* data = static_cast<App::PropertyComplexGeoData*>(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<App::PropertyComplexGeoData*>(prop)->getComplexData();
const Data::ComplexGeoData* data = static_cast<App::PropertyComplexGeoData*>(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<App::PropertyComplexGeoData*>(prop)->getComplexData();
const Data::ComplexGeoData* data = static_cast<App::PropertyComplexGeoData*>(prop)->getComplexData();
data->getPoints(points, normals, accuracy);
}
}
if (data) {
this->pcLinkRoot->removeAllChildren();
std::vector<Base::Vector3d> points;
std::vector<Data::ComplexGeoData::Facet> 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<Data::ComplexGeoData::Facet>::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<Data::ComplexGeoData::Facet>::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<Base::Vector3d>::const_iterator it = normals.begin(); it != normals.end(); ++it) {
norm[i++].setValue(static_cast<float>(it->x),
static_cast<float>(it->y),
static_cast<float>(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());
}
}
}