Skip to content

Commit

Permalink
+ get also back normals from MeshObject::getPoints
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Mar 4, 2016
1 parent 0ea6a2e commit 70f5867
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 73 deletions.
20 changes: 19 additions & 1 deletion src/Mod/Mesh/App/Mesh.cpp
Expand Up @@ -256,10 +256,28 @@ void MeshObject::getPoints(std::vector<Base::Vector3d> &Points,
std::vector<Base::Vector3d> &Normals,
float Accuracy, uint16_t flags) const
{
Base::Matrix4D mat = _Mtrx;

unsigned long ctpoints = _kernel.CountPoints();
Points.reserve(ctpoints);
for (unsigned long i=0; i<ctpoints; i++) {
Points.push_back(this->getPoint(i));
Base::Vector3f vertf = _kernel.GetPoint(i);
Base::Vector3d vertd(vertf.x, vertf.y, vertf.z);
vertd = mat * vertd;
Points.push_back(vertd);
}

// nullify translation part
mat[0][3] = 0.0;
mat[1][3] = 0.0;
mat[2][3] = 0.0;
Normals.reserve(ctpoints);
MeshCore::MeshRefNormalToPoints ptNormals(_kernel);
for (unsigned long i=0; i<ctpoints; i++) {
Base::Vector3f normalf = ptNormals[i];
Base::Vector3d normald(normalf.x, normalf.y, normalf.z);
normald = mat * normald;
Normals.push_back(normald);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/Mod/Points/App/Points.cpp
Expand Up @@ -193,8 +193,9 @@ void PointKernel::save(std::ostream& out) const
}
}

void PointKernel::getFaces(std::vector<Base::Vector3d> &Points,std::vector<Facet> &Topo,
float Accuracy, uint16_t flags) const
void PointKernel::getPoints(std::vector<Base::Vector3d> &Points,
std::vector<Base::Vector3d> &Normals,
float Accuracy, uint16_t flags) const
{
unsigned long ctpoints = _Points.size();
Points.reserve(ctpoints);
Expand Down
5 changes: 3 additions & 2 deletions src/Mod/Points/App/Points.h
Expand Up @@ -85,9 +85,10 @@ class PointsExport PointKernel : public Data::ComplexGeoData
{ this->_Points = pts; }
void swap(std::vector<value_type>& pts)
{ this->_Points.swap(pts); }
void getFaces(std::vector<Base::Vector3d> &Points,std::vector<Facet> &Topo,
float Accuracy, uint16_t flags=0) const;

virtual void getPoints(std::vector<Base::Vector3d> &Points,
std::vector<Base::Vector3d> &Normals,
float Accuracy, uint16_t flags=0) const;
virtual void transformGeometry(const Base::Matrix4D &rclMat);
virtual Base::BoundBox3d getBoundBox(void)const;

Expand Down
137 changes: 69 additions & 68 deletions src/Mod/ReverseEngineering/Gui/Command.cpp
Expand Up @@ -101,78 +101,79 @@ void CmdApproxPlane::activated(int iMsg)
{
std::vector<App::GeoFeature*> obj = Gui::Selection().getObjectsOfType<App::GeoFeature>();
for (std::vector<App::GeoFeature*>::iterator it = obj.begin(); it != obj.end(); ++it) {
std::map<std::string, App::Property*> Map;
(*it)->getPropertyMap(Map);
for (std::map<std::string, App::Property*>::iterator jt = Map.begin(); jt != Map.end(); ++jt) {
if (jt->second->getTypeId().isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) {
std::vector<Base::Vector3d> aPoints;
std::vector<Data::ComplexGeoData::Facet> aTopo;
const Data::ComplexGeoData* data = static_cast<App::PropertyComplexGeoData*>(jt->second)->getComplexData();
if (!data)
continue;

data->getFaces(aPoints, aTopo,0.01f);

// get a reference normal for the plane fit
Base::Vector3f refNormal(0,0,0);
if (!aTopo.empty()) {
Data::ComplexGeoData::Facet f = aTopo.front();
Base::Vector3d v1 = aPoints[f.I2] - aPoints[f.I1];
Base::Vector3d v2 = aPoints[f.I3] - aPoints[f.I1];
refNormal = Base::convertTo<Base::Vector3f>(v1 % v2);
std::vector<Base::Vector3d> aPoints;
std::vector<Base::Vector3d> aNormals;

std::vector<App::Property*> List;
(*it)->getPropertyList(List);
for (std::vector<App::Property*>::iterator jt = List.begin(); jt != List.end(); ++jt) {
if ((*jt)->getTypeId().isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) {
const Data::ComplexGeoData* data = static_cast<App::PropertyComplexGeoData*>(*jt)->getComplexData();
if (data) {
data->getPoints(aPoints, aNormals, 0.01f);
if (!aPoints.empty())
break;
}
}
}

std::vector<Base::Vector3f> aData;
aData.reserve(aPoints.size());
for (std::vector<Base::Vector3d>::iterator jt = aPoints.begin(); jt != aPoints.end(); ++jt)
aData.push_back(Base::toVector<float>(*jt));
MeshCore::PlaneFit fit;
fit.AddPoints(aData);
float sigma = fit.Fit();
Base::Vector3f base = fit.GetBase();
Base::Vector3f dirU = fit.GetDirU();
Base::Vector3f dirV = fit.GetDirV();
Base::Vector3f norm = fit.GetNormal();

// if the dot product of the reference with the plane normal is negative
// a flip must be done
if (refNormal * norm < 0) {
norm = -norm;
dirU = -dirU;
}
if (!aPoints.empty()) {
// get a reference normal for the plane fit
Base::Vector3f refNormal(0,0,0);
if (!aNormals.empty()) {
refNormal = Base::convertTo<Base::Vector3f>(aNormals.front());
}

float width, length;
fit.Dimension(width, length);

// move to the corner point
base = base - (0.5f * length * dirU + 0.5f * width * dirV);

Base::CoordinateSystem cs;
cs.setPosition(Base::convertTo<Base::Vector3d>(base));
cs.setAxes(Base::convertTo<Base::Vector3d>(norm),
Base::convertTo<Base::Vector3d>(dirU));
Base::Placement pm = Base::CoordinateSystem().displacement(cs);
double q0, q1, q2, q3;
pm.getRotation().getValue(q0, q1, q2, q3);

Base::Console().Log("RMS value for plane fit with %lu points: %.4f\n", aData.size(), sigma);
Base::Console().Log(" Plane base(%.4f, %.4f, %.4f)\n", base.x, base.y, base.z);
Base::Console().Log(" Plane normal(%.4f, %.4f, %.4f)\n", norm.x, norm.y, norm.z);

std::stringstream str;
str << "from FreeCAD import Base" << std::endl;
str << "App.ActiveDocument.addObject('Part::Plane','Plane_fit')" << std::endl;
str << "App.ActiveDocument.ActiveObject.Length = " << length << std::endl;
str << "App.ActiveDocument.ActiveObject.Width = " << width << std::endl;
str << "App.ActiveDocument.ActiveObject.Placement = Base.Placement("
<< "Base.Vector(" << base.x << "," << base.y << "," << base.z << "),"
<< "Base.Rotation(" << q0 << "," << q1 << "," << q2 << "," << q3 << "))" << std::endl;

openCommand("Fit plane");
doCommand(Gui::Command::Doc, str.str().c_str());
commitCommand();
updateActive();
std::vector<Base::Vector3f> aData;
aData.reserve(aPoints.size());
for (std::vector<Base::Vector3d>::iterator jt = aPoints.begin(); jt != aPoints.end(); ++jt)
aData.push_back(Base::toVector<float>(*jt));
MeshCore::PlaneFit fit;
fit.AddPoints(aData);
float sigma = fit.Fit();
Base::Vector3f base = fit.GetBase();
Base::Vector3f dirU = fit.GetDirU();
Base::Vector3f dirV = fit.GetDirV();
Base::Vector3f norm = fit.GetNormal();

// if the dot product of the reference with the plane normal is negative
// a flip must be done
if (refNormal * norm < 0) {
norm = -norm;
dirU = -dirU;
}

float width, length;
fit.Dimension(width, length);

// move to the corner point
base = base - (0.5f * length * dirU + 0.5f * width * dirV);

Base::CoordinateSystem cs;
cs.setPosition(Base::convertTo<Base::Vector3d>(base));
cs.setAxes(Base::convertTo<Base::Vector3d>(norm),
Base::convertTo<Base::Vector3d>(dirU));
Base::Placement pm = Base::CoordinateSystem().displacement(cs);
double q0, q1, q2, q3;
pm.getRotation().getValue(q0, q1, q2, q3);

Base::Console().Log("RMS value for plane fit with %lu points: %.4f\n", aData.size(), sigma);
Base::Console().Log(" Plane base(%.4f, %.4f, %.4f)\n", base.x, base.y, base.z);
Base::Console().Log(" Plane normal(%.4f, %.4f, %.4f)\n", norm.x, norm.y, norm.z);

std::stringstream str;
str << "from FreeCAD import Base" << std::endl;
str << "App.ActiveDocument.addObject('Part::Plane','Plane_fit')" << std::endl;
str << "App.ActiveDocument.ActiveObject.Length = " << length << std::endl;
str << "App.ActiveDocument.ActiveObject.Width = " << width << std::endl;
str << "App.ActiveDocument.ActiveObject.Placement = Base.Placement("
<< "Base.Vector(" << base.x << "," << base.y << "," << base.z << "),"
<< "Base.Rotation(" << q0 << "," << q1 << "," << q2 << "," << q3 << "))" << std::endl;

openCommand("Fit plane");
doCommand(Gui::Command::Doc, str.str().c_str());
commitCommand();
updateActive();
}
}
}
Expand Down

0 comments on commit 70f5867

Please sign in to comment.