mirror of https://gitee.com/bigwinds/arangodb
Version 2.0 from Richard Parker
This commit is contained in:
parent
572b0694f2
commit
07b10b09b7
1442
GeoIndex/GeoIndex.c
1442
GeoIndex/GeoIndex.c
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* GeoIndex.h - header file for GeoIndex algorithms */
|
||||
/* Version 1.0 24.9.2011 R. A. Parker */
|
||||
/* Version 2.0 3.12.2011 R. A. Parker */
|
||||
|
||||
#ifdef GEO_TRIAGENS
|
||||
#include <Basics/Common.h>
|
||||
|
@ -43,10 +43,14 @@
|
|||
typedef long long GeoString;
|
||||
|
||||
/* percentage growth of slot or slotslot tables */
|
||||
#define GeoIndexGROW 50
|
||||
#define GeoIndexGROW 10
|
||||
|
||||
/* Largest interval that is processed simply */
|
||||
#define GeoIndexSMALLINTERVAL 5
|
||||
/* maximum number of points in a pot >=2 */
|
||||
#define GeoIndexPOTSIZE 6
|
||||
|
||||
/* number of fixed points for max-dist calculations */
|
||||
#define GeoIndexFIXEDPOINTS 8
|
||||
typedef unsigned short GeoFix;
|
||||
|
||||
/* If this #define is there, then the INDEXDUMP and */
|
||||
/* INDEXVALID functions are also available. These */
|
||||
|
@ -55,13 +59,13 @@ typedef long long GeoString;
|
|||
/* assumed to be a character string, if DEBUG is */
|
||||
/* set to 2. */
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
#define DEBUG 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double latitude;
|
||||
double longitude;
|
||||
void const * data;
|
||||
void * data;
|
||||
} GeoCoordinate;
|
||||
|
||||
typedef struct
|
||||
|
@ -73,11 +77,29 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int slotct;
|
||||
int occslots; /* number of occupied slots */
|
||||
int * sortslot;
|
||||
GeoString * geostrings; /* These two indexed in */
|
||||
GeoCoordinate * gc; /* parallel by a "slot" */
|
||||
double x[GeoIndexFIXEDPOINTS];
|
||||
double y[GeoIndexFIXEDPOINTS];
|
||||
double z[GeoIndexFIXEDPOINTS];
|
||||
} GeoIndexFixed;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int LorLeaf;
|
||||
int RorPoints;
|
||||
GeoString middle;
|
||||
GeoFix maxdist[GeoIndexFIXEDPOINTS];
|
||||
GeoString start;
|
||||
GeoString end;
|
||||
int level;
|
||||
int points[GeoIndexPOTSIZE];
|
||||
} GeoPot;
|
||||
typedef struct
|
||||
{
|
||||
GeoIndexFixed fixed; /* fixed point data */
|
||||
int potct; /* pots allocated */
|
||||
int slotct; /* slots allocated */
|
||||
GeoPot * pots; /* the pots themselves */
|
||||
GeoCoordinate * gc; /* the slots themselves */
|
||||
} GeoIndex;
|
||||
|
||||
GeoIndex * GeoIndex_new(void);
|
||||
|
@ -85,6 +107,7 @@ void GeoIndex_free(GeoIndex * gi);
|
|||
double GeoIndex_distance(GeoCoordinate * c1, GeoCoordinate * c2);
|
||||
int GeoIndex_insert(GeoIndex * gi, GeoCoordinate * c);
|
||||
int GeoIndex_remove(GeoIndex * gi, GeoCoordinate * c);
|
||||
int GeoIndex_hint(GeoIndex * gi, int hint);
|
||||
GeoCoordinates * GeoIndex_PointsWithinRadius(GeoIndex * gi,
|
||||
GeoCoordinate * c, double d);
|
||||
GeoCoordinates * GeoIndex_NearestCountPoints(GeoIndex * gi,
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* regression testing program for GeoIndex module */
|
||||
/* R.A.P. 1.1 5.11.2011 */
|
||||
/* R.A.P. 2.0 4.12.2011 */
|
||||
|
||||
#ifdef GEO_TRIAGENS
|
||||
#include "GeoIndex/GeoIndex.h"
|
||||
#else
|
||||
#include "GeoIndex.h"
|
||||
#include "GeoIndex2.h"
|
||||
#endif
|
||||
|
||||
int errors;
|
||||
|
@ -39,6 +39,24 @@ int errors;
|
|||
char ix[1000]; /* working array for (void *) data */
|
||||
char iy[30];
|
||||
|
||||
int np[20]={14676,23724,24457,24785,24809,
|
||||
25909,25051,27052,25192,28126,
|
||||
25191,29291,25079,30338,24852,
|
||||
31320,24565,31936,24133,31893};
|
||||
int hs[20]={16278595,6622245,83009659,97313687,94638085,
|
||||
86998272,72133969,99595673,76554853,116384443,
|
||||
458789,67013205,44378533,97387502,97331554,
|
||||
76392514,43104144,48695421,87361440,1556675} ;
|
||||
int np1[10]={6761,13521,20282,27042,33803,
|
||||
40563,47324,54084,60845,67605};
|
||||
int hs1[10]={79121168,71376992,120173779,54504134,89075457,
|
||||
50229904,41454125,104395668,14196041,106196305};
|
||||
int hs2[10]={21216619,99404510,92771863,40046216,25926851,
|
||||
6056147,93877377,82650316,14776130,41666384};
|
||||
int np4[4]={2838,5116,5180,9869};
|
||||
int hs4[4]={33972992,9770664,11661062,28398735};
|
||||
int hs5[4]={79685116,67516870,19274248,35037618};
|
||||
|
||||
void icheck(int e, int a, int b)
|
||||
{
|
||||
if(a==b) return;
|
||||
|
@ -118,6 +136,56 @@ void gcmass(int e, GeoCoordinates * gc, int ct, int hash)
|
|||
GeoIndex_CoordinatesFree(gc);
|
||||
}
|
||||
|
||||
void coonum(GeoCoordinate * gc, int num)
|
||||
{
|
||||
double lat,lon;
|
||||
int i,j;
|
||||
j=num;
|
||||
gc->latitude=-42.23994323;
|
||||
gc->longitude=-53.40029372;
|
||||
gc->data=&ix[num%997];
|
||||
for(i=1;i<30;i++)
|
||||
{
|
||||
lat=0.0;
|
||||
lon=0.0;
|
||||
if( (j&1)==1 )
|
||||
{
|
||||
if(i==1) { lat=16.1543722; lon=12.1992384; }
|
||||
if(i==2) { lat=6.14347227; lon=5.19923843; }
|
||||
if(i==3) { lat=2.15237222; lon=3.19923843; }
|
||||
if(i==4) { lat=1.51233226; lon=1.63122143; }
|
||||
if(i==5) { lat=1.14347229; lon=1.69932121; }
|
||||
if(i==6) { lat=0.93443431; lon=0.80023323; }
|
||||
if(i==7) { lat=0.63443442; lon=0.79932032; }
|
||||
if(i==8) { lat=0.70049323; lon=0.80076994; }
|
||||
if(i==9) { lat=0.89223236; lon=0.78805238; }
|
||||
if(i==10) { lat=0.85595656; lon=0.72332312; }
|
||||
if(i==11) { lat=0.18823232; lon=0.21129576; }
|
||||
if(i==12) { lat=0.12294854; lon=0.15543207; }
|
||||
if(i==13) { lat=0.30984343; lon=0.18223745; }
|
||||
if(i==14) { lat=0.19923412; lon=0.27345381; }
|
||||
if(i==15) { lat=0.18223534; lon=0.15332087; }
|
||||
if(i==16) { lat=0.09344343; lon=0.08002332; }
|
||||
if(i==17) { lat=0.06344344; lon=0.07993203; }
|
||||
if(i==18) { lat=0.07004932; lon=0.08007699; }
|
||||
if(i==19) { lat=0.08922323; lon=0.07880523; }
|
||||
if(i==20) { lat=0.08559565; lon=0.07233231; }
|
||||
if(i==21) { lat=0.01882323; lon=0.02112957; }
|
||||
if(i==22) { lat=0.01229485; lon=0.01554320; }
|
||||
if(i==23) { lat=0.03098434; lon=0.01822374; }
|
||||
if(i==24) { lat=0.01992341; lon=0.02734538; }
|
||||
if(i==25) { lat=0.01822353; lon=0.01533208; }
|
||||
if(i==26) { lat=0.00934434; lon=0.00800233; }
|
||||
if(i==27) { lat=0.00634434; lon=0.00799320; }
|
||||
if(i==28) { lat=0.00700493; lon=0.00800769; }
|
||||
if(i==29) { lat=0.00480493; lon=0.00170769; }
|
||||
}
|
||||
gc->latitude+=lat;
|
||||
gc->longitude+=lon;
|
||||
j>>=1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
GeoIndex * gi;
|
||||
|
@ -170,7 +238,7 @@ int main(int argc, char ** argv)
|
|||
/* mainly for debugging rather than regression */
|
||||
|
||||
gi=GeoIndex_new();
|
||||
|
||||
i=GeoIndex_hint(gi,10); /* set it to "robust" mode */
|
||||
for(i=0;i<50;i++)
|
||||
{
|
||||
gcp.latitude = 90.0;
|
||||
|
@ -900,44 +968,27 @@ int main(int argc, char ** argv)
|
|||
|
||||
if(mode==2)
|
||||
{
|
||||
gcp1.latitude = 44.999999;
|
||||
gcp1.longitude= 45.0000001;
|
||||
printf("start of 50000 x points within radius (43 found)\n");
|
||||
for(i=0;i<50000;i++)
|
||||
printf("start of 5000000 x points within radius 127 Km (3 found)\n");
|
||||
for(i=0;i<10000;i++)
|
||||
{
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp1,430000.0);
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
for(j=1;j<=500;j++)
|
||||
{
|
||||
coonum(&gcp1,j);
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp1,127000.0);
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
}
|
||||
}
|
||||
printf("End of timing test\n");
|
||||
}
|
||||
|
||||
if(mode==3)
|
||||
{
|
||||
printf("start of 10000 x points by count (2)\n");
|
||||
for(i=0;i<4;i++)
|
||||
printf("start of 5000000 x points by count (2)\n");
|
||||
for(i=0;i<10000;i++)
|
||||
{
|
||||
if(i==0)
|
||||
{
|
||||
gcp1.latitude = 44.999999;
|
||||
gcp1.longitude= 45.0000001;
|
||||
}
|
||||
if(i==1)
|
||||
{
|
||||
gcp1.latitude = -44.999999;
|
||||
gcp1.longitude= 45.0000001;
|
||||
}
|
||||
if(i==2)
|
||||
{
|
||||
gcp1.latitude = 44.999999;
|
||||
gcp1.longitude= -45.0000001;
|
||||
}
|
||||
if(i==3)
|
||||
{
|
||||
gcp1.latitude = -44.999999;
|
||||
gcp1.longitude= -45.0000001;
|
||||
}
|
||||
for(j=0;j<2500;j++)
|
||||
for(j=1;j<=500;j++)
|
||||
{
|
||||
coonum(&gcp1,j);
|
||||
list1 = GeoIndex_NearestCountPoints(gi,&gcp1,2);
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
}
|
||||
|
@ -949,6 +1000,134 @@ int main(int argc, char ** argv)
|
|||
|
||||
GeoIndex_free(gi);
|
||||
|
||||
/* */
|
||||
/* 400 - 499 */
|
||||
/* ========= */
|
||||
/* */
|
||||
|
||||
/* another batch of massive tests - again used as */
|
||||
/* comparisons - this time between 1.1 and 2.0 */
|
||||
|
||||
gi=GeoIndex_new();
|
||||
la=41.23456789;
|
||||
lo=39.87654321;
|
||||
for(i=0;i<20;i++)
|
||||
{
|
||||
for(j=1;j<30000;j++)
|
||||
{
|
||||
gcp.latitude = la;
|
||||
gcp.longitude= lo;
|
||||
gcp.data = &ix[(7*i+j)%1000];
|
||||
r = GeoIndex_insert(gi,&gcp);
|
||||
icheck(400,0,r);
|
||||
la+=19.5396157761;
|
||||
if(la>90.0) la-=180.0;
|
||||
lo+=17.2329155421;
|
||||
if(lo>180) lo-=360.0;
|
||||
}
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp,9800000.0);
|
||||
for(j=0;j<list1->length;j++) /* delete before freeing list1! */
|
||||
{
|
||||
r=GeoIndex_remove(gi,list1->coordinates+j);
|
||||
}
|
||||
gcmass(400+5*i,list1, np[i], hs[i]);
|
||||
}
|
||||
|
||||
GeoIndex_free(gi);
|
||||
|
||||
/* */
|
||||
/* 500 - 599 */
|
||||
/* ========= */
|
||||
/* */
|
||||
|
||||
/* This set of tests aims to cluster the points in */
|
||||
/* a sligtly more realistic way. */
|
||||
|
||||
gi=GeoIndex_new();
|
||||
for(i=1;i<135212;i++)
|
||||
{
|
||||
coonum(&gcp,i);
|
||||
r = GeoIndex_insert(gi,&gcp);
|
||||
icheck(501,0,r);
|
||||
if( (i%2)==0)
|
||||
{
|
||||
coonum(&gcp,i/2);
|
||||
r = GeoIndex_remove(gi,&gcp);
|
||||
icheck(502,0,r);
|
||||
}
|
||||
if( (i%13521)==0)
|
||||
{
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp,9800000.0);
|
||||
gcmass(505+4*(i/13521),list1,
|
||||
np1[i/13521 - 1], hs1[i/13521 - 1]);
|
||||
list1 = GeoIndex_NearestCountPoints(gi,&gcp,i/1703);
|
||||
gcmass(507+4*(i/13521),list1,i/1703,hs2[i/13521 - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
GeoIndex_free(gi);
|
||||
/* */
|
||||
/* 600 - 610 */
|
||||
/* ========= */
|
||||
/* */
|
||||
|
||||
/* Test a very large database - too big for V1.2! */
|
||||
if(mode==4)
|
||||
{
|
||||
gi=GeoIndex_new();
|
||||
for(i=1;i<21123212;i++)
|
||||
{
|
||||
coonum(&gcp,i);
|
||||
r = GeoIndex_insert(gi,&gcp);
|
||||
icheck(601,0,r);
|
||||
if( (i%2)==0)
|
||||
{
|
||||
coonum(&gcp,i/2);
|
||||
r = GeoIndex_remove(gi,&gcp);
|
||||
icheck(602,0,r);
|
||||
}
|
||||
if( (i%4541672)==0)
|
||||
{
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp,9800.0);
|
||||
gcmass(603+4*(i/4541672),list1,
|
||||
np4[i/4541672 - 1], hs4[i/4541672 - 1]);
|
||||
list1 = GeoIndex_NearestCountPoints(gi,&gcp,i/1832703);
|
||||
gcmass(605+4*(i/4541672),list1,i/1832703,hs5[i/4541672 - 1]);
|
||||
}
|
||||
}
|
||||
GeoIndex_free(gi);
|
||||
}
|
||||
/* */
|
||||
/* 900 - 999 */
|
||||
/* ========= */
|
||||
/* */
|
||||
|
||||
/* tests that ensure old bugs have not reappeared */
|
||||
|
||||
/* forgot to allow for distance greater than pi.radius */
|
||||
/* this went into sin(theta) to give small value, so it */
|
||||
/* found that many points were not within 30000 Km */
|
||||
|
||||
gi=GeoIndex_new();
|
||||
la=41.23456789;
|
||||
lo=39.87654321;
|
||||
for(j=1;j<50;j++)
|
||||
{
|
||||
gcp.latitude = la;
|
||||
gcp.longitude= lo;
|
||||
gcp.data = &ix[j];
|
||||
r = GeoIndex_insert(gi,&gcp);
|
||||
icheck(900,0,r);
|
||||
la+=19.5396157761;
|
||||
if(la>90.0) la-=180.0;
|
||||
lo+=17.2329155421;
|
||||
if(lo>180) lo-=360.0;
|
||||
}
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp,30000000.0);
|
||||
gcmass(901,list1, 49, 94065911);
|
||||
|
||||
GeoIndex_free(gi);
|
||||
|
||||
if(errors==0) {
|
||||
printf("Georeg Regression Program succeeded\n");
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue