move size calculation to its own function

This commit is contained in:
Motiejus Jakštys 2021-05-04 21:54:46 +03:00
parent 534a9b9814
commit a4e4229627

View File

@ -358,7 +358,6 @@ drop type if exists wm_t_bend_attrs;
create type wm_t_bend_attrs as ( create type wm_t_bend_attrs as (
bend geometry, bend geometry,
area real, area real,
cmp real,
adjsize real, adjsize real,
baselinelength real, baselinelength real,
curvature real, curvature real,
@ -370,7 +369,7 @@ create function wm_bend_attrs(
dbggen integer default null dbggen integer default null
) returns setof wm_t_bend_attrs as $$ ) returns setof wm_t_bend_attrs as $$
declare declare
fourpi constant real default 4*radians(180); cmp float;
i int4; i int4;
polygon geometry; polygon geometry;
bend geometry; bend geometry;
@ -380,27 +379,12 @@ begin
bend = bends[i]; bend = bends[i];
res = null; res = null;
res.bend = bend; res.bend = bend;
res.area = 0;
res.cmp = 0;
res.adjsize = 0; res.adjsize = 0;
res.baselinelength = st_distance(st_startpoint(bend), st_endpoint(bend)); res.baselinelength = st_distance(st_startpoint(bend), st_endpoint(bend));
res.curvature = wm_inflection_angle(bend) / st_length(bend); res.curvature = wm_inflection_angle(bend) / st_length(bend);
res.isolated = false; res.isolated = false;
if st_numpoints(bend) >= 3 then if st_numpoints(bend) >= 3 then
polygon = st_makepolygon(st_addpoint(bend, st_startpoint(bend))); res.adjsize = wm_adjsize(bend);
-- Compactness Index (cmp) is defined as "the ratio of the area of the
-- polygon over the circle whose circumference length is the same as the
-- length of the circumference of the polygon". I assume they meant the
-- area of the circle. So here goes:
-- 1. get polygon area P.
-- 2. get polygon perimeter = u. Pretend it's our circle's circumference.
-- 3. get A (area) of the circle from u: A = u^2/(4pi)
-- 4. divide P by A: cmp = P/A = P/(u^2/(4pi)) = 4pi*P/u^2
res.area = st_area(polygon);
res.cmp = fourpi*res.area/(st_perimeter(polygon)^2);
if res.cmp > 0 then
res.adjsize = (res.area*(0.75/res.cmp));
end if;
end if; end if;
if dbgname is not null then if dbgname is not null then
@ -411,8 +395,6 @@ begin
i, i,
bend, bend,
jsonb_build_object( jsonb_build_object(
'area', res.area,
'cmp', res.cmp,
'adjsize', res.adjsize, 'adjsize', res.adjsize,
'baselinelength', res.baselinelength, 'baselinelength', res.baselinelength,
'curvature', res.curvature 'curvature', res.curvature
@ -424,6 +406,72 @@ begin
end; end;
$$ language plpgsql; $$ language plpgsql;
-- wm_exaggerate exaggerates a given bend. Must be a simple linestring.
drop function if exists wm_exaggerate;
create function wm_exaggerate(
bend geometry,
size real,
desired_size real
) returns geometry as $$
declare
step constant float default 1.5; -- line length multiplier per step
midpoint geometry; -- midpoint of the baseline
splitbend geometry; -- bend split across farthest point
bendm geometry; -- bend with coefficients to prolong the lines
begin
midpoint = st_lineinterpolatepoint(st_makeline(
st_pointn(bend, 1),
st_pointn(bend, -1)
), .5);
while size < desired_size loop
splitbend = st_split(
bend,
st_pointn(st_longestline(midpoint, bend), -1)
);
-- Convert bend to LINESTRINGM, where M is the fraction by how
-- much the point will be prolonged.
-- Currently using linear interpolation; can be updated to gaussian
-- or so (then interpolate manually instead of relying on st_addmeasure)
bendm = st_linemerge(st_union(
st_addmeasure(st_geometryn(splitbend, 1), 0, frac),
st_addmeasure(st_geometryn(splitbend, 2), frac, 0)
));
size = wm_adjsize(bend);
end loop;
end
$$ language plpgsql;
-- wm_adjsize calculates adjusted size for a polygon. Can return 0.
drop function if exists wm_adjsize;
create function wm_adjsize(bend geometry, OUT adjsize float) as $$
declare
polygon geometry;
area float;
cmp float;
begin
adjsize = 0;
polygon = st_makepolygon(st_addpoint(bend, st_startpoint(bend)));
-- Compactness Index (cmp) is defined as "the ratio of the area of the
-- polygon over the circle whose circumference length is the same as the
-- length of the circumference of the polygon". I assume they meant the
-- area of the circle. So here goes:
-- 1. get polygon area P.
-- 2. get polygon perimeter = u. Pretend it's our circle's circumference.
-- 3. get A (area) of the circle from u: A = u^2/(4pi)
-- 4. divide P by A: cmp = P/A = P/(u^2/(4pi)) = 4pi*P/u^2
area = st_area(polygon);
cmp = 4*pi()*area/(st_perimeter(polygon)^2);
if cmp > 0 then
adjsize = (area*(0.75/cmp));
end if;
end
$$ language plpgsql;
create function wm_exaggeration( create function wm_exaggeration(
INOUT bendattrs wm_t_bend_attrs[], INOUT bendattrs wm_t_bend_attrs[],
dhalfcircle float, dhalfcircle float,
@ -432,7 +480,6 @@ create function wm_exaggeration(
OUT mutated boolean OUT mutated boolean
) as $$ ) as $$
declare declare
area_threshold float;
begin begin
end end
@ -552,7 +599,6 @@ begin
res.bend, res.bend,
jsonb_build_object( jsonb_build_object(
'area', res.area, 'area', res.area,
'cmp', res.cmp,
'adjsize', res.adjsize, 'adjsize', res.adjsize,
'baselinelength', res.baselinelength, 'baselinelength', res.baselinelength,
'curvature', res.curvature, 'curvature', res.curvature,