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;
浙公网安备 33010602011771号