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]);
        }
    }
}
Exemple #2
0
 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;
 }
Exemple #3
0
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();
}
Exemple #4
0
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();
            }
        }
    }
}