轉載幾個蜂窩小區的數學模型
設計模型:
1、 設計一個XY軸座標系,1是原點,座標(0,0)
2、 X軸:49、28、13、4、1、7、19、37、61的六邊形中心所在直線(如圖),1和7之間的距離是7,對應座標軸的1個刻度
3、 Y軸:45、25、11、3、1、6、17、34、57 的六邊形中心所在直線(如圖),同樣刻度是1
4、 從內向外都是有一個個圈(Cycle)組成,1是第0圈,2-7是第1圈,8-19是第2圈(見圖上有顏色的六邊形組成的一個圈)
5、 每個圈都有6條邊(除了第0圈只有1個)
6、 第N圈的每條邊都有N個六邊形(如圖:有顏色的六邊形組成的第2圈,相同顏色的組成一條邊)
7、 第N圈的起點編號是CycStartID(n),結束編號是CycEndID(n),那麼有:CycStartID(n)=CycEndID(n-1)+1,CycEndID(n) = CycStartID+6n-1
8、 每個圈的移動順序是(舉例第2圈):7-(Down)-8-(LeftDown)-9-(LeftUp)-10-(LeftUp)-11-(Up)-12-(Up)-13-(RightUp)-14-(RightUp)-15-(RightDown)-16-(RightDown)-17-(Down)-18-(Down)-19
9、 從上述的移動可以看出,第N圈的第一條邊(比如第2圈的8,9)的順序都是:先Down à 循環N-1次LeftDown à 循環N次LeftUP à 循環N次Up à 循環N次RightUp à 循環N次RightDown à 循環N次Down
10、 從圖中座標可以看出,每次移動的座標變化規律如下:
a) Down=(1,-1),
b) LeftDown=(0,-1),
c) LeftUp=(-1,0),
d) Up=(-1,1),
e) RightUp=(0,1)
f) RightDown=(1,0)
g) Down=(1,-1)
11、 從圖中座標可以看出,在第一、三象限的距離是X或Y的最大值,而第二、四象限的距離是X+Y。因此,如果兩個編號的座標相減(A-B),如果落在第一三象限,則就是(A-B)的X或Y的最大值的絕對值。否則落在第二四象限,就是(A-B)的X和Y的絕對值的和。
思路2:
通過數學歸納,我們可以知道,從第2圈開始,第n圈所擁有的數字個數是6*(n-1),那麼,第n圈的最大值是:1+6*(2-1)+6*(3-1)+……+6*(n-1)=3*n*(n-1)+1;第n圈的最小值即第n-1圈的最大值+1。通過上述公式,我們可以知道任意數字所在的圈數n。
觀察上圖,我們發現每一圈數字組成的圖形是一個正六邊形, X軸上分別是正六邊形的第3個頂點(負值)和第6個頂點,Y軸上分別是六邊形的第2個頂點(負值)和第5個頂點,同時第6個頂點也是圈中的最大值。
正六邊形的每一條邊的長度包含N個數字,從而,我們可以從第6個頂點反向回推各個頂點的值。比如:
第5個頂點的值是:(3*n*(n-1)+1)-(n-1);
第4個頂點的值是:(3*n*(n-1)+1)-(n-1)-(n-1);
…………
通過已知的6個頂點的取值,我們可以獲取到當前數字所在哪一條邊,從而根據不同的邊計算出具體數字所在的二維座標,從而將蜂窩最短距離的計算轉換成二維座標中兩點間距離的計算。
代碼展示:
struct XY
{
int x;
int y;
};
// 獲取某點的座標
void GetValueCoordinate(int iValue, XY &strXY)
{
// 座標原點爲(0,0)
if (1 == iValue)
{
strXY.x = 0;
strXY.y = 0;
return;
}
// 1、定位該點所在的圈數
// 第n圈的元素個數:6*(n-1)
// 第n圈的起始元素:3n^2-9n+8
// 第n圈的結束元素:3n^2-3n+1
int n = 1;
while(iValue > (3*n*n-3*n+1))
{
n++;
}
// 2、定位該點所在的邊,從而獲取到象限信息
// 六邊形每條邊所含點數爲當前圈數n,以圈中最大點數爲第6個頂點,那麼對應6個頂點數分別是:
// 第6個頂點:3n^2-3n+1
// 第5個頂點:3n^2-3n+1-(n-1)=3n^2-4n+2
// 第4個頂點:3n^2-4n+2-(n-1)=3n^2-5n+3
// 第3個頂點:3n^2-5n+3-(n-1)=3n^2-6n+4
// 第2個頂點:3n^2-6n+4-(n-1)=3n^2-7n+5
// 第1個頂點:3n^2-7n+5-(n-1)=3n^2-8n+6
// X軸上分別是六邊形的第3個頂點和第6個頂點
// X軸:49、28、13、4、1、7、19、37、61
// Y軸上分別是六邊形的第2個頂點和第5個頂點
// Y軸:45、25、11、3、1、6、17、34、57
// 1、2頂點之間,第4象限
if (((3*n*n-8*n+6) <= iValue) && (iValue < (3*n*n-7*n+5)))
{
// X軸=第2個頂點-點數
strXY.x = (3*n*n-7*n+5)-iValue;
// Y軸固定爲圈數-1(負值)
strXY.y = -(n-1);
}
// 2、3頂點之間,第3象限
else if (((3*n*n-7*n+5) <= iValue) && (iValue < (3*n*n-6*n+4)))
{
// X軸=圈數-1-偏移(偏移=第3個頂點-點數)(負值)
strXY.x = -((n-1) - ((3*n*n-6*n+4)-iValue));
// Y軸=圈數-1-偏移(偏移=點數-第2個頂點)(負值)
strXY.y = -((n-1) - (iValue - (3*n*n-7*n+5)));
}
// 3、4頂點之間,第2象限
else if (((3*n*n-6*n+4) <= iValue) && (iValue < (3*n*n-5*n+3)))
{
// X軸固定爲圈數-1(負值)
strXY.x = -(n-1);
// Y軸=點數-第3個頂點
strXY.y = iValue - (3*n*n-6*n+4);
}
// 4、5頂點之間,第2象限
else if (((3*n*n-5*n+3) <= iValue) && (iValue < (3*n*n-4*n+2)))
{
// X軸=第5個頂點-點數(負值)
strXY.x = -((3*n*n-4*n+2)-iValue);
// Y軸固定爲圈數-1
strXY.y = (n-1);
}
// 5、6頂點之間,第1象限
else if (((3*n*n-4*n+2) <= iValue) && (iValue < (3*n*n-3*n+1)))
{
// X軸=圈數-1-偏移(偏移=第6個頂點-點數)
strXY.x = (n-1) - ((3*n*n-3*n+1)-iValue);
// Y軸=圈數-1-偏移(偏移=點數-第5個頂點)
strXY.y = (n-1) - (iValue - (3*n*n-4*n+2));
}
// 6、1頂點之間,第4象限
else
{
// X軸固定爲圈數-1
strXY.x = (n-1);
// 如果是當前圈的結束元素(第6個頂點),Y軸直接賦0值
// 否則,Y軸=點數-第n圈的起始元素+1(負值)
if (iValue == (3*n*n-3*n+1))
{
strXY.y = 0;
}
else
{
strXY.y = -(iValue - (3*n*n-9*n+8) + 1);
}
}
return;
}
思路3
思路4:
數學方法思路:
1)先定義兩個座標系
一個是二維斜座標,X軸(1,2,9,22,41,...),Y軸(1,7,19,37,...),比如19是XY(0,2),30是XY(-2,-1)
一個是LAS(層layer>0,扇區area∈[0,5],序號sn∈[0,lay-1]),比如19是LAS(2,5,1),30是LAS(3,3,1)
2)第一步:把兩個輸入數值分別轉換成LAS座標,再從LAS座標轉成XY座標
這兩個轉換可都用數學公式推導出來(提醒:求LAS時可解1元2次方程;求XY時要根據扇區area分別推導)
3)第二步:兩個數值的XY向量相減,得到從原點出發的長度向量
4)第三步:從原點出發的長度向量XY座標,再轉回LAS 座標,最後的“層Layer”即兩數距離
主要推導過程和參考實現:
1)LAS座標
Layer是層數(>0),每一層的起點是 f(layer) = 3*layer*(layer -1)+2,每層有6* layer個數;
如果輸入數字a,則a所在的層就是 f(layer) <= a 的最大layer
求解一元二次方程,得到:
參考代碼:
2)LAS座標轉XY座標
參考代碼:
3)XY座標轉LAS座標
參考代碼(上面的逆過程):