void PlaneFitSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices) { MeshCore::MeshPoint center; MeshCore::MeshPointArray PointArray = kernel.GetPoints(); MeshCore::MeshPointIterator v_it(kernel); MeshCore::MeshRefPointToPoints vv_it(kernel); MeshCore::MeshPointArray::_TConstIterator v_beg = kernel.GetPoints().begin(); for (unsigned int i=0; i<iterations; i++) { Base::Vector3f N, L; for (std::vector<unsigned long>::const_iterator it = point_indices.begin(); it != point_indices.end(); ++it) { v_it.Set(*it); MeshCore::PlaneFit pf; pf.AddPoint(*v_it); center = *v_it; const std::set<unsigned long>& cv = vv_it[v_it.Position()]; if (cv.size() < 3) continue; std::set<unsigned long>::const_iterator cv_it; for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) { pf.AddPoint(v_beg[*cv_it]); center += v_beg[*cv_it]; } float scale = 1.0f/((float)cv.size()+1.0f); center.Scale(scale,scale,scale); // get the mean plane of the current vertex with the surrounding vertices pf.Fit(); N = pf.GetNormal(); N.Normalize(); // look in which direction we should move the vertex L.Set(v_it->x - center.x, v_it->y - center.y, v_it->z - center.z); if (N*L < 0.0) N.Scale(-1.0, -1.0, -1.0); // maximum value to move is distance to mean plane float d = std::min<float>((float)fabs(this->tolerance),(float)fabs(N*L)); N.Scale(d,d,d); PointArray[v_it.Position()].Set(v_it->x - N.x, v_it->y - N.y, v_it->z - N.z); } // assign values without affecting iterators unsigned long count = kernel.CountPoints(); for (unsigned long idx = 0; idx < count; idx++) { kernel.SetPoint(idx, PointArray[idx]); } } }
virtual std::vector<float> getParameter(FitParameter::Points pts) const { std::vector<float> values; MeshCore::PlaneFit fit; fit.AddPoints(pts); if (fit.Fit() < FLOAT_MAX) { Base::Vector3f base = fit.GetBase(); Base::Vector3f axis = fit.GetNormal(); values.push_back(base.x); values.push_back(base.y); values.push_back(base.z); values.push_back(axis.x); values.push_back(axis.y); values.push_back(axis.z); } return values; }
void ParameterCorrection::CalcEigenvectors() { MeshCore::PlaneFit planeFit; //for (it = aclPoints.begin(); it!=aclPoints.end(); ++it) // planeFit.AddPoint(*it); for (int i=_pvcPoints->Lower(); i<=_pvcPoints->Upper(); i++) { planeFit.AddPoint(Base::Vector3f( (float)(*_pvcPoints)(i).X(), (float)(*_pvcPoints)(i).Y(), (float)(*_pvcPoints)(i).Z())); } planeFit.Fit(); _clU = planeFit.GetDirU(); _clV = planeFit.GetDirV(); _clW = planeFit.GetNormal(); }
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; 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) 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(); } } } }