mysql判断一个点是否在多边形内

以下是mysql备份


drop database if exists test;
create database if not exists test default charset=utf8;
use test;

CREATE TABLE `tower` ( 
  `id` int(11) NOT NULL auto_increment,
  name varchar(50), 
  `ploygongeo` text NOT NULL, 
  PRIMARY KEY  (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO tower (name, ploygongeo) VALUES('a', 'POLYGON((20.0 20.0, 20.0 30.0, 30.0 30.0, 30.0 20.0, 20.0 20.0))');
INSERT INTO tower (name, ploygongeo) VALUES('b', 'POLYGON((20.0 20.0, 20.0 40.0, 40.0 40.0, 40.0 20.0, 20.0 20.0))');
INSERT INTO tower (name, ploygongeo) VALUES('c', 'POLYGON((30.0 30.0, 30.0 40.0, 40.0 40.0, 40.0 30.0, 30.0 30.0))');


DROP TABLE IF EXISTS `gps`;
CREATE TABLE `gps` (
  `id` int(11) DEFAULT NULL ,
  lng decimal(10,7),
  lat decimal(10,7),
  `point` point DEFAULT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into gps(id, lng, lat, point) values(1, 15.0, 25.0, POINTFROMTEXT('POINT(15 25)'));
insert into gps(id, lng, lat, point) values(2, 25.0, 15.0, POINTFROMTEXT('POINT(25 15)'));
insert into gps(id, lng, lat, point) values(3, 25.0, 30.0, POINTFROMTEXT('POINT(25 30)'));
insert into gps(id, lng, lat, point) values(4, 35.0, 35.0, POINTFROMTEXT('POINT(35 35)'));

DELIMITER //  
 
CREATE FUNCTION myWithin(p POINT, poly POLYGON) RETURNS INT(1) DETERMINISTIC  
BEGIN  
DECLARE n INT DEFAULT 0;  
DECLARE pX DECIMAL(9,6);  
DECLARE pY DECIMAL(9,6);  
DECLARE ls LINESTRING;  
DECLARE poly1 POINT;  
DECLARE poly1X DECIMAL(9,6);  
DECLARE poly1Y DECIMAL(9,6);  
DECLARE poly2 POINT;  
DECLARE poly2X DECIMAL(9,6);  
DECLARE poly2Y DECIMAL(9,6);  
DECLARE i INT DEFAULT 0;  
DECLARE result INT(1) DEFAULT 0;  
SET pX = X(p);  
SET pY = Y(p);  
SET ls = ExteriorRing(poly);  
SET poly2 = EndPoint(ls);  
SET poly2X = X(poly2);  
SET poly2Y = Y(poly2);  
SET n = NumPoints(ls);  
WHILE i<n DO  
SET poly1 = PointN(ls, (i+1));  
SET poly1X = X(poly1);  
SET poly1Y = Y(poly1);  
IF ( ( ( ( poly1X <= pX ) && ( pX < poly2X ) ) || ( ( poly2X <= pX ) && ( pX < poly1X ) ) ) && ( pY > ( poly2Y - poly1Y ) * ( pX - poly1X ) / ( poly2X - poly1X ) + poly1Y ) ) THEN  
SET result = !result;  
END IF;  
SET poly2X = poly1X;  
SET poly2Y = poly1Y;  
SET i = i + 1;  
END WHILE;  
RETURN result;  
End;  
// 
DELIMITER ; 

select t.name, g.id from tower as t, gps as g where myWithin(g.point, PolygonFromText(t.ploygongeo)) > 0;


DELIMITER //  
 
CREATE FUNCTION myWithin2(pX DECIMAL(9,6), pY DECIMAL(9,6), poly POLYGON) RETURNS INT(1) DETERMINISTIC  
BEGIN  
DECLARE n INT DEFAULT 0;    
DECLARE ls LINESTRING;  
DECLARE poly1 POINT;  
DECLARE poly1X DECIMAL(9,6);  
DECLARE poly1Y DECIMAL(9,6);  
DECLARE poly2 POINT;  
DECLARE poly2X DECIMAL(9,6);  
DECLARE poly2Y DECIMAL(9,6);  
DECLARE i INT DEFAULT 0;  
DECLARE result INT(1) DEFAULT 0;  
SET ls = ExteriorRing(poly);  
SET poly2 = EndPoint(ls);  
SET poly2X = X(poly2);  
SET poly2Y = Y(poly2);  
SET n = NumPoints(ls);  
WHILE i<n DO  
SET poly1 = PointN(ls, (i+1));  
SET poly1X = X(poly1);  
SET poly1Y = Y(poly1);  
IF ( ( ( ( poly1X <= pX ) && ( pX < poly2X ) ) || ( ( poly2X <= pX ) && ( pX < poly1X ) ) ) && ( pY > ( poly2Y - poly1Y ) * ( pX - poly1X ) / ( poly2X - poly1X ) + poly1Y ) ) THEN  
SET result = !result;  
END IF;  
SET poly2X = poly1X;  
SET poly2Y = poly1Y;  
SET i = i + 1;  
END WHILE;  
RETURN result;  
End;  
// 
DELIMITER ;

select t.name, g.id from tower as t, gps as g where myWithin2(g.lng, g.lat, PolygonFromText(t.ploygongeo)) > 0;


 

posted @ 2017-09-14 09:11  微风吹过jy  阅读(1448)  评论(0)    收藏  举报