Changes between Initial Version and Version 1 of UsersWikiExamplesSpikeRemover


Ignore:
Timestamp:
Dec 3, 2009, 6:30:03 AM (14 years ago)
Author:
nik1166
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • UsersWikiExamplesSpikeRemover

    v1 v1  
     1= Spike-Remover =
     2
     3This function searches for spikes and removes them. Spikes arise by the intersection of geometries or by digitization errors. The geometry and the azimuth direction angle is the input. As result you get the clean geometriy back without any spikes. The process is the following: At first the SpikeRemover function deagrades the polygon at inner and outer rings. After then the Spike Remover calls the SpikeRemoverCore. This funktion cleans  the individual polygons of inner and outside spikes. As a result you get back  the clean geometry.
     4
     5''Input Value: Polygon, Angle in float 0.01''
     6
     7''Return Value: Cleaned geometry''
     8
     9== Function spike remover ==
     10{{{
     11
     12create or replace function spikeremover(geometry, angle double precision)
     13  returns geometry as
     14$body$
     15select st_makepolygon(
     16        (/*outer ring of polygon*/
     17        select st_exteriorring(spikeremovercore($1,$2)) as outer_ring
     18          from st_dumprings($1)where path[1] = 0
     19        ), 
     20                array(/*all inner rings*/
     21        select st_exteriorring(spikeremovercore($1, $2)) as inner_rings
     22          from st_dumprings($1) where path[1] > 0)
     23) as geom
     24$body$
     25  language 'sql' immutable
     26  cost 100;
     27alter function spikeremover(geometry, double precision) owner to gis;
     28}}}
     29
     30== Function spike remover core ==
     31{{{
     32
     33-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     34--
     35-- $Id: spikeRemoverCore.sql 2009-10-01 08:00 Andreas Schmidt(andreas.schmidtATiz.bwl.de)  &  Nils Krüger(nils.kruegerATiz.bwl.de) $
     36--
     37-- spikeRemover - remove Spike from
     38-- input Polygon geometries, angle
     39-- http://www.izlbw.de/
     40-- Copyright 2009 Informatikzentrum Landesverwaltung Baden-Württemberg (IZLBW) Germany
     41-- Version 1.0
     42--
     43-- This is free software; you can redistribute and/or modify it under
     44-- the terms of the GNU General Public Licence. See the COPYING file.
     45-- This software is without any warrenty and you use it at your own risk
     46-- 
     47-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     48
     49create or replace function spikeremovercore(geometry, angle double precision)
     50  returns geometry as
     51$body$declare
     52 ingeom alias for $1;
     53 angle  alias for $2;
     54 lineusp geometry;
     55 linenew geometry;
     56 newgeom geometry;
     57 testgeom varchar;
     58 remove_point boolean;
     59 newb boolean;
     60 changed boolean;
     61 point_id integer;
     62 numpoints integer;
     63
     64begin
     65        -- input geometry or rather set as default for the output
     66        newgeom := ingeom;
     67   
     68        -- check polygon
     69        if (select st_geometrytype(ingeom)) = 'st_polygon' then
     70            if (select st_numinteriorrings(ingeom)) = 0 then
     71               
     72                -- default value of the loop indicates if the geometry has been changed
     73                newb := true;   
     74                --save the polygon boundary as a line
     75                lineusp := st_boundary(ingeom) as line;
     76                -- number of tags
     77                numpoints := st_numpoints(lineusp);
     78                -- globale changevariable
     79                changed := false;
     80
     81                -- loop ( to remove several points)
     82                while newb = true loop
     83                    -- default values
     84                    remove_point := false;
     85                    newb := false;
     86                    point_id := 0;
     87                       
     88
     89                    -- the geometry passes pointwisely
     90                    while (point_id <= numpoints) and (remove_point = false) loop
     91                                -- the check of the angle at the current point of a spike including the special case, that it is the first point.
     92                            if (select abs(pi() - abs(st_azimuth(st_pointn(lineusp, case when point_id= 1 then st_numpoints(lineusp) - 1 else point_id - 1 end),
     93                                st_pointn(lineusp, point_id)) - st_azimuth(st_pointn(lineusp, point_id), st_pointn(lineusp, point_id + 1))))) <= angle                then
     94                                       
     95
     96                                    -- remove point
     97                                    linenew := removepoint(lineusp, point_id - 1);
     98
     99                                    if linenew is not null then
     100                                        raise notice '---> remove point %', point_id;
     101                                        lineusp := linenew;
     102                                        remove_point := true;
     103
     104                                        -- if the first point is concerned, the last point must also be changed to close the line again.
     105                                        if point_id = 1 then
     106                                                linenew := st_setpoint(lineusp, numpoints - 2, st_pointn(lineusp, 1));
     107                                                lineusp := linenew;
     108                                        end if;
     109                                    end if;
     110                            end if;
     111                            point_id = point_id + 1;
     112
     113                    end loop;
     114
     115                    -- remove point
     116                    if remove_point = true then
     117                        numpoints := st_numpoints(lineusp);
     118                        newb := true;
     119                        point_id := 0;
     120                        changed := true;
     121                    end if;
     122
     123                end loop;
     124                --with the change it is tried to change back the new line geometry in a polygon. if this is not possible, the existing geometry is used
     125                if changed = true then
     126                    newgeom :=  st_buildarea(lineusp) as geom;
     127
     128                    -- errorhandling
     129                    if newgeom is not null then
     130                        raise notice 'creating new geometry!';
     131                    else
     132                        newgeom := ingeom;
     133                        raise notice '-------------- area could not be created !!! --------------';
     134                        testgeom:=st_astext(lineusp);
     135                        raise notice 'geometry %', testgeom;
     136                end if;
     137            end if;
     138        end if;
     139    end if;
     140        -- return value
     141        return newgeom;
     142 end;
     143 $body$
     144  language 'plpgsql' volatile
     145  cost 100;
     146alter function spikeremovercore(geometry, double precision) owner to gis;
     147
     148}}}
     149
     150== Example 1: ==
     151{{{
     152POLYGON((3480407.01 5483810.171,3480407.01 5483810.17,3480409.11 5483777.431,3480407.348 5483777.421,3480405.15 5483777.409,3480404.816 5483777.407,3480394.58 5483777.35,3480395.36 5483811.12,3480404.55 5483810.46,3480405.951 5483810.295,3480406.312 5483795.106,3480405.951 5483810.296,3480406.903 5483810.184,3480407.01 5483810.171))
     153}}}
     154'''which produces:'''
     155{{{
     156POLYGON((3480407.01 5483810.171,3480407.01 5483810.17,3480409.11 5483777.431,3480407.348 5483777.421,3480405.15 5483777.409,3480404.816 5483777.407,3480394.58 5483777.35,3480395.36 5483811.12,3480404.55 5483810.46,3480405.951 5483810.295,3480405.951 5483810.296,3480406.903 5483810.184,3480407.01 5483810.171))
     157}}}
     158
     159----
     160== Example 2: ==
     161{{{
     162POLYGON((3415632.49 5291021.49,3415632.488 5291021.494,3415632.49 5291021.494,3415628.93 5291028.28,3415642.95 5291001.56,3415651.18 5290985.86,3415659.27 5290984.61,3415644.71 5290947.81,3415629.17 5290921.83,3415621.28 5290929.72,3415640.21 5290959.43,3415625.38 5290971.41,3415627.79 5290983.94,3415629.49 5290992.19,3415630.14 5290995.36,3415625.65 5291022.5,3415632.49 5291021.49))
     163}}}
     164'''which produces:'''
     165{{{
     166POLYGON((3415632.49 5291021.49,3415632.488 5291021.494,3415632.49 5291021.494,3415642.95 5291001.56,3415651.18 5290985.86,3415659.27 5290984.61,3415644.71 5290947.81,3415629.17 5290921.83,3415621.28 5290929.72,3415640.21 5290959.43,3415625.38 5290971.41,3415627.79 5290983.94,3415629.49 5290992.19,3415630.14 5290995.36,3415625.65 5291022.5,3415632.49 5291021.49))
     167}}}