天干物燥,小心火燭,看了唐家三少的一篇自述,突然覺得我們和人家相比起來差距太大了,人家從小語文不好,雖然我們程序員半路出家的比較多,但是我還是覺得三少不錯,如果不看網絡小說,你們應該不曉得這個人的。
一個很簡單的APP,但是真心五臟俱全呀,數據庫就用了七個,還有莫名的爬蟲(老大為了省錢,爬的免費的天氣數據),新來的CTO看不下去了,當然,我也是新來的,鄙人到這家公司是今年三月份,CTO到這家公司是今年二月份,其實呢,看不下去也是有原因的,一個APP,就五六十張表,結果呢,整了七個數據庫,請注意,是七個數據庫,真心覺得沒有什么必要,於是乎,開始了混混烈烈的重構,原來的是用的ModelFirst,然后因為用了很多的數據庫訪問,所以呢,全部依賴注入,然后各種強關聯,其實這個是我最受不了的,因為我們做的這玩意很金融沒有關系呀,你還是全強關聯,真心有點受不了,強關聯就強關聯吧,數據還全部是真刪除,我去,我也是服了,然后呢,一條數據的生成過程也沒有,雖然我們查詢某些特定的存儲過程,可以得到某些需要的數據,但是呀,真心不想說什么了。
然后這個任務就交給了寶寶,說心里話,寶寶也是處呀,寶寶怎么知道搭建什么框架,最后采取了各種建議,寶寶決定,框架復雜了就好么?No,解決問題才是根本,於是乎,就開始了一個簡單工廠,完了之后加了一個緩存這就是現在的項目的基本框架,可能有些人任務寶寶是不是太隨意了,但是我看了重構與模式那本書之后,反正現在的我就認為簡單和復雜都是相對的,只有解決問題,這才是根本。反正一個工廠,誰負責接口,誰負責實現,這些都沒有問題,然后呢,訪問數據,因為個人能力的問題,也沒有想那么多,反正數據太多的時候就分表唄,至少寶寶是這么認為的。
額,好像扯遠了,直接上代碼(兩個點)半正矢公式 計算(Haversine formula):
public static class AreaOfTwoPoint
{
private static double EARTH_RADIUS = 6370996.81;
public static double AreaOfPoint(List<Point> list)
{
double result;
if (list.Count<Point>() == 2)
{
double lat = list[0].lat;
double lat2 = list[0].lat;
double lon = list[1].lon;
double lon2 = list[1].lon;
double num = AreaOfTwoPoint.Distance(lat, lon , lat2, lon2);
result = 3.1415926535897931 * Math.Pow(num / 2.0, 2.0);
}
else
{
result = 0.0;
}
return result;
}
private static double HvaerSin(double thera)
{
double num = Math.Sin(thera / 2.0);
return num * num;
}
private static double Distance(double lat1, double lon1, double lat2, double lon2)
{
lat1 = AreaOfTwoPoint.ConvertDegreesToRadians(lat1);
lon1 = AreaOfTwoPoint.ConvertDegreesToRadians(lon1);
lat2 = AreaOfTwoPoint.ConvertDegreesToRadians(lat2);
lon2 = AreaOfTwoPoint.ConvertDegreesToRadians(lon2);
double thera = Math.Abs(lon1 - lon2);
double thera2 = Math.Abs(lat1 - lat2);
double d = AreaOfTwoPoint.HvaerSin(thera2) + Math.Cos(lat1) * Math.Cos(lat2) * AreaOfTwoPoint.HvaerSin(thera);
return 2.0 * AreaOfTwoPoint.EARTH_RADIUS * Math.Asin(Math.Sqrt(d));
}
private static double ConvertDegreesToRadians(double degrees)
{
return degrees * 3.1415926535897931 / 180.0;
}
}
具體請參考:https://en.wikipedia.org/wiki/Haversine_formula
多個點,寶寶沒本事,沒有辦法,只能就說按照多邊形的投影走了,就是得到多邊形,然后切割成N-2個小三角。然后計算面積。
在這里必須要提醒的是,在處理的時候,有時候當三個點在經緯度上面顯示出來約等於一條直線的時候,因為小數問題,可能會被計算機識別為一條直線,那么,此時,得到的面積就會無窮大,所以,在實際運用過程中,請注意,每個點之間的對應的投影點,及時做好處理。
private double CalcArea(List<Points> list)
{
var count = list.Count;
if (count > 2)
{
//數組中的元素值
double mtotalArea = 0;
double LowX = 0.0;
double LowY = 0.0;
double MiddleX = 0.0;
double MiddleY = 0.0;
double HighX = 0.0;
double HighY = 0.0;
//三角形的邊
double AM = 0.0, BM = 0.0, CM = 0.0;
double AL = 0.0, BL = 0.0, CL = 0.0;
double AH = 0.0, BH = 0.0, CH = 0.0;
double CoefficientL = 0.0, CoefficientH = 0.0;
double ALtangent = 0.0, BLtangent = 0.0, CLtangent = 0.0;
double AHtangent = 0.0, BHtangent = 0.0, CHtangent = 0.0;
double ANormalLine = 0.0, BNormalLine = 0.0, CNormalLine = 0.0;
//定位置
double OrientationValue = 0.0;
//余弦函數
double AngleCos = 0.0;
double Sum1 = 0.0, Sum2 = 0.0;
double Count1 = 0,Count2 = 0;
double Sum = 0.0;
double Radius = 6370996.81;//地球半徑
for (int i = 0; i < count; i++)
{
//坐標系中,一般X代表緯度(Lon),Y代表經度(Lat)
if (i == 0)
{
LowX = (list[count - 1].Lon) * Math.PI / 180;
LowY = (list[count - 1].Lat) * Math.PI / 180;
MiddleX = (list[0].Lon) * Math.PI / 180;
MiddleY = (list[0].Lat) * Math.PI / 180;
HighX = (list[1].Lon) * Math.PI / 180;
HighY = (list[1].Lat) * Math.PI / 180;
}
else if (i == count - 1)
{
LowX = (list[count-2].Lon) * Math.PI / 180;
LowY = (list[count-2].Lat) * Math.PI / 180;
MiddleX = (list[count - 1].Lon) * Math.PI / 180;
MiddleY = (list[count - 1].Lat) * Math.PI / 180;
HighX = (list[0].Lon) * Math.PI / 180;
HighY = (list[0].Lat) * Math.PI / 180;
}
else
{
LowX = (list[i-1].Lon) * Math.PI / 180;
LowY = (list[i - 1].Lat) * Math.PI / 180;
MiddleX = (list[i].Lon) * Math.PI / 180;
MiddleY = (list[i].Lat) * Math.PI / 180;
HighX = (list[i+1].Lon) * Math.PI / 180;
HighY = (list[i+1].Lat) * Math.PI / 180;
}
AM = Math.Cos(MiddleY) * Math.Cos(MiddleX);
BM = Math.Cos(MiddleY) * Math.Sin(MiddleX);
CM = Math.Sin(MiddleY);
AL = Math.Cos(LowY) * Math.Cos(LowX);
BL = Math.Cos(LowY) * Math.Sin(LowX);
CL = Math.Sin(LowY);
AH = Math.Cos(HighY) * Math.Cos(HighX);
BH = Math.Cos(HighY) * Math.Sin(HighX);
CH = Math.Sin(HighY);
CoefficientL = (AM * AM + BM * BM + CM * CM) / (AM * AL + BM * BL + CM * CL);
CoefficientH = (AM * AM + BM * BM + CM * CM) / (AM * AH + BM * BH + CM * CH);
ALtangent = CoefficientL * AL - AM;
BLtangent = CoefficientL * BL - BM;
CLtangent = CoefficientL * CL - CM;
AHtangent = CoefficientH * AH - AM;
BHtangent = CoefficientH * BH - BM;
CHtangent = CoefficientH * CH - CM;
AngleCos = (AHtangent * ALtangent + BHtangent * BLtangent + CHtangent * CLtangent) / (Math.Sqrt(AHtangent * AHtangent + BHtangent * BHtangent + CHtangent * CHtangent) * Math.Sqrt(ALtangent * ALtangent + BLtangent * BLtangent + CLtangent * CLtangent));
AngleCos = Math.Acos(AngleCos);//余弦角度
ANormalLine = BHtangent * CLtangent - CHtangent * BLtangent;
BNormalLine = 0 - (AHtangent * CLtangent - CHtangent * ALtangent);
CNormalLine = AHtangent * BLtangent - BHtangent * ALtangent;
if (AM != 0)
OrientationValue = ANormalLine / AM;
else if (BM != 0)
OrientationValue = BNormalLine / BM;
else
OrientationValue = CNormalLine / CM;
if (OrientationValue > 0)
{
Sum1 += AngleCos;
Count1++;
}
else
{
Sum2 += AngleCos;
Count2++;
}
}
if (Sum1 > Sum2)
{
Sum = Sum1 + (2 * Math.PI * Count2 - Sum2);
}
else
{
Sum = (2 * Math.PI * Count1 - Sum1) + Sum2;
}
return Math.Abs((Sum - (count - 2) * Math.PI) * Radius * Radius);
}
return 0;
}
如有侵權,請聯系本人,謝謝。
