Esempio n. 1
0
void filter_depthscan::applyFilter(RichParameterSet* pars){
    typedef qglviewer::Vec QGLVec;
    /// Window size
    int w = drawArea()->width();
    int h = drawArea()->height();
   
    /// Create query octree
    SurfaceMeshModel* selection = SurfaceMesh::safe_cast( model() );
    Octree octree( selection );

    if(selection->n_faces()==0)
        throw StarlabException("Cannot scan a point cloud, need n_faces()>0");
    
    /// Need face normals for angle rejection
    if(!selection->has_face_normals())
        SurfaceMesh::NormalsHelper(selection).compute_face_normals();
    Vector3FaceProperty fnormals = selection->face_normals();
    
    /// Create a model to store scans & add it
    SurfaceMeshModel* scan = new SurfaceMeshModel("","Scan");
    document()->addModel(scan);   
    drawArea()->setRenderer(scan,"Flat Shading");
    scan->color = QColor(125,0,0);

    /// assert( step>1 )
    int step = qMax( pars->getInt("density"),1 );
    
    /// angle: [0,90]
    double angle = qBound(0.0, (double) pars->getFloat("maxangle"), 90.0);
    double mincosangle = cos( angle * M_PI / 180 );
    
    /// scan noise
    double znoise = pars->getFloat("znoise");
    
    /// Fetch normals?
    // bool getNormals = pars->getBool("getnormal");
    

    /// Size of matrices
    int nrows = std::floor( double(h) / step );
    int ncols = std::floor( double(w) / step );
    
    /// Layers containing point coordinates
    Matrix<XYZ_View, Dynamic, Dynamic> X(ncols,nrows);

    /// Perform scan
    for(int winX=0,i=0; i<ncols; winX+=step, i++){
        for(int winY=0,j=0; j<nrows; winY+=step, j++){
            QGLVec _orig, _dir;
            drawArea()->camera()->convertClickToLine( QPoint(winX, winY), _orig, _dir );
            Vector3 orig(_orig[0],_orig[1],_orig[2]);
            Vector3 dir(_dir[0],_dir[1],_dir[2]);
            dir.normalize(); ///< just to be sure
            int isectHit = -1;
            Eigen::Vector3d ipoint = octree.closestIntersectionPoint( Ray(orig, dir), &isectHit );
            
            X(i,j).xyz[0] = std::numeric_limits<Scalar>::quiet_NaN();
            if(isectHit>=0){
                Vector3 fnormal = fnormals[ Face(isectHit) ];
                double cosangle = std::abs(dot( fnormal, dir ));
                if(cosangle>mincosangle){
                    ipoint += dir*randn(0.0,znoise);
                    
                    /// Save point
                    X(i,j).xyz = ipoint;
                    X(i,j).view = dir;
                }
            }
        }
    }

    DepthTriangulator(scan).execute(X, mincosangle);
    scan->update_vertex_normals();
    
    /// Inform user
    showMessage("Scanned #P=%d points", scan->n_vertices());
}