<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
		<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.js"></script>

  </head>
<body>
  <div id="main"></div>
    </body>
</html>

var bounds = null; 
var isPointInPolygon = function(point, pts){
       

        //下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
        //基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
        //在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。

        var N = pts.length;
        var boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
        var intersectCount = 0;//cross points count of x
        var precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        var p1, p2;//neighbour bound vertices
        var p = point; //测试点

        p1 = pts[0];//left vertex
        for(var i = 1; i <= N; ++i){//check all rays
            if(p.equals(p1)){
                return boundOrVertex;//p is an vertex
            }

            p2 = pts[i % N];//right vertex
            if(p.lat < Math.min(p1.lat, p2.lat) || p.lat > Math.max(p1.lat, p2.lat)){//ray is outside of our interests
                p1 = p2;
                continue;//next ray left point
            }

            if(p.lat > Math.min(p1.lat, p2.lat) && p.lat < Math.max(p1.lat, p2.lat)){//ray is crossing over by the algorithm (common part of)
                if(p.lng <= Math.max(p1.lng, p2.lng)){//x is before of ray
                    if(p1.lat == p2.lat && p.lng >= Math.min(p1.lng, p2.lng)){//overlies on a horizontal ray
                        return boundOrVertex;
                    }

                    if(p1.lng == p2.lng){//ray is vertical
                        if(p1.lng == p.lng){//overlies on a vertical ray
                            return boundOrVertex;
                        }else{//before ray
                            ++intersectCount;
                        }
                    }else{//cross point on the left side
                        var xinters = (p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng;//cross point of lng
                        if(Math.abs(p.lng - xinters) < precision){//overlies on a ray
                            return boundOrVertex;
                        }

                        if(p.lng < xinters){//before ray
                            ++intersectCount;
                        }
                    }
                }
            }else{//special case when ray is crossing through the vertex
                if(p.lat == p2.lat && p.lng <= p2.lng){//p crossing over p2
                    var p3 = pts[(i+1) % N]; //next vertex
                    if(p.lat >= Math.min(p1.lat, p3.lat) && p.lat <= Math.max(p1.lat, p3.lat)){//p.lat lies between p1.lat & p3.lat
                        ++intersectCount;
                    }else{
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2;//next ray left point
        }

        if(intersectCount % 2 == 0){//偶数在多边形外
            return false;
        } else { //奇数在多边形内
            return true;
        }
    };
		
$(document).ready(function(){
  $('#main').append('<div>Do while get the data</div>');
  
	$.get('https://lc-OnsG2j7w.cn-n1.lcfile.com/9777e2380374792ea6d6.json',function(res){
			bounds = res.bounds;
    
    $('#main').append('<div>Start testing!</div>');
    $('#main').append('<div>------</div>');
    
  doTest(200);
  doTest(600);
  doTest(1000);
  doTest(10000);
    
    $('#main').append('<div>------</div>');
    
  $('#main').append('<div>Done!</div>');
	}); 
  
  getTestData = function(dataLength){
    var points = []; 
		for(var i=0;i<dataLength;i++){
			points.push({
				lat:_.random( 20.000001,52.99999),
				lng:_.random(99.000000,150.999939),
        equals:function(){
          return false;
        }
			});
		};
    
    return points;
  }
	
	doTest = function(dataLength){
		var points = getTestData(200); 
		for(var i=0;i<600;i++){
			points.push({
				lat:_.random( 20.000001,52.99999),
				lng:_.random(99.000000,150.999939),
        equals:function(){
          return false;
        }
			});
    };
    
   var startTime = new Date();
		for(var i=0;i<points.length;i++){
			var p = points[i];
			console.log(p.lat +','+p.lng+' is in china: '+isPointInPolygon(p,bounds));
		} 
    $('#main').append('<div>'+dataLength+ ' many datas, Total times: '+ (new Date().getTime() - startTime.getTime())+' ms '+'</div>');
	};
	
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.