| 1 | /************************************************************************* | 
|---|
| 2 | * Copyright (c) 2011 AT&T Intellectual Property | 
|---|
| 3 | * All rights reserved. This program and the accompanying materials | 
|---|
| 4 | * are made available under the terms of the Eclipse Public License v1.0 | 
|---|
| 5 | * which accompanies this distribution, and is available at | 
|---|
| 6 | * http://www.eclipse.org/legal/epl-v10.html | 
|---|
| 7 | * | 
|---|
| 8 | * Contributors: See CVS logs. Details at http://www.graphviz.org/ | 
|---|
| 9 | *************************************************************************/ | 
|---|
| 10 |  | 
|---|
| 11 | #include "config.h" | 
|---|
| 12 |  | 
|---|
| 13 | #ifdef HAVE_ANN | 
|---|
| 14 | //---------------------------------------------------------------------- | 
|---|
| 15 | //		File:			get_nearest_neighb_graph.cpp | 
|---|
| 16 | //---------------------------------------------------------------------- | 
|---|
| 17 |  | 
|---|
| 18 | #include <cstdlib>						// C standard library | 
|---|
| 19 | #include <cstdio>						// C I/O (for sscanf) | 
|---|
| 20 | #include <cstring>						// string manipulation | 
|---|
| 21 | #include <fstream>						// file I/O | 
|---|
| 22 | #include <ANN/ANN.h>					// ANN declarations | 
|---|
| 23 |  | 
|---|
| 24 | using namespace std;					// make std:: accessible | 
|---|
| 25 | int                             dim                             = 4;                    // dimension | 
|---|
| 26 |  | 
|---|
| 27 |  | 
|---|
| 28 | static void printPt(ostream &out, ANNpoint p)			// print point | 
|---|
| 29 | { | 
|---|
| 30 | out << ""<< p[0]; | 
|---|
| 31 | for (int i = 1; i < dim; i++) { | 
|---|
| 32 | out << ","<< p[i]; | 
|---|
| 33 | } | 
|---|
| 34 | out << ""; | 
|---|
| 35 | } | 
|---|
| 36 |  | 
|---|
| 37 | static void sortPtsX(int n, ANNpointArray pts){ | 
|---|
| 38 | /* sort so that edges always go from left to right in x-doordinate */ | 
|---|
| 39 | ANNpoint p; | 
|---|
| 40 | ANNcoord x, y; | 
|---|
| 41 | int i, j; | 
|---|
| 42 | for (i = 0; i < n; i++){ | 
|---|
| 43 | for (j = 0; j < dim; j++){ | 
|---|
| 44 | p = pts[i]; | 
|---|
| 45 | if (p[0] < p[2] || (p[0] == p[2] && p[1] < p[3])) continue; | 
|---|
| 46 | x = p[0]; y = p[1]; | 
|---|
| 47 | p[0] = p[2]; | 
|---|
| 48 | p[1] = p[3]; | 
|---|
| 49 | p[2] = x; | 
|---|
| 50 | p[3] = y; | 
|---|
| 51 | } | 
|---|
| 52 | } | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 | static void sortPtsY(int n, ANNpointArray pts){ | 
|---|
| 56 | /* sort so that edges always go from left to right in x-doordinate */ | 
|---|
| 57 | ANNpoint p; | 
|---|
| 58 | ANNcoord x, y; | 
|---|
| 59 | int i, j; | 
|---|
| 60 | for (i = 0; i < n; i++){ | 
|---|
| 61 | for (j = 0; j < dim; j++){ | 
|---|
| 62 | p = pts[i]; | 
|---|
| 63 | if (p[1] < p[3] || (p[1] == p[3] && p[0] < p[2])) continue; | 
|---|
| 64 | x = p[0]; y = p[1]; | 
|---|
| 65 | p[0] = p[2]; | 
|---|
| 66 | p[1] = p[3]; | 
|---|
| 67 | p[2] = x; | 
|---|
| 68 | p[3] = y; | 
|---|
| 69 | } | 
|---|
| 70 | } | 
|---|
| 71 | } | 
|---|
| 72 |  | 
|---|
| 73 |  | 
|---|
| 74 | extern "C"void nearest_neighbor_graph_ann(int nPts, int dim, int k, double eps, double *x, int *nz0, int **irn0, int **jcn0, double **val0); | 
|---|
| 75 |  | 
|---|
| 76 | void nearest_neighbor_graph_ann(int nPts, int dim, int k, double eps, double *x, int *nz0, int **irn0, int **jcn0, double **val0){ | 
|---|
| 77 |  | 
|---|
| 78 | /* Gives a nearest neighbor graph is a list of dim-dimendional points. The connectivity is in irn/jcn, and the distance in val. | 
|---|
| 79 |  | 
|---|
| 80 | nPts: number of points | 
|---|
| 81 | dim: dimension | 
|---|
| 82 | k: number of neighbors needed | 
|---|
| 83 | eps: error tolerance | 
|---|
| 84 | x: nPts*dim vector. The i-th point is x[i*dim : i*dim + dim - 1] | 
|---|
| 85 | nz: number of entries in the connectivity matrix irn/jcn/val | 
|---|
| 86 | irn, jcn: the connectivity | 
|---|
| 87 | val: the distance | 
|---|
| 88 |  | 
|---|
| 89 | note that there could be repeates | 
|---|
| 90 | */ | 
|---|
| 91 |  | 
|---|
| 92 | ANNpointArray		dataPts;				// data points | 
|---|
| 93 | ANNidxArray			nnIdx;					// near neighbor indices | 
|---|
| 94 | ANNdistArray		dists;					// near neighbor distances | 
|---|
| 95 | ANNkd_tree*			kdTree;					// search structure | 
|---|
| 96 |  | 
|---|
| 97 | double *xx; | 
|---|
| 98 | int *irn, *jcn; | 
|---|
| 99 | double *val; | 
|---|
| 100 | int nz; | 
|---|
| 101 |  | 
|---|
| 102 | irn = *irn0; | 
|---|
| 103 | jcn = *jcn0; | 
|---|
| 104 | val = *val0; | 
|---|
| 105 |  | 
|---|
| 106 |  | 
|---|
| 107 | dataPts = annAllocPts(nPts, dim);			// allocate data points | 
|---|
| 108 | nnIdx = new ANNidx[k];						// allocate near neigh indices | 
|---|
| 109 | dists = new ANNdist[k];						// allocate near neighbor dists | 
|---|
| 110 |  | 
|---|
| 111 | for (int i = 0; i < nPts; i++){ | 
|---|
| 112 | xx =  dataPts[i]; | 
|---|
| 113 | for (int j = 0; j < dim; j++) xx[j] = x[i*dim + j]; | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | //========= graph when sort based on x ======== | 
|---|
| 117 | nz = 0; | 
|---|
| 118 | sortPtsX(nPts, dataPts); | 
|---|
| 119 | kdTree = new ANNkd_tree(					// build search structure | 
|---|
| 120 | dataPts,					// the data points | 
|---|
| 121 | nPts,						// number of points | 
|---|
| 122 | dim);						// dimension of space | 
|---|
| 123 | for (int ip = 0; ip < nPts; ip++){ | 
|---|
| 124 | kdTree->annkSearch(						// search | 
|---|
| 125 | dataPts[ip],						// query point | 
|---|
| 126 | k,								// number of near neighbors | 
|---|
| 127 | nnIdx,							// nearest neighbors (returned) | 
|---|
| 128 | dists,							// distance (returned) | 
|---|
| 129 | eps);							// error bound | 
|---|
| 130 |  | 
|---|
| 131 | for (int i = 0; i < k; i++) {			// print summary | 
|---|
| 132 | if (nnIdx[i] == ip) continue; | 
|---|
| 133 | val[nz] = dists[i]; | 
|---|
| 134 | irn[nz] = ip; | 
|---|
| 135 | jcn[nz++] = nnIdx[i]; | 
|---|
| 136 | //cout << ip << "--" << nnIdx[i] << " [len = " << dists[i]<< ", weight = \"" << 1./(dists[i]) << "\", wt = \"" << 1./(dists[i]) << "\"]\n"; | 
|---|
| 137 | //printPt(cout, dataPts[ip]); | 
|---|
| 138 | //cout << "--"; | 
|---|
| 139 | //printPt(cout, dataPts[nnIdx[i]]); | 
|---|
| 140 | //cout << "\n"; | 
|---|
| 141 | } | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 |  | 
|---|
| 145 | //========= graph when sort based on y ======== | 
|---|
| 146 | sortPtsY(nPts, dataPts); | 
|---|
| 147 | kdTree = new ANNkd_tree(					// build search structure | 
|---|
| 148 | dataPts,					// the data points | 
|---|
| 149 | nPts,						// number of points | 
|---|
| 150 | dim);						// dimension of space | 
|---|
| 151 | for (int ip = 0; ip < nPts; ip++){ | 
|---|
| 152 | kdTree->annkSearch(						// search | 
|---|
| 153 | dataPts[ip],						// query point | 
|---|
| 154 | k,								// number of near neighbors | 
|---|
| 155 | nnIdx,							// nearest neighbors (returned) | 
|---|
| 156 | dists,							// distance (returned) | 
|---|
| 157 | eps);							// error bound | 
|---|
| 158 |  | 
|---|
| 159 | for (int i = 0; i < k; i++) {			// print summary | 
|---|
| 160 | if (nnIdx[i] == ip) continue; | 
|---|
| 161 | val[nz] = dists[i]; | 
|---|
| 162 | irn[nz] = ip; | 
|---|
| 163 | jcn[nz++] = nnIdx[i]; | 
|---|
| 164 | // cout << ip << "--" << nnIdx[i] << " [len = " << dists[i]<< ", weight = \"" << 1./(dists[i]) << "\", wt = \"" << 1./(dists[i]) << "\"]\n"; | 
|---|
| 165 | } | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | delete [] nnIdx;							// clean things up | 
|---|
| 169 | delete [] dists; | 
|---|
| 170 | delete kdTree; | 
|---|
| 171 |  | 
|---|
| 172 | *nz0 = nz; | 
|---|
| 173 |  | 
|---|
| 174 | annClose();									// done with ANN | 
|---|
| 175 |  | 
|---|
| 176 |  | 
|---|
| 177 |  | 
|---|
| 178 | } | 
|---|
| 179 |  | 
|---|
| 180 | #endif  /* HAVE_ANN */ | 
|---|
| 181 |  | 
|---|