/**
 * Input arguments: index (pointer), testset (matrix), n (int),  params (struct)
 * Output arguments: indices(matrix), dists(matrix)
 */
static void _index_find_nn(int nOutArray, mxArray* OutArray[], int nInArray, const mxArray* InArray[])
{
    /* Check the number of input arguments */
    if(nInArray != 4) {
        mexErrMsgTxt("Incorrect number of input arguments");
    }
    /* Check if there is one Output matrix */
    if(nOutArray > 2) {
        mexErrMsgTxt("One or two outputs required.");
    }

    const mxArray* indexMat = InArray[0];
    TypedIndex* typedIndex = *(TypedIndex**)mxGetData(indexMat);

    const mxArray* testsetMat = InArray[1];
    check_allowed_type(testsetMat);

    int tcount = mxGetN(testsetMat);

    const mxArray* nnMat = InArray[2];

    if ((mxGetM(nnMat)!=1)||(mxGetN(nnMat)!=1)) {
        mexErrMsgTxt("Number of nearest neighbors should be a scalar.");
    }
    int nn = (int)(*mxGetPr(nnMat));

    int* result = (int*)malloc(tcount*nn*sizeof(int));
    float* dists = NULL;
    double* ddists = NULL;

    const mxArray* pStruct = InArray[3];

    FLANNParameters p;
    matlabStructToFlannStruct(pStruct, p);

    if (mxIsSingle(testsetMat)) {
        if (typedIndex->type != FLANN_FLOAT32) {
            mexErrMsgTxt("Index type must match testset type");
        }
        float* testset = (float*) mxGetData(testsetMat);
        dists = (float*)malloc(tcount*nn*sizeof(float));
        flann_find_nearest_neighbors_index_float(typedIndex->index,testset, tcount, result, dists, nn, &p);
    }
    else if (mxIsDouble(testsetMat)) {
        if (typedIndex->type != FLANN_FLOAT64) {
            mexErrMsgTxt("Index type must match testset type");
        }
        double* testset = (double*) mxGetData(testsetMat);
        ddists = (double*)malloc(tcount*nn*sizeof(double));
        flann_find_nearest_neighbors_index_double(typedIndex->index,testset, tcount, result, ddists, nn, &p);
    }
    else if (mxIsUint8(testsetMat)) {
        if (typedIndex->type != FLANN_UINT8) {
            mexErrMsgTxt("Index type must match testset type");
        }
        unsigned char* testset = (unsigned char*) mxGetData(testsetMat);
        dists = (float*)malloc(tcount*nn*sizeof(float));
        flann_find_nearest_neighbors_index_byte(typedIndex->index,testset, tcount, result, dists, nn, &p);
    }
    else if (mxIsInt32(testsetMat)) {
        if (typedIndex->type != FLANN_INT32) {
            mexErrMsgTxt("Index type must match testset type");
        }
        int* testset = (int*) mxGetData(testsetMat);
        dists = (float*)malloc(tcount*nn*sizeof(float));
        flann_find_nearest_neighbors_index_int(typedIndex->index,testset, tcount, result, dists, nn, &p);
    }

    /* Allocate memory for Output Matrix */
    OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL);

    /* Get pointer to Output matrix and store result*/
    double* pOut = mxGetPr(OutArray[0]);
    for (int i=0; i<tcount*nn; ++i) {
        pOut[i] = result[i]+1; // matlab uses 1-based indexing
    }
    free(result);
    if (nOutArray > 1) {
        /* Allocate memory for Output Matrix */
        OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL);

        /* Get pointer to Output matrix and store result*/
        double* pDists = mxGetPr(OutArray[1]);
        if (dists!=NULL) {
            for (int i=0; i<tcount*nn; ++i) {
                pDists[i] = dists[i];
            }
        }
        if (ddists!=NULL) {
            for (int i=0; i<tcount*nn; ++i) {
                pDists[i] = ddists[i];
            }
        }
    }
    if (dists!=NULL) free(dists);
    if (ddists!=NULL) free(ddists);
}
Example #2
0
int NearestNode(MacroMesh *m, real *xphy) {
  int nearest = -1;

#ifdef _WITH_FLANN
  // Use of flann library: faster  ???
  static bool is_ready = false;
  static struct FLANNParameters p;

  static float speedup;
  static flann_index_t findex;

  // at first call: construct the index
  // TO DO free the index when finished
  if (!is_ready) {
    printf("Using flann: build search index...\n");
    p = DEFAULT_FLANN_PARAMETERS;
    p.algorithm = FLANN_INDEX_AUTOTUNED;
    p.target_precision = 0.9; /* want 90% target precision */

#if real == double
      findex = flann_build_index_double(m->node, m->nbnodes, 3, &speedup, &p);
#else
      findex = flann_build_index_float(m->node, m->nbnodes, 3, &speedup, &p);
#endif
    is_ready = true;
  }
  
  // number of nearest neighbors to search 
  int nn = 1;
  int result[nn];
  real dists[nn];

  // compute the nn nearest-neighbors of each point in xphy
  // with index construction
  // flann_find_nearest_neighbors_real(m->node,     // nodes list
  // 				      m->nbnodes,  // number of nodes
  // 				      3,           // space dim
  // 				      xphy,
  // 				      1,           // number of points in xphy
  // 				      result,      // nearest points indices
  // 				      dists,       // distances
  // 				      nn,
  // 				      &p);         // flan struct
  

#if real == double
  flann_find_nearest_neighbors_index_double(findex,// index
					    xphy,
					    1,      // number of points in xphy
					    result, // nearest points indices
					    dists,  // distances
					    nn,
					    &p);     // flan struct
#else
  flann_find_nearest_neighbors_index_float(findex,// index
					   xphy,
					   1,      // number of points in xphy
					   result, // nearest points indices
					   dists,  // distances
					   nn,
					   &p);     // flan struct
#endif

  nearest = result[0];
  // printf("xphy=%f %f %f nearest=%d %f %f %f \n",
  // 	 xphy[0],xphy[1],xphy[2],nearest+1,
  // 	 m->node[0+nearest*3],m->node[1+nearest*3],m->node[2+nearest*3]);

#else // Do not use FLANN library.

  // slow version: loops on all the points
  real d = 1e20;

  for(int ino = 0; ino < m->nbnodes; ino++){
    real d2 = Dist(xphy, m->node + 3 * ino);
    if (d2 < d) {
      nearest = ino;
      d = d2;
    }
  }
#endif

  return nearest;
}