. vamaq , , . , , , , , vamaq, .
In my solution, I use the cosine rule to determine the angle between two lines without reference to the azimuth, and then use ST_Contains to check if the angle of the polygon is sharp or obtuse so that I can ensure that the angle is internal.
CREATE OR REPLACE FUNCTION is_internal(polygon geometry, p2 geometry, p3 geometry)
RETURNS boolean as
$$
BEGIN
return st_contains(polygon, st_makeline(p2, p3));
END
$$ language plpgsql;
CREATE OR REPLACE FUNCTION angle(p1 geometry, p2 geometry, p3 geometry)
RETURNS float AS
$$
DECLARE
p12 float;
p23 float;
p13 float;
BEGIN
select st_distance(p1, p2) into p12;
select st_distance(p1, p3) into p13;
select st_distance(p2, p3) into p23;
return acos((p12^2 + p13^2 - p23^2) / (2*p12*p13));
END
$$ language plpgsql;
CREATE OR REPLACE FUNCTION internal_angle(polygon geometry, p1 geometry, p2 geometry, p3 geometry)
RETURNS float as
$$
DECLARE
ang float;
is_intern boolean;
BEGIN
select angle(p1, p2, p3) into ang;
select is_internal(polygon, p2, p3) into is_intern;
IF not is_intern THEN
select 6.28318530718 - ang into ang;
END IF;
return ang;
END
$$ language plpgsql;
CREATE OR REPLACE FUNCTION corner_triplets(geom geometry)
RETURNS table(corner_number integer, p1 geometry, p2 geometry, p3 geometry) AS
$$
DECLARE
max_corner_number integer;
BEGIN
create temp table corners on commit drop as select path[2] as corner_number, t1.geom as point from (select (st_dumppoints($1)).*) as t1 where path[1] = 1;
select max(corners.corner_number) into max_corner_number from corners;
insert into corners (corner_number, point) select 0, point from corners where corners.corner_number = max_corner_number - 1;
create temp table triplets on commit drop as select t1.corner_number, t1.point as p1, t2.point as p2, t3.point as p3 from corners as t1, corners as t2, corners as t3 where t1.corner_number = t2.corner_number + 1 and t1.corner_number = t3.corner_number - 1;
return QUERY TABLE triplets;
END;
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION internal_angles(geom geometry)
RETURNS table(corner geometry, angle float)
AS $$
BEGIN
create temp table internal_angs on commit drop as select p1, internal_angle(geom, p1, p2, p3) from (select (c).* from (select corner_triplets(geom) as c) as t1) as t2;
return QUERY TABLE internal_angs;
END;
$$
LANGUAGE plpgsql;
Using:
select (c).* into temp from (select internal_angles(geom) as c from my_table) as t;