百度地图和高德地图坐标系的互相转换
GPS、谷歌、百度、高德坐标相互转换
一、在进行地图开发过程中,我们一般能接触到以下三种类型的地图坐标系:
1.WGS-84原始坐标系,一般用国际GPS纪录仪记录下来的经纬度,通过GPS定位拿到的原始经纬度,Google和高德地图定位的的经纬度(国外)都是基于WGS-84坐标系的;但是在国内是不允许直接用WGS84坐标系标注的,必须经过加密后才能使用;
2.GCJ-02坐标系,又名“火星坐标系”,是我国国测局独创的坐标体系,由WGS-84加密而成,在国内,必须至少使用GCJ-02坐标系,或者使用在GCJ-02加密后再进行加密的坐标系,如百度坐标系。高德和Google在国内都是使用GCJ-02坐标系,可以说,GCJ-02是国内最广泛使用的坐标系;
3.百度坐标系:bd-09,百度坐标系是在GCJ-02坐标系的基础上再次加密偏移后形成的坐标系,只适用于百度地图。(目前百度API提供了从其它坐标系转换为百度坐标系的API,但却没有从百度坐标系转为其他坐标系的API)
二、为什么会发生偏移?
1.由于坐标系之间不兼容,如在百度地图上定位的经纬度拿到高德地图上直接描点就肯定会发生偏移;只考虑国内的情况,高德地图和Google地图是可以不经过转换也能够准确显示的(在国内用的都是GCJ-02坐标系);下面是收录了网上的WGS-84,GCJ-02,百度坐标系(bd-09)之间的相互转换的方法,经测试,是转换后相对准确可用的。
三、代码
Java:
package com.zehin.map.util;
public class GPSUtil {
public static double pi = 3.1415926535897932384626;
public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
public static double a = 6378245.0;
public static double ee = 0.00669342162296594323;
public static double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
public static double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
* Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
public static double[] transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[]{lat,lon};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLat,mgLon};
}
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
/**
* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
*
* @param lat
* @param lon
* @return
*/
public static double[] gps84_To_Gcj02(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[]{lat,lon};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLat, mgLon};
}
/**
* * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
* */
public static double[] gcj02_To_Gps84(double lat, double lon) {
double[] gps = transform(lat, lon);
double lontitude = lon * 2 - gps[1];
double latitude = lat * 2 - gps[0];
return new double[]{latitude, lontitude};
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
*
* @param lat
* @param lon
*/
public static double[] gcj02_To_Bd09(double lat, double lon) {
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
double[] gps = {tempLat,tempLon};
return gps;
}
/**
* * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param
* bd_lat * @param bd_lon * @return
*/
public static double[] bd09_To_Gcj02(double lat, double lon) {
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta);
double tempLat = z * Math.sin(theta);
double[] gps = {tempLat,tempLon};
return gps;
}
/**将gps84转为bd09
* @param lat
* @param lon
* @return
*/
public static double[] gps84_To_bd09(double lat,double lon){
double[] gcj02 = gps84_To_Gcj02(lat,lon);
double[] bd09 = gcj02_To_Bd09(gcj02[0],gcj02[1]);
return bd09;
}
public static double[] bd09_To_gps84(double lat,double lon){
double[] gcj02 = bd09_To_Gcj02(lat, lon);
double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
//保留小数点后六位
gps84[0] = retain6(gps84[0]);
gps84[1] = retain6(gps84[1]);
return gps84;
}
/**保留小数点后六位
* @param num
* @return
*/
private static double retain6(double num){
String result = String .format("%.6f", num);
return Double.valueOf(result);
}
}
c#:
public class GpsUtil
{
public static double pi = 3.1415926535897932384626;
public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
public static double a = 6378245.0;
public static double ee = 0.00669342162296594323;
public static double TransformLat(double x, double y)
{
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ 0.2 * Math.Sqrt(Math.Abs(x));
ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
public static double TransformLon(double x, double y)
{
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
* Math.Sqrt(Math.Abs(x));
ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
public static double[] transform(double lat, double lon)
{
if (OutOfChina(lat, lon))
{
return new double[] { lat, lon };
}
double dLat = TransformLat(lon - 105.0, lat - 35.0);
double dLon = TransformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.Sin(radLat);
magic = 1 - ee * magic * magic;
double SqrtMagic = Math.Sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * SqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / SqrtMagic * Math.Cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[] { mgLat, mgLon };
}
public static bool OutOfChina(double lat, double lon)
{
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
/**
* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
*
* @param lat
* @param lon
* @return
*/
public static double[] Gps84ToGcj02(double lat, double lon)
{
if (OutOfChina(lat, lon))
{
return new double[] { lat, lon };
}
double dLat = TransformLat(lon - 105.0, lat - 35.0);
double dLon = TransformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.Sin(radLat);
magic = 1 - ee * magic * magic;
double SqrtMagic = Math.Sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * SqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / SqrtMagic * Math.Cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[] { mgLat, mgLon };
}
/**
* * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
* */
public static double[] Gcj02ToGps84(double lat, double lon)
{
double[] gps = transform(lat, lon);
double lontitude = lon * 2 - gps[1];
double latitude = lat * 2 - gps[0];
return new double[] { latitude, lontitude };
}
/// <summary>
/// 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
/// 高德谷歌转为百度
/// </summary>
/// <param name="lat"></param>
/// <param name="lon"></param>
/// <returns></returns>
public static double[] Gcj02ToBd09(double lat, double lon)
{
double x = lon, y = lat;
double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi);
double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi);
double tempLon = z * Math.Cos(theta) + 0.0065;
double tempLat = z * Math.Sin(theta) + 0.006;
double[] gps = { tempLat, tempLon };
return gps;
}
/// <summary>
/// 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标
/// 百度坐标转为高德谷歌坐标
/// </summary>
/// <param name="lat"></param>
/// <param name="lon"></param>
/// <returns></returns>
public static double[] Bd09ToGcj02(double lat, double lon)
{
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi);
double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * x_pi);
double tempLon = z * Math.Cos(theta);
double tempLat = z * Math.Sin(theta);
double[] gps = { tempLat, tempLon };
return gps;
}
/// <summary>
/// gps84转为bd09
/// GPS坐标转为百度坐标
/// </summary>
/// <param name="lat"></param>
/// <param name="lon"></param>
/// <returns></returns>
public static double[] Gps84ToBd09(double lat, double lon)
{
double[] gcj02 = Gps84ToGcj02(lat, lon);
double[] bd09 = Gcj02ToBd09(gcj02[0], gcj02[1]);
return bd09;
}
/// <summary>
/// 百度坐标转成GPS坐标
/// </summary>
/// <param name="lat"></param>
/// <param name="lon"></param>
/// <returns></returns>
public static double[] Bd09ToGps84(double lat, double lon)
{
double[] gcj02 = Bd09ToGcj02(lat, lon);
double[] gps84 = Gcj02ToGps84(gcj02[0], gcj02[1]);
//保留小数点后六位
gps84[0] = Retain6(gps84[0]);
gps84[1] = Retain6(gps84[1]);
return gps84;
}
/// <summary>
/// 保留小数点后六位
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private static double Retain6(double num)
{
String result = String.Format("%.6f", num);
return Double.Parse(result);
}
}
作者:青檬可乐_
链接:https://www.jianshu.com/p/d3dd4149bb0b
四种Sandcastle方法生成c#.net帮助类帮助文档
方法一、Visual Studio新建documentation生成帮助文档
前段时间在网上收集和自己平时工作总结整理了《干货,比较全面的c#.net公共帮助类》,整理完成上传github之后我又想,既然是帮助类,总得有个帮助文档于是乎想到了Sandcastle,Sandcastle是微软官方生成帮助文档这发面的工具。
它可以配合Microsoft Visual Studio生成的dll和xml注释文件生成完整的帮助文档。
结合可视化工具Sandcastle Help File Builder,简单直接,还能生成各种属性的说明。
支持Helpe1x:chm, Helper2x:Hxs, Website,HelperView等多种格式而且扩展灵活功能强大,下面我们就看一下怎样用Sandcastle生成chm文档。
一、下载
首先我们前往CodePlex下载Sandcastle,地址:http://sandcastle.codeplex.com/
然后下载Sandcastle Help File Builder,地址:http://shfb.codeplex.com/,点击右边download下载即可。
二、安装
Sandcastle,直接Next就可以了,Sandcastle Help File Builder要说一下的是,在MAML Schema IntelliSense for Visual Studio为vs安装插件的时候一定要勾选上,不然新建项目的时候会没有这个选项。
三、设置
在生成这里设置xml文档文件,保存,编译之后在你项目目录的bin\Debug就会看到生成的xml文件了。
四、新建项目documentation
首先 新建documentation项目,这里就是安装Sandcastle Help File Builder的时候勾选上vs的原因。如果没有勾选上,这里新建的时候没有这个选项的。
然后勾选上你刚才已经生成的dll和xml文件,右键属性如上图写上标题。编译生成即可。这里有一点要注意,可能会报错(SHFB: Error BE0037: Could not find the path the the HTML Help 1 compiler. See the error number topic in the help file for details.),是没有安装Microsoft HTML Help,当然你安装了之后可以跳过此步骤。
如果没有安装Microsoft HTML Help,我们到https://www.microsoft.com/en-us/download/details.aspx?id=21138去下载Microsoft HTML Help然后安装。
五、生成
如果没有报错,直接生成,然后我们项目目录的Help就可以看到生成的帮助文档了
是不是很简单。这样我们就生成了之前帮助类的帮助文档了。另外我再介绍几种生成帮助文档的方式。
方法二、cmd生成帮助文档
在Sandcastle和Sandcastle Help File Builder都安装好的前提下,
在我们将步骤三生成的Common.Utility.dll 和Common.Utility.xml 拷贝至C:\Program Files (x86)\Sandcastle\Examples\Sandcastle(Sandcastle安装路径)下面。
这种方法是一种批处理的方法,然后我们打开cmd,输入build_sandcastle.bat vs2005 Common.Utility 回车,然后进行批处理。
我们会看到这目录下生成很多文件夹,如果过程没有报错,我们在chm 文件夹就会看到我们生成的帮助文档了。
方法三、SandcastleBuilderGUI
我们根据上面的设置,然后引入Common.Utility.dll 和Common.Utility.xml,生成即可。相关设置参考:http://www.cnblogs.com/lonely7345/archive/2010/01/13/1647245.html
方法四、Sandcastle Help File Builder可视化工具
通过Sandcastle的图形操作界面。在C:\Program Files (x86)\Sandcastle\Examples\Generic\SandcastleGui.exe下打开如下界面。
根据图上相关设置然后点击Build按钮。即可生成帮助文档,是不是更方便简洁。
当然前提是也是生成Common.Utility.dll 和Common.Utility.xml的情况下面。
如上四种方法生成帮助文档。至此c#.net帮助类告一段落。
本文来自:http://www.cnblogs.com/anyushengcms/p/7682501.html
文档API生成神器SandCastle使用心得
一、功能描述
关于Sandcastle网上的参考资料相对较少,Google出来很多资料都是全英文的,相对于我这种英语渣渣看起来还是很费劲的。
言简意赅,Sandcastle主要功能是能够将C#类生成类似MSDN风格帮助文档的工具,支持本地化,并提供一个基本的命令行编译器界面和一个Visual Studio插件。
优点:
1.生成简单,工作量小,几分钟之内就能完成一个项目的api文档制作。
2.自动生成索引项、内容项目表、主题块和页面布局,提高一致性和熟悉程度。
3.代码高亮,易读性强
4.生成api界面美观。
缺点:
只支持visual studio,意思是只支持微软旗下产品。
二、下载与安装
我是在github中下载的sandcastle,链接隧道 https://github.com/EWSoftware/SHFB/releases,下载时需注意版本号,我没有看版本备注就直接下载了最新版本的sandcastle,安装后生成api后直接报错了,不能生成成功。后来排查后发现是版本问题,我的idea是vs2013,当前sandcastle版本只支持最低vs2015的Idea,所以一直报错。
这个版本中备注描述的很清楚,这是最后一个支持vs2013的版本。
三、配置SandCastle
主要配置详解
3.1 首先打开SandCastle,新建一个文件用来存放sandcastle新建的工程文件,类似vs中新建项目后的解决方案。
3.2 在项目属性中选择需要生成的api类型,如果你想生成类似MSDN帮助文档风格,就可以选择Website。
3.3 Framework version 选择生成解决方案的framework版本号,如果与之不一致,则生成api时会报错
chm类型生成的文档(参考)
website类型
在vs中的引用类按f1可打开该类的帮助文档。
3.4.点击Project Explorer,点击新建的api文件,右击Documentation Sources选择Add Document Source
3.5 选择的类库生成属性中需在输出中xml文档文件复选框打钩在生成,否则生成api无效。
3.6 选择所需生成的类库,也就是后缀名为.csproj的文件即可
四、常见错误
4.1 SHFB: Error BE0043: Unexpected error detected in last build step. See output above for details.
错误信息的意思是缺少程序集的引用,那我就需要把不用的程序集剔除掉,那么如何剔除呢,请看一下操作
4.2 SHFB: Error BE0064: BUILD CANCELLED BY USER
这个错误是由于框架版本不一致所引起的,也就是如果该项目生成时选择的framework版本为4.5,而sandcastle配置的是4.0版本,那么就会报错。
4.3 Sandcastle [丢失<summary> 节点]的问题
遇到这个问题,首先查看代码注释是否有<summary>节点,是否规范。
然后有人会说我明明在代码中已经定义了summary 节点,为什么还会报这种错呢?
这种我尝试最暴力的方法就是让它不提示这个错误,在sandcastle中设置missing tags,取消<summary> elments 的报错信息,点击取消复选框,哪个节点的报错就不会报错。
五、SandCastle在vs中的使用
前面说了都是sandcastle软件的独立使用,还有一种方法是将其集成在vs中使用,使用方法与独立使用相差不大。
如果是已经安装了sandcastle,那么请忽略以下安装步骤。
5.1 在sandcastle目录文件夹下找到后缀为vsix的插件,双击执行,如果弹出此扩展已安装,那么表示安装成功
5.2 在需生成api的项目下添加项目,如果已安装成功,那么在已安装的扩展插件中Documentation就会出现sandcastle插件,输入名称,存放位置,点击确定添加。
5.3.添加完成后,此时的操作和不是集成在vs中的无明显差别,如需生成文档,右击新建的文件,点击生成即可。
六、运行生成API
上面所有步骤完成之后就可以运行sandcastle了,点击build the help file生成
生成成功之后在当前生成目录下,查看生成文件是否齐全,如果文件不全,那么原因在于生成不成功或配置不正确
双击index.html查看api中是否有报错信息,代码是否高亮,链接是否可点。
最近才开始学习ASP.NET Core,发现社区的学习资料很多,但是相关的视频教程不是很多,52ABP官方有两个视频教程,但是ABP框架比较臃肿,初学者学起来有点吃力,所以还是推荐大家先啃书或者官方文档,有点基础知识了再看视频教程学习,个人觉得这样学起来比较好一点。经过一段时间的学习后我找到一些相关的免费视频教程,发现还是不错,推荐给大家,共同学习,共同进步!
一,文档教程汇总:
零度教程(零度网站上面有很多免费博客和视频教程)
二,视频教程汇总:
说明:我比较喜欢在B站上看视频教程,别人都是在上面追番,我却喜欢在上面看一些教程,这是我所有的B站教程收藏夹,因为上面有很多其他地方要收费教程和一些YouTube上搬运的视频,而且还没广告,当然也有不少原创的UP主,我比较喜欢的是Anduin2017 ,他录制了很多不错视频教程,推荐大家去看一下。这是我在B站正在学习或者学过的.NET Core视频教程的收藏夹。大家不嫌麻烦也可以关注一下我,我后面也打算在上面做一些技术视频教程。当然网上还有一些不错的收费视频教程,作为学生党的我也没有这个余钱去买,一是比较贵,二是我也觉得没必要,把下面这个教程多看几遍,然后动手实践一下,再多啃几本书和浏览一些博客就够了。
1,NewsPublish项目 — 在线视频地址,这个新闻发布系统主要由Asp.Net Core&Sql Server数据库搭建,比较适合初学者,如果大家觉得Sql Server 2017客户端比较大,吃内存的话,推荐大家用微软的Azure Data Studio ,这个Sql Server的GUI比较轻量级,界面也很友好,当然功能肯定也没有Sql Server 2017那么多,不过一般对于我来说够用了。
另外推荐两个有用的网站:
- 在线生成数据库测试数据生成网站:https://www.mockaroo.com/
- 在线连接字符串参考网站:https://www.connectionstrings.com/
2,草根专栏的教程 — ASP.NET Core 2.1 + Ng6实战、GraphQL in ASP.NET Core 后面这个视频教程也不太适合初学者,至少的有ASP.NET Core Web API相关的基础知识才行,先看第一个视频教程吧,结合作者的博客一起学习。
3,52ABP的视频教程 —ASP.NET Core 2.X ABP框架入门教程、Asp.NET Core2.0 EF Core 项目实战入门视频教程,作者将ABP框架用ASP.NET Core实现的,里面涉及的知识面比较广,可以结合52ABP的官方文档学习,第一个教程以 .NET Core + Entity Framework Core为基础,中间涉及到各种插件和组件如: AutoMapper、CodeFirst、IOC,仓储、MVC和EF,比较适合初学者。后面这个视频是收费的教程,不过也不贵,才35元,肯定要支持作者。
4,首届.NET Core开源峰会演讲 — 这个虽然不是做.NET Core项目教程,但是这个dnc开源峰会目前是由社区驱动的最高.NET Core在线开源会议,肯定是要去了解一下的,这里是官网Github,B站dncto视频地址 ,第二届会议将会在2018年12月30召开,当然如果你是.NET Core开发大牛,也可以参加讲师报名。
三,项目案例汇总:
Github上的一个开源项目,目标是建立一个由知名资源组成的分类社区驱动集合。
Coding The World!
https://www.cnblogs.com/ckjbug/archive/2018/10/09/9763503.html