⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kd_util.cpp

📁 c++实现的KNN库:建立高维度的K-d tree,实现K邻域搜索
💻 CPP
字号:
//----------------------------------------------------------------------// File:			kd_util.cpp// Programmer:		Sunil Arya and David Mount// Description:		Common utilities for kd-trees// Last modified:	01/04/05 (Version 1.0)//----------------------------------------------------------------------// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and// David Mount.  All Rights Reserved.// // This software and related documentation is part of the Approximate// Nearest Neighbor Library (ANN).  This software is provided under// the provisions of the Lesser GNU Public License (LGPL).  See the// file ../ReadMe.txt for further information.// // The University of Maryland (U.M.) and the authors make no// representations about the suitability or fitness of this software for// any purpose.  It is provided "as is" without express or implied// warranty.//----------------------------------------------------------------------// History://	Revision 0.1  03/04/98//		Initial release//----------------------------------------------------------------------#include "kd_util.h"					// kd-utility declarations#include <ANN/ANNperf.h>				// performance evaluation//----------------------------------------------------------------------// The following routines are utility functions for manipulating// points sets, used in determining splitting planes for kd-tree// construction.//----------------------------------------------------------------------//----------------------------------------------------------------------//	NOTE: Virtually all point indexing is done through an index (i.e.//	permutation) array pidx.  Consequently, a reference to the d-th//	coordinate of the i-th point is pa[pidx[i]][d].  The macro PA(i,d)//	is a shorthand for this.//----------------------------------------------------------------------										// standard 2-d indirect indexing#define PA(i,d)			(pa[pidx[(i)]][(d)])										// accessing a single point#define PP(i)			(pa[pidx[(i)]])//----------------------------------------------------------------------//	annAspectRatio//		Compute the aspect ratio (ratio of longest to shortest side)//		of a rectangle.//----------------------------------------------------------------------double annAspectRatio(	int					dim,			// dimension	const ANNorthRect	&bnd_box)		// bounding cube{	ANNcoord length = bnd_box.hi[0] - bnd_box.lo[0];	ANNcoord min_length = length;				// min side length	ANNcoord max_length = length;				// max side length	for (int d = 0; d < dim; d++) {		length = bnd_box.hi[d] - bnd_box.lo[d];		if (length < min_length) min_length = length;		if (length > max_length) max_length = length;	}	return max_length/min_length;}//----------------------------------------------------------------------//	annEnclRect, annEnclCube//		These utilities compute the smallest rectangle and cube enclosing//		a set of points, respectively.//----------------------------------------------------------------------void annEnclRect(	ANNpointArray		pa,				// point array	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					dim,			// dimension	ANNorthRect			&bnds)			// bounding cube (returned){	for (int d = 0; d < dim; d++) {		// find smallest enclosing rectangle		ANNcoord lo_bnd = PA(0,d);		// lower bound on dimension d		ANNcoord hi_bnd = PA(0,d);		// upper bound on dimension d		for (int i = 0; i < n; i++) {			if (PA(i,d) < lo_bnd) lo_bnd = PA(i,d);			else if (PA(i,d) > hi_bnd) hi_bnd = PA(i,d);		}		bnds.lo[d] = lo_bnd;		bnds.hi[d] = hi_bnd;	}}void annEnclCube(						// compute smallest enclosing cube	ANNpointArray		pa,				// point array	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					dim,			// dimension	ANNorthRect			&bnds)			// bounding cube (returned){	int d;										// compute smallest enclosing rect	annEnclRect(pa, pidx, n, dim, bnds);	ANNcoord max_len = 0;				// max length of any side	for (d = 0; d < dim; d++) {			// determine max side length		ANNcoord len = bnds.hi[d] - bnds.lo[d];		if (len > max_len) {			// update max_len if longest			max_len = len;		}	}	for (d = 0; d < dim; d++) {			// grow sides to match max		ANNcoord len = bnds.hi[d] - bnds.lo[d];		ANNcoord half_diff = (max_len - len) / 2;		bnds.lo[d] -= half_diff;		bnds.hi[d] += half_diff;	}}//----------------------------------------------------------------------//	annBoxDistance - utility routine which computes distance from point to//		box (Note: most distances to boxes are computed using incremental//		distance updates, not this function.)//----------------------------------------------------------------------ANNdist annBoxDistance(			// compute distance from point to box	const ANNpoint		q,				// the point	const ANNpoint		lo,				// low point of box	const ANNpoint		hi,				// high point of box	int					dim)			// dimension of space{	register ANNdist dist = 0.0;		// sum of squared distances	register ANNdist t;	for (register int d = 0; d < dim; d++) {		if (q[d] < lo[d]) {				// q is left of box			t = ANNdist(lo[d]) - ANNdist(q[d]);			dist = ANN_SUM(dist, ANN_POW(t));		}		else if (q[d] > hi[d]) {		// q is right of box			t = ANNdist(q[d]) - ANNdist(hi[d]);			dist = ANN_SUM(dist, ANN_POW(t));		}	}	ANN_FLOP(4*dim)						// increment floating op count	return dist;}//----------------------------------------------------------------------//	annSpread - find spread along given dimension//	annMinMax - find min and max coordinates along given dimension//	annMaxSpread - find dimension of max spread//----------------------------------------------------------------------ANNcoord annSpread(				// compute point spread along dimension	ANNpointArray		pa,				// point array	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					d)				// dimension to check{	ANNcoord min = PA(0,d);				// compute max and min coords	ANNcoord max = PA(0,d);	for (int i = 1; i < n; i++) {		ANNcoord c = PA(i,d);		if (c < min) min = c;		else if (c > max) max = c;	}	return (max - min);					// total spread is difference}void annMinMax(					// compute min and max coordinates along dim	ANNpointArray		pa,				// point array	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					d,				// dimension to check	ANNcoord			&min,			// minimum value (returned)	ANNcoord			&max)			// maximum value (returned){	min = PA(0,d);						// compute max and min coords	max = PA(0,d);	for (int i = 1; i < n; i++) {		ANNcoord c = PA(i,d);		if (c < min) min = c;		else if (c > max) max = c;	}}int annMaxSpread(						// compute dimension of max spread	ANNpointArray		pa,				// point array	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					dim)			// dimension of space{	int max_dim = 0;					// dimension of max spread	ANNcoord max_spr = 0;				// amount of max spread	if (n == 0) return max_dim;			// no points, who cares?	for (int d = 0; d < dim; d++) {		// compute spread along each dim		ANNcoord spr = annSpread(pa, pidx, n, d);		if (spr > max_spr) {			// bigger than current max			max_spr = spr;			max_dim = d;		}	}	return max_dim;}//----------------------------------------------------------------------//	annMedianSplit - split point array about its median//		Splits a subarray of points pa[0..n] about an element of given//		rank (median: n_lo = n/2) with respect to dimension d.  It places//		the element of rank n_lo-1 correctly (because our splitting rule//		takes the mean of these two).  On exit, the array is permuted so//		that:////		pa[0..n_lo-2][d] <= pa[n_lo-1][d] <= pa[n_lo][d] <= pa[n_lo+1..n-1][d].////		The mean of pa[n_lo-1][d] and pa[n_lo][d] is returned as the//		splitting value.////		All indexing is done indirectly through the index array pidx.////		This function uses the well known selection algorithm due to//		C.A.R. Hoare.//----------------------------------------------------------------------										// swap two points in pa array#define PASWAP(a,b) { int tmp = pidx[a]; pidx[a] = pidx[b]; pidx[b] = tmp; }void annMedianSplit(	ANNpointArray		pa,				// points to split	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					d,				// dimension along which to split	ANNcoord			&cv,			// cutting value	int					n_lo)			// split into n_lo and n-n_lo{	int l = 0;							// left end of current subarray	int r = n-1;						// right end of current subarray	while (l < r) {		register int i = (r+l)/2;		// select middle as pivot		register int k;		if (PA(i,d) > PA(r,d))			// make sure last > pivot			PASWAP(i,r)		PASWAP(l,i);					// move pivot to first position		ANNcoord c = PA(l,d);			// pivot value		i = l;		k = r;		for(;;) {						// pivot about c			while (PA(++i,d) < c) ;			while (PA(--k,d) > c) ;			if (i < k) PASWAP(i,k) else break;		}		PASWAP(l,k);					// pivot winds up in location k		if (k > n_lo)	   r = k-1;		// recurse on proper subarray		else if (k < n_lo) l = k+1;		else break;						// got the median exactly	}	if (n_lo > 0) {						// search for next smaller item		ANNcoord c = PA(0,d);			// candidate for max		int k = 0;						// candidate's index		for (int i = 1; i < n_lo; i++) {			if (PA(i,d) > c) {				c = PA(i,d);				k = i;			}		}		PASWAP(n_lo-1, k);				// max among pa[0..n_lo-1] to pa[n_lo-1]	}										// cut value is midpoint value	cv = (PA(n_lo-1,d) + PA(n_lo,d))/2.0;}//----------------------------------------------------------------------//	annPlaneSplit - split point array about a cutting plane//		Split the points in an array about a given plane along a//		given cutting dimension.  On exit, br1 and br2 are set so//		that://		//				pa[ 0 ..br1-1] <  cv//				pa[br1..br2-1] == cv//				pa[br2.. n -1] >  cv////		All indexing is done indirectly through the index array pidx.////----------------------------------------------------------------------void annPlaneSplit(				// split points by a plane	ANNpointArray		pa,				// points to split	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					d,				// dimension along which to split	ANNcoord			cv,				// cutting value	int					&br1,			// first break (values < cv)	int					&br2)			// second break (values == cv){	int l = 0;	int r = n-1;	for(;;) {							// partition pa[0..n-1] about cv		while (l < n && PA(l,d) < cv) l++;		while (r >= 0 && PA(r,d) >= cv) r--;		if (l > r) break;		PASWAP(l,r);		l++; r--;	}	br1 = l;					// now: pa[0..br1-1] < cv <= pa[br1..n-1]	r = n-1;	for(;;) {							// partition pa[br1..n-1] about cv		while (l < n && PA(l,d) <= cv) l++;		while (r >= br1 && PA(r,d) > cv) r--;		if (l > r) break;		PASWAP(l,r);		l++; r--;	}	br2 = l;					// now: pa[br1..br2-1] == cv < pa[br2..n-1]}//----------------------------------------------------------------------//	annBoxSplit - split point array about a orthogonal rectangle//		Split the points in an array about a given orthogonal//		rectangle.  On exit, n_in is set to the number of points//		that are inside (or on the boundary of) the rectangle.////		All indexing is done indirectly through the index array pidx.////----------------------------------------------------------------------void annBoxSplit(				// split points by a box	ANNpointArray		pa,				// points to split	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					dim,			// dimension of space	ANNorthRect			&box,			// the box	int					&n_in)			// number of points inside (returned){	int l = 0;	int r = n-1;	for(;;) {							// partition pa[0..n-1] about box		while (l < n && box.inside(dim, PP(l))) l++;		while (r >= 0 && !box.inside(dim, PP(r))) r--;		if (l > r) break;		PASWAP(l,r);		l++; r--;	}	n_in = l;					// now: pa[0..n_in-1] inside and rest outside}//----------------------------------------------------------------------//	annSplitBalance - compute balance factor for a given plane split//		Balance factor is defined as the number of points lying//		below the splitting value minus n/2 (median).  Thus, a//		median split has balance 0, left of this is negative and//		right of this is positive.  (The points are unchanged.)//----------------------------------------------------------------------int annSplitBalance(			// determine balance factor of a split	ANNpointArray		pa,				// points to split	ANNidxArray			pidx,			// point indices	int					n,				// number of points	int					d,				// dimension along which to split	ANNcoord			cv)				// cutting value{	int n_lo = 0;	for(int i = 0; i < n; i++) {		// count number less than cv		if (PA(i,d) < cv) n_lo++;	}	return n_lo - n/2;}//----------------------------------------------------------------------//	annBox2Bnds - convert bounding box to list of bounds//		Given two boxes, an inner box enclosed within a bounding//		box, this routine determines all the sides for which the//		inner box is strictly contained with the bounding box,//		and adds an appropriate entry to a list of bounds.  Then//		we allocate storage for the final list of bounds, and return//		the resulting list and its size.//----------------------------------------------------------------------void annBox2Bnds(						// convert inner box to bounds	const ANNorthRect	&inner_box,		// inner box	const ANNorthRect	&bnd_box,		// enclosing box	int					dim,			// dimension of space	int					&n_bnds,		// number of bounds (returned)	ANNorthHSArray		&bnds)			// bounds array (returned){	int i;	n_bnds = 0;									// count number of bounds	for (i = 0; i < dim; i++) {		if (inner_box.lo[i] > bnd_box.lo[i])	// low bound is inside				n_bnds++;		if (inner_box.hi[i] < bnd_box.hi[i])	// high bound is inside				n_bnds++;	}	bnds = new ANNorthHalfSpace[n_bnds];		// allocate appropriate size	int j = 0;	for (i = 0; i < dim; i++) {					// fill the array		if (inner_box.lo[i] > bnd_box.lo[i]) {				bnds[j].cd = i;				bnds[j].cv = inner_box.lo[i];				bnds[j].sd = +1;				j++;		}		if (inner_box.hi[i] < bnd_box.hi[i]) {				bnds[j].cd = i;				bnds[j].cv = inner_box.hi[i];				bnds[j].sd = -1;				j++;		}	}}//----------------------------------------------------------------------//	annBnds2Box - convert list of bounds to bounding box//		Given an enclosing box and a list of bounds, this routine//		computes the corresponding inner box.  It is assumed that//		the box points have been allocated already.//----------------------------------------------------------------------void annBnds2Box(	const ANNorthRect	&bnd_box,		// enclosing box	int					dim,			// dimension of space	int					n_bnds,			// number of bounds	ANNorthHSArray		bnds,			// bounds array	ANNorthRect			&inner_box)		// inner box (returned){	annAssignRect(dim, inner_box, bnd_box);		// copy bounding box to inner	for (int i = 0; i < n_bnds; i++) {		bnds[i].project(inner_box.lo);			// project each endpoint		bnds[i].project(inner_box.hi);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -