GeoHash补充

16 篇文章 0 订阅

最近在逛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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值