最近在做船舶运输的相关服务,需要在地图上展示台风行进方向的扇形区域,以及该区域内的船舶,扇形区域的输入参数包括:
- 台风行进方向
- 扇形半径
- 行进方向夹角
由于postgis内置函数并未提供直接构造扇形的功能,所以只能自己实现。思路很简单,利用半径画圆,利用半径和夹角画三角形,利用postgis的重影函数,求得两个对象的重叠部分,即是我们需要的扇形,示意图如下:(需要注意的是,三角形的边长要放大,以免相交后圆弧部分被切掉,这里直接放大一倍)
函数定义如下:
lon,lat代表圆心坐标,radius是扇形半径,drc是
CREATE OR REPLACE FUNCTION "sdc_dw"."fn_sdc_sector"("lon" numeric, "lat" numeric, "radius" numeric, "drc" numeric, "bdc" numeric)
RETURNS "public"."geography" AS $BODY$
DECLARE
circle geometry;
trigle geometry;
lon1 NUMERIC;
lat1 NUMERIC;
lon2 NUMERIC;
lat2 NUMERIC;
c1 NUMERIC;
c2 NUMERIC;
center TEXT;
rate NUMERIC;
rate2 NUMERIC;
rate3 NUMERIC;
BEGIN
--纬度差一度约111/1.8527海里, 经度查一度约111/1.8527海里;
rate = 111 / 1.8527;
rate2 = cosd(lat)*0.93;
-- rate2 = 1;
--半径扩大两倍画三角
rate3 = 3;
c1 = (drc + bdc) % 360;
c2 = (drc - bdc + 360) % 360;
IF
c1 >= 0
AND c1 < 90 THEN
lon1 = lon + rate3 * radius * sind(c1) / (rate2 * rate);
lat1 = lat + rate3 * radius * cosd(c1) / rate;
END IF;
IF
c1 >= 90
AND c1 < 180 THEN
lon1 = lon + rate3 * radius * cosd(c1 % 90) / (rate2 * rate);
lat1 = lat - rate3 * radius * sind(c1 % 90) / rate;
END IF;
IF
c1 >= 180
AND c1 < 270 THEN
lon1 = lon - rate3 * radius * sind(c1 % 90) / (rate2 * rate);
lat1 = lat - rate3 * radius * cosd(c1 % 90) / rate;
END IF;
IF
c1 >= 270
AND c1 < 360 THEN
lon1 = lon - rate3 * radius * cosd(c1 % 90) / (rate2 * rate);
lat1 = lat + rate3 * radius * sind(c1 % 90) / rate;
END IF;
IF
c2 >= 0
AND c2 < 90 THEN
lon2 = lon + rate3 * radius * sind(c2) / (rate2 * rate);
lat2 = lat + rate3 * radius * cosd(c2) / rate;
END IF;
IF
c2 >= 90
AND c2 < 180 THEN
lon2 = lon + rate3 * radius * cosd(c2 % 90) / (rate2 * rate);
lat2 = lat - rate3 * radius * sind(c2 % 90) / rate;
END IF;
IF
c2 >= 180
AND c2 < 270 THEN
lon2 = lon - rate3 * radius * sind(c2 % 90) / (rate2 * rate);
lat2 = lat - rate3 * radius * cosd(c2 % 90) / rate;
END IF;
IF
c2 >= 270
AND c2 < 360 THEN
lon2 = lon - rate3 * radius * cosd(c2 % 90) / (rate2 * rate);
lat2 = lat + rate3 * radius * sind(c2 % 90) / rate;
END IF;
IF
lon1 > 180 THEN
lon1 = 180 - lon1;
END IF;
IF
lon2 > 180 THEN
lon2 = 180 - lon2;
END IF;
IF
lon1 < - 180 THEN
lon1 = - 1 * lon1 - 180;
END IF;
IF
lon2 < - 180 THEN
lon2 = - 1 * lon2 - 180;
END IF;
IF
lat1 > 90 THEN
lat1 = 90 - lat1;
END IF;
IF
lat2 > 90 THEN
lat2 = 90 - lat2;
END IF;
IF
lat1 < - 90 THEN
lat1 = - 1 * lat1 - 90;
END IF;
IF
lat2 < - 90 THEN
lat2 = - 1 * lat2 - 90;
--
END IF;
center = 'POINT(lon lat)';
center = REPLACE(center, 'lon', lon :: TEXT);
center = REPLACE(center, 'lat', lat :: TEXT);
circle = ST_Buffer(ST_GeomFromText(center,4326)::geography, radius*1.8527*1000) :: geography;
trigle = ST_Polygon('LINESTRING(' || lon || ' ' || lat || ',' || lon1 || ' ' || lat1 || ',' || lon2 ||
' ' || lat2 || ',' || lon || ' ' || lat || ')', 4326) :: geography;
RETURN ST_Intersection(circle, trigle);
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
来源:oschina
链接:https://my.oschina.net/u/4308645/blog/4724708