<div dir="ltr"><div>-- Function: public.rc_totopogeomwithouterrors(geometry, character varying, integer, double precision)</div><div><br></div><div>-- DROP FUNCTION public.rc_totopogeomwithouterrors(geometry, character varying, integer, double precision);</div>
<div><br></div><div>CREATE OR REPLACE FUNCTION public.rc_totopogeomwithouterrors(ageom geometry, atopology character varying, alayer integer, atolerance double precision DEFAULT 0)</div><div>  RETURNS topogeometry AS</div>
<div>$BODY$</div><div>DECLARE</div><div>  layer_info RECORD;</div><div>  topology_info RECORD;</div><div>  rec RECORD;</div><div>  tg topology.TopoGeometry;</div><div>  elems topology.TopoElementArray = '{{0,0}}';</div>
<div>  sql TEXT;</div><div>  typ TEXT;</div><div>  tolerance FLOAT8;</div><div>BEGIN</div><div><br></div><div>raise notice 'ageom : %',ST_AsText(ageom);</div><div>  -- Get topology information</div><div>  BEGIN</div>
<div>    SELECT *</div><div>    FROM topology.topology</div><div>      INTO STRICT topology_info WHERE name = atopology;</div><div>  EXCEPTION</div><div>    WHEN NO_DATA_FOUND THEN</div><div>      RAISE EXCEPTION 'No topology with name "%" in topology.topology',</div>
<div>        atopology;</div><div>  END;</div><div><br></div><div>  -- Get tolerance, if 0 was given</div><div>  tolerance := COALESCE( NULLIF(atolerance, 0), topology._st_mintolerance(atopology, ageom) );</div><div><br></div>
<div>  -- Get layer information</div><div>  BEGIN</div><div>    SELECT *, CASE</div><div>      WHEN feature_type = 1 THEN 'puntal'</div><div>      WHEN feature_type = 2 THEN 'lineal'</div><div>      WHEN feature_type = 3 THEN 'areal'</div>
<div>      WHEN feature_type = 4 THEN 'mixed'</div><div>      ELSE 'unexpected_'||feature_type</div><div>      END as typename</div><div>    FROM topology.layer l</div><div>      INTO STRICT layer_info</div>
<div>      WHERE l.layer_id = alayer</div><div>      AND l.topology_id = <a href="http://topology_info.id">topology_info.id</a>;</div><div>  EXCEPTION</div><div>    WHEN NO_DATA_FOUND THEN</div><div>      RAISE EXCEPTION 'No layer with id "%" in topology "%"',</div>
<div>        alayer, atopology;</div><div>  END;</div><div><br></div><div>  -- Can't convert to a hierarchical topogeometry</div><div>  IF layer_info.level > 0 THEN</div><div>      RAISE EXCEPTION 'Layer "%" of topology "%" is hierarchical, cannot convert to it.',</div>
<div>        alayer, atopology;</div><div>  END IF;</div><div><br></div><div><br></div><div>  -- </div><div>  -- Check type compatibility and create empty TopoGeometry</div><div>  -- 1:puntal, 2:lineal, 3:areal, 4:collection</div>
<div>  --</div><div>  typ = geometrytype(ageom);</div><div>  IF typ = 'GEOMETRYCOLLECTION' THEN</div><div>    --  A collection can only go collection layer</div><div>    IF layer_info.feature_type != 4 THEN</div><div>
      RAISE EXCEPTION</div><div>        'Layer "%" of topology "%" is %, cannot hold a collection feature.',</div><div>        layer_info.layer_id, <a href="http://topology_info.name">topology_info.name</a>, layer_info.typename;</div>
<div>    END IF;</div><div>    tg := topology.CreateTopoGeom(atopology, 4, alayer);</div><div>  ELSIF typ = 'POINT' OR typ = 'MULTIPOINT' THEN -- puntal</div><div>    --  A point can go in puntal or collection layer</div>
<div>    IF layer_info.feature_type != 4 and layer_info.feature_type != 1 THEN</div><div>      RAISE EXCEPTION</div><div>        'Layer "%" of topology "%" is %, cannot hold a puntal feature.',</div>
<div>        layer_info.layer_id, <a href="http://topology_info.name">topology_info.name</a>, layer_info.typename;</div><div>    END IF;</div><div>    tg := topology.CreateTopoGeom(atopology, 1, alayer);</div><div>  ELSIF typ = 'LINESTRING' or typ = 'MULTILINESTRING' THEN -- lineal</div>
<div>    --  A line can go in lineal or collection layer</div><div>    IF layer_info.feature_type != 4 and layer_info.feature_type != 2 THEN</div><div>      RAISE EXCEPTION</div><div>        'Layer "%" of topology "%" is %, cannot hold a lineal feature.',</div>
<div>        layer_info.layer_id, <a href="http://topology_info.name">topology_info.name</a>, layer_info.typename;</div><div>    END IF;</div><div>    tg := topology.CreateTopoGeom(atopology, 2, alayer);</div><div>  ELSIF typ = 'POLYGON' OR typ = 'MULTIPOLYGON' THEN -- areal</div>
<div>    --  An area can go in areal or collection layer</div><div>    IF layer_info.feature_type != 4 and layer_info.feature_type != 3 THEN</div><div>      RAISE EXCEPTION</div><div>        'Layer "%" of topology "%" is %, cannot hold an areal feature.',</div>
<div>        layer_info.layer_id, <a href="http://topology_info.name">topology_info.name</a>, layer_info.typename;</div><div>    END IF;</div><div>    tg := topology.CreateTopoGeom(atopology, 3, alayer);</div><div>  ELSE</div>
<div>      -- Should never happen</div><div>      RAISE EXCEPTION</div><div>        'Unsupported feature type %', typ;</div><div>  END IF;</div><div><br></div><div>  -- Now that we have a topogeometry, we loop over distinct components </div>
<div>  -- and add them to the definition of it. We add them as soon</div><div>  -- as possible so that each element can further edit the</div><div>  -- definition by splitting</div><div><br></div><div>--modified to catch errors:</div>
<div>BEGIN</div><div><br></div><div>  FOR rec IN SELECT DISTINCT id(tg), alayer as lyr,-- geom,</div><div>    CASE WHEN ST_Dimension(geom) = 0 THEN 1</div><div>         WHEN ST_Dimension(geom) = 1 THEN 2</div><div>         WHEN ST_Dimension(geom) = 2 THEN 3</div>
<div>    END as type,</div><div>    CASE WHEN ST_Dimension(geom) = 0 THEN</div><div>           topology.topogeo_addPoint(atopology, geom, tolerance)</div><div>         WHEN ST_Dimension(geom) = 1 THEN</div><div>           topology.topogeo_addLineString(atopology, geom, tolerance)</div>
<div>         WHEN ST_Dimension(geom) = 2 THEN</div><div>           topology.topogeo_addPolygon(atopology, geom, tolerance)</div><div>    END as primitive</div><div>    FROM (SELECT (ST_Dump(ageom)).geom) as f</div><div>    WHERE NOT ST_IsEmpty(geom)</div>
<div>  LOOP</div><div>  --raise notice 'coucou, tg : %, geom %',<a href="http://rec.id">rec.id</a>, ST_AsText(rec.geom);</div><div>    -- TODO: consider use a single INSERT statement for the whole thing</div><div>
    sql := 'INSERT INTO ' || quote_ident(atopology)</div><div>        || '.relation(topogeo_id, layer_id, element_type, element_id) VALUES ('</div><div>        || <a href="http://rec.id">rec.id</a> || ',' || rec.lyr || ',' || rec.type</div>
<div>        || ',' || rec.primitive || ')';</div><div>    EXECUTE sql;</div><div>  END LOOP;</div><div><br></div><div>  RETURN tg;</div><div>  </div><div>EXCEPTION</div><div>    WHEN SQLSTATE 'P0001' THEN</div>
<div>        RAISE NOTICE 'this geometry can''t be converted to topogeom : %</div><div><span class="" style="white-space:pre">              </span>doing nothing',ageom;</div><div><span class="" style="white-space:pre">  </span>RETURN NULL;<span class="" style="white-space:pre">      </span></div>
<div>END;</div><div>END</div><div>$BODY$</div><div>  LANGUAGE plpgsql VOLATILE STRICT</div><div>  COST 100;</div><div>ALTER FUNCTION public.rc_totopogeomwithouterrors(geometry, character varying, integer, double precision)</div>
<div>  OWNER TO postgres;</div><div><br></div><div><br></div><div class="gmail_extra"><br><br><div class="gmail_quote">2014/1/15 Rémi Cura <span dir="ltr"><<a href="mailto:remi.cura@gmail.com" target="_blank">remi.cura@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Last chance :<div>this function is a a sloghtly modified topogeom constructor that won't stop when habving an error.</div>
<div>This way you can import everything that works, and then deal with the unworking ...</div>
<div><br></div></div><div class=""><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">2014/1/15 Sandro Santilli <span dir="ltr"><<a href="mailto:strk@keybit.net" target="_blank">strk@keybit.net</a>></span><br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div>On Tue, Jan 14, 2014 at 04:10:45PM +0100, Ludovic Granjon wrote:<br>
<br>
> UPDATE ec SET topogeom2 = toTopoGeom(geom, 'ec_topo', 1, 1.0);<br>
</div>...<br>
<div>> ERREUR: Spatial exception - geometry intersects edge 262<br>
</div>...<br>
<div>> Have  you a solution for that ?<br>
<br>
</div>Do the update in chunks. That way you'll import what can be and isolate<br>
the offending record (if still offending) and then fight with that one<br>
individually.<br>
<br>
These kind of error sometime happen when the tolerance you specify<br>
is bigger than the smallest distance between any two vertices in<br>
your input dataset. An ST_SnapToGrid with given tolerance might also<br>
give you better results, but the chunked loading is always the best<br>
way to do topology building.<br>
<br>
--strk;<br>
<div><div>_______________________________________________<br>
postgis-users mailing list<br>
<a href="mailto:postgis-users@lists.osgeo.org" target="_blank">postgis-users@lists.osgeo.org</a><br>
<a href="http://lists.osgeo.org/cgi-bin/mailman/listinfo/postgis-users" target="_blank">http://lists.osgeo.org/cgi-bin/mailman/listinfo/postgis-users</a><br>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div></div>