+ improve the plane fit from REEN module
This commit is contained in:
parent
1a2fe206ca
commit
2e6c54eedf
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "Approximation.h"
|
||||
|
||||
#include <Base/BoundBox.h>
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <Mod/Mesh/App/WildMagic4/Wm4ApprQuadraticFit3.h>
|
||||
#include <Mod/Mesh/App/WildMagic4/Wm4ApprPlaneFit3.h>
|
||||
|
@ -360,6 +361,24 @@ void PlaneFit::ProjectToPlane ()
|
|||
}
|
||||
}
|
||||
|
||||
void PlaneFit::Dimension(float& length, float& width) const
|
||||
{
|
||||
const Base::Vector3f& bs = _vBase;
|
||||
const Base::Vector3f& ex = _vDirU;
|
||||
const Base::Vector3f& ey = _vDirV;
|
||||
|
||||
Base::BoundBox3f bbox;
|
||||
std::list<Base::Vector3f>::const_iterator cIt;
|
||||
for (cIt = _vPoints.begin(); cIt != _vPoints.end(); ++cIt) {
|
||||
Base::Vector3f pnt = *cIt;
|
||||
pnt.TransformToCoordinateSystem(bs, ex, ey);
|
||||
bbox.Add(pnt);
|
||||
}
|
||||
|
||||
length = bbox.MaxX - bbox.MinX;
|
||||
width = bbox.MaxY - bbox.MinY;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
bool QuadraticFit::GetCurvatureInfo(double x, double y, double z,
|
||||
|
|
|
@ -225,6 +225,10 @@ public:
|
|||
* Projects the points onto the fitted plane.
|
||||
*/
|
||||
void ProjectToPlane();
|
||||
/**
|
||||
* Get the dimension of the fitted plane.
|
||||
*/
|
||||
void Dimension(float& length, float& width) const;
|
||||
|
||||
protected:
|
||||
Base::Vector3f _vBase; /**< Base vector of the plane. */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
# include <BRepFill.hxx>
|
||||
# include <BRepLib.hxx>
|
||||
# include <gp_Circ.hxx>
|
||||
# include <gp_Ax3.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <GCE2d_MakeSegment.hxx>
|
||||
|
@ -576,10 +577,11 @@ static PyObject * makeSolid(PyObject *self, PyObject *args)
|
|||
static PyObject * makePlane(PyObject *self, PyObject *args)
|
||||
{
|
||||
double length, width;
|
||||
PyObject *pPnt=0, *pDir=0;
|
||||
if (!PyArg_ParseTuple(args, "dd|O!O!", &length, &width,
|
||||
&(Base::VectorPy::Type), &pPnt,
|
||||
&(Base::VectorPy::Type), &pDir))
|
||||
PyObject *pPnt=0, *pDirZ=0, *pDirX=0;
|
||||
if (!PyArg_ParseTuple(args, "dd|O!O!O!", &length, &width,
|
||||
&(Base::VectorPy::Type), &pPnt,
|
||||
&(Base::VectorPy::Type), &pDirZ,
|
||||
&(Base::VectorPy::Type), &pDirX))
|
||||
return NULL;
|
||||
|
||||
if (length < Precision::Confusion()) {
|
||||
|
@ -598,11 +600,21 @@ static PyObject * makePlane(PyObject *self, PyObject *args)
|
|||
Base::Vector3d pnt = static_cast<Base::VectorPy*>(pPnt)->value();
|
||||
p.SetCoord(pnt.x, pnt.y, pnt.z);
|
||||
}
|
||||
if (pDir) {
|
||||
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDir)->value();
|
||||
if (pDirZ) {
|
||||
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDirZ)->value();
|
||||
d.SetCoord(vec.x, vec.y, vec.z);
|
||||
}
|
||||
Handle_Geom_Plane aPlane = new Geom_Plane(p, d);
|
||||
Handle_Geom_Plane aPlane;
|
||||
if (pDirX) {
|
||||
Base::Vector3d vec = static_cast<Base::VectorPy*>(pDirX)->value();
|
||||
gp_Dir dx;
|
||||
dx.SetCoord(vec.x, vec.y, vec.z);
|
||||
aPlane = new Geom_Plane(gp_Ax3(p, d, dx));
|
||||
}
|
||||
else {
|
||||
aPlane = new Geom_Plane(p, d);
|
||||
}
|
||||
|
||||
BRepBuilderAPI_MakeFace Face(aPlane, 0.0, length, 0.0, width
|
||||
#if OCC_VERSION_HEX >= 0x060502
|
||||
, Precision::Confusion()
|
||||
|
@ -614,6 +626,10 @@ static PyObject * makePlane(PyObject *self, PyObject *args)
|
|||
PyErr_SetString(PyExc_Exception, "creation of plane failed");
|
||||
return NULL;
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
PyErr_SetString(PyExc_Exception, "creation of plane failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject * makeBox(PyObject *self, PyObject *args)
|
||||
|
@ -1688,8 +1704,8 @@ struct PyMethodDef Part_methods[] = {
|
|||
"makeSolid(shape) -- Create a solid out of the shells inside a shape."},
|
||||
|
||||
{"makePlane" ,makePlane ,METH_VARARGS,
|
||||
"makePlane(length,width,[pnt,dir]) -- Make a plane\n"
|
||||
"By default pnt=Vector(0,0,0) and dir=Vector(0,0,1)"},
|
||||
"makePlane(length,width,[pnt,dirZ,dirX]) -- Make a plane\n"
|
||||
"By default pnt=Vector(0,0,0) and dirZ=Vector(0,0,1), dirX is ignored in this case"},
|
||||
|
||||
{"makeBox" ,makeBox ,METH_VARARGS,
|
||||
"makeBox(length,width,height,[pnt,dir]) -- Make a box located\n"
|
||||
|
|
|
@ -127,6 +127,15 @@ void CmdApproxPlane::activated(int iMsg)
|
|||
std::vector<Data::ComplexGeoData::Facet> aTopo;
|
||||
static_cast<App::PropertyComplexGeoData*>(jt->second)->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::Vector3f> aData;
|
||||
aData.reserve(aPoints.size());
|
||||
for (std::vector<Base::Vector3d>::iterator jt = aPoints.begin(); jt != aPoints.end(); ++jt)
|
||||
|
@ -135,21 +144,38 @@ void CmdApproxPlane::activated(int iMsg)
|
|||
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();
|
||||
|
||||
Base::Console().Message("RMS value for plane fit with %ld points: %.4f\n", aData.size(), sigma);
|
||||
Base::Console().Message(" Plane base(%.4f, %.4f, %.4f)\n", base.x, base.y, base.z);
|
||||
Base::Console().Message(" Plane normal(%.4f, %.4f, %.4f)\n", norm.x, norm.y, norm.z);
|
||||
// if the dot product of the refernce 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::Console().Log("RMS value for plane fit with %ld 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 << "import Part" << std::endl;
|
||||
str << "from FreeCAD import Base" << std::endl;
|
||||
str << "Part.show(Part.makePlane("
|
||||
<< 10 << ", " << 10 << ", "
|
||||
str << "App.ActiveDocument.addObject('Part::Feature','Plane_fit').Shape="
|
||||
<< "Part.makePlane("
|
||||
<< width << ", " << length << ", "
|
||||
<< "Base.Vector("
|
||||
<< base.x << ", " << base.y << ", " << base.z << "), "
|
||||
<< "Base.Vector("
|
||||
<< norm.x << ", " << norm.y << ", " << norm.z << ")))" << std::endl;
|
||||
<< norm.x << ", " << norm.y << ", " << norm.z << "), "
|
||||
<< "Base.Vector("
|
||||
<< dirU.x << ", " << dirU.y << ", " << dirU.z << "))" << std::endl;
|
||||
|
||||
openCommand("Fit plane");
|
||||
doCommand(Gui::Command::Doc, str.str().c_str());
|
||||
|
|
Loading…
Reference in New Issue
Block a user