最近在逛cocoa的时候发现有一些小细节可以优化的
- 我们在设定二分精度时可以设置精度为个体的影响范围为精度,这样我们在搜索的时候可以直接用“==”而非“like”
- 我们可以不用进行base32编码,直接将其转化为unsinged long,可以大大减少计算,数据库使用字符串是因为很多数据库对字符串类型有很好的支持,c上面用字符串效率低得可以
- 之前那个写得仓促,有很多错误没整理,这次这个是完整版,当然,只是对我的游戏进行了优化,其他实现需要开发者动起手来
#pragma once
#include"BaseEntity.h"
#include"cocos2d.h"
#include<algorithm>
#include<bitset>
using namespace std;
class GeoHash
{
public:
static char base32_encode[32];
#define precision 10
#define binaryLength 20
#define world_size Vec2(1000,1000)//wathc out!if x!=y,there will be problems in combining binary code
protected://dividision
static void halfDivision(double, double, double,string&);//half division,declare the left part as ‘0‘ there
static bool between(double value,double min,double max)
{
return value > min&&value < max;
}
protected://convert to base32 code
static string base32Encoding(string);
public:
static string getIndex(Vec2);//get GeoHash code
static unsigned long getUlIndex(Vec2);
static std::vector<BaseEntity*> getNeighbors(Vec2, std::vector<BaseEntity*>);
};
char GeoHash::base32_encode[] = {
‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘,
‘8‘, ‘9‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘,
‘h‘, ‘j‘, ‘k‘, ‘m‘, ‘n‘, ‘p‘, ‘q‘, ‘r‘,
‘s‘, ‘t‘, ‘u‘, ‘v‘, ‘w‘, ‘x‘, ‘y‘, ‘z‘
};
string GeoHash::base32Encoding(string bitStr)
{
string outPutStr;
int count = 0;
while (bitStr.length>count * 5)
{
string eachStr;
for (int i = 0; i < 5; i++)
{
eachStr.push_back(bitStr.at(count + i));
}
int refer = 0;
for (int j = 0; j < 5; j++)
{
refer = refer * 2 + (eachStr[j] - ‘0‘);
}
outPutStr.push_back(base32_encode[refer]);
}
if (bitStr.length > count * 5)//push ‘0‘ to fill the rest
{
int addTo5 = (count + 1) * 5 - bitStr.length;
string eachStr;
for (int i = 0; i < addTo5; i++)
{
eachStr.push_back(‘0‘);
}
int refer = 0;
for (int j = 0; j < 5; j++)
{
refer = refer * 2 + (bitStr[j] - ‘0‘);
}
outPutStr.push_back(base32_encode[refer]);
}
return outPutStr;
}
string GeoHash::getIndex(Vec2 po)
{
string bitX;
halfDivision(world_size.x, world_size.y, po.x, bitX);
string bitY;
halfDivision(world_size.x, world_size.y, po.y, bitY);
//将xy轴组合,偶数位放y,奇数位放x
string totalBit;
for (int i = 0; i < bitX.size(); i++)
{
totalBit.push_back(bitY.at(i));
totalBit.push_back(bitX.at(i));
}
return base32Encoding(totalBit);
}
unsigned long GeoHash::getUlIndex(Vec2 po)
{
string bitX;
halfDivision(world_size.x, world_size.y, po.x, bitX);
string bitY;
halfDivision(world_size.x, world_size.y, po.y, bitY);
//将xy轴组合,偶数位放y,奇数位放x
string totalBit;
for (int i = 0; i < bitX.size(); i++)
{
totalBit.push_back(bitY.at(i));
totalBit.push_back(bitX.at(i));
}
bitset<binaryLength> binaryIndex(totalBit);
return binaryIndex.to_ulong();
}
void GeoHash::halfDivision(double min, double max, double value,string& bit)
{
if (max - min < precision)
{
return;
}
if (between(value, min, (min + max) / 2))
{
bit += "0";
halfDivision(value, min, (min + max) / 2, bit);
}
else
{
bit += "1";
halfDivision(value, (min + max) / 2, max, bit);
}
}
std::vector<BaseEntity*> GeoHash::getNeighbors(Vec2 centre, vector<BaseEntity*> preSelectedEntities)
{
vector<BaseEntity*> temp;
for_each(preSelectedEntities.cbegin(), preSelectedEntities.cend(), [&temp,centre](BaseEntity* entity){
if (entity->getGeoHashIndex() == getUlIndex(centre))
{
temp.push_back(entity);
}
});
return temp;
}
时间: 2024-10-24 15:44:30