Invalide (Curve) vlak-geometrie volgens PostGIS in BGT Wegdeel

Dit kwam uit het nieuwe SQL Script BGT-Lean in NLExtract. Dit script maakt een slanke/meer hapklare versie van de “Full” BGT zoals door NLExtract in PostGIS ingelezen uit de BGT (City)GML:

  • alleen actueelbestaande records (geen historie)
  • uitsplitsen naar 1 geometrie-kolom per tabel, bijv Wegdeel_vlak
  • alleen relevante kolommen, geen metadata, status etc.
  • belangrijkste: converteer geo-kolommen naar “(OGC) Simple Geometries”, geen Curves etc

De vraag is meer algemeen en heeft betrekking op laatste. Aanvankelijk neemt BGT Lean alleen valide geometrie mee. Dus waar PostGIS ST_IsValid(vlak) is True. Alleen dan gaan er records ontbreken, bijv plm 900 op 7.7 miljoen Wegdelen met vlak). De validatie melding is: Self-intersection at or near point …. PostGIS versie: postgis/postgis:10-3.2-alpine (dus 3.2 met PG v10 in Docker).

Als voorbeeld een Fietspad vlak in Amersfoort met lokaalid = 'G0307.f86336b663854a3b9d00dd4d89a49b56'.
De geometrie is een m.i. een simpel Polygoon maar is beschreven als CURVEPOLYGON met embedded COMPOUNDCURVE, waarin weer CIRCULARSTRINGs. QGIS accepteert deze overigens, zie deze CSV met WKT. Het NLExtract GitHub issue staat hier.

Maar mijn vraag is algemeen, daarom hier gesteld, want kan het zijn dat de BGT Curve-geometrie op zich valide is, maar dat door bijv ‘tolerantie’ in GEOS (de lib in PostGIS die valideert) er toch ‘invalid’ wordt gegeven? Ik heb meen ik zoiets weleens gezien in BRK waarin data uit Oracle Spatial vervolgens PostGIS ‘te weinig cijfers achter de comma had’ (1000-en van mm).

Beetje off-topic misschien, maar ik heb nooit begrepen waarom curve-geometrieën (bogen) in de datamodellen zijn gekomen. Ze voegen heel weinig toe en als je een beetje gevoel voor geometrie, data en software hebt kun je op je klompen aanvoelen dat dit soort problemen gaan ontstaan.

Wat betreft validatie zou het mooi zijn als er software, eventueel met service, zou zijn die validatie uitvoert op een manier waar iedereen het mee eens is. JTS (of GEOS etc.) zou een optie kunnen zijn. Je kunt dan data leveren met het stempel “geometrie gevalideerd door JTS” en hierover afspraken maken in contracten. Geen idee of hier al wel eens over wordt nagedacht bij bijvoorbeeld landelijke voorzieningen of Geonovum.

In ieder geval zijn hier regelmatig vragen over op dit forum, zoek bijvoorbeeld op de term “valide”.

1 like

Wat mij betreft heb je een punt over die curve-geometrieën, Raymond. Ik heb al heel lang het gevoel dat de BGT toentertijd - met de beste bedoelingen uiteraard - helaas is ontworpen met weinig geo-expertise aan boord. Geen enkele geo-expert zou ook maar overwegen om straatnaamlabels als puntjes op te nemen en van het thema ‘wegen’ geen hartlijnen te definiëren. Maar we moeten het er mee doen, en alsnog is de BGT natuurlijk een huzarenstukje als je het vergelijkt met de situatie in de landen om ons heen, of waar dan ook ter wereld.

1 like

+1

In mijn ervaring leveren curves en arcs alleen maar ellende op. Ik probeer ze er meestal ook uit te halen als ik ze toevallig tegenkom…

Nou, daar is best al veel geregeld. JTS is de referentieimplementatie van SFS. Dus als JTS het afkeurt voldoet het niet aan SFS.

daarbovenop, alle data die we uitwisselen in gml dient zich te houden aan het bijbehorende datamodel (dat ook netjes wordt genoemd bij de namespaces bovenin de xml). SFS maakt integraal onderdeel uit van het gml datamodel.

Dus niet valide volgens JTS betekent niet conform SFS betekent niet conform het gml datamodel.

Wat moeten we nog meer afspreken als we vragen om gml-data te leveren?

Wat interessant is, is dat validiteit wordt beïnvloedt door het aantal decimalen waarmee een computer rekent. Daarom vind ik het ook erg goed dat het basismodel geometrie zoals we dat in Nederland hanteren een vast aantal decimalen heeft gedefinieerd.

Overigens is het altijd een goed idee om een aantal van die probleempunten te bekijken (goed inzoomen) om te zien wat er aan de hand is. Meestal komt er dan wel een oorzaak bovendrijven en kan ook een remedie worden gevonden.

Ben benieuwd wat hier precies het probleem is.

Wat exact de reden is dat goede validatiesoftware een tolerantie gebruikt bij validatie die past bij het CRS waarin de gegevens zijn opgeslagen.

Case in point (pun intended): als twee punten coördinaten hebben die pas na 5 cijfers achter de komma verschillen, in EPSG:28992, moeten die twee als gelijk uit validatie komen, hoewel ‘de computer’ er een duidelijk verschil in ziet.

Bedankt voor alle reacties! Inmiddels weer veel bijgeleerd en zijn er 2 werkbare oplossingen. Om een, in dit geval Polygon te maken, zal de boog-geometrie moeten ‘expanderen’. In PostGIS met ST_CurveToLine() . De 2 oplossingen die een valide geometrie opleveren:

  • een (ST_)Buffer van 0 eromheen leggen (dank @willemhoffmans ) na expansie
  • de tolerantie-parameters van de PostGIS expansie functie ST_CurveToLine() aanpassen

Voor details zie NLExtract issue hier.

Vooral die laatste is interessant m.b.t. ‘goed/valide’ of ‘fout/invalide’. Mijn indruk is nu dat dit van de tolerantie en andere settings in je expansie afhangt. Dat is los van de vraag of je überhaupt ‘bogen’ moet gebruiken. Dat is historisch.

Toevallig had net overleg over OSM-BGT met Kadaster BRT/BGT team en @PeeWee32 . Er blijkt ook een handreiking te zijn wat lijkt de minimum tolerantie is (moet nog doornemen, zie wel het woord ‘Oracle’ daarin…).

Edit: in de tijd dat ik bovenstaande inklopte, kwamen er 2 antwoorden die ditzelfde (tolerantie) ‘aansnijden’…

De CAD wereld is er anders erg blij mee dat er wegvakken met bogen in de BGT staan :slight_smile: Maar voor de GIS wereld kan ik me ook indenken dat dit niet handig is.

Net even geprobeerd om dat ding met FME in te lezen, maar die vind het niet lekker. Als csv-bestandje inlezen is geen probleem, maar om dan van de wkt een geometrie te maken (GeometryReplacer met Geometry Encoding = ‘OGC Well Known Text’, voor de FME’ers onder ons) weigert ie met de melding INVALID_PARAMETER_GEOMETRY_SOURCE… FME is waarschijnlijk wat strikter dan QGis hierin, vermoed ik. Maar PostGis is dus niet de enige…

Gdal heeft hier ook moeite mee. Het is ook de vraag of je dit moet willen in een gml bestand. De structuur van het bestand wordt hier behoorlijk complexer van. Simpeler zou zijn als er een attribuut wordt toegevoegd die aangeeft welke punten van de polygoon onderdeel zijn van een curve. Als je een curve wil dan kun je die info gebruiken en anders laat je hem achterwege.

Volgens mij kun je curves niet in WKT serializeren.

Eens, maar op dit moment moeten we omgaan met wat de BGT levert en probeer ik voor PostGIS valide geometrie te genereren. “Curves” zijn gestandaardiseerd in OGC Simple Features dus op zich mogelijk in GML. Alleen zoek ik nog waar de ‘grenswaarden’ m.b.t. toleranties liggen, een document o.i.d. Bij EPSG:28992 vindt ik niets. Is het max 5 cijfers achter comma zoals @sbjager zegt? Waar gespecificeerd. Maar dan nog kun je (in PostGIS) sturen met de 3 optionele parameters van ST_CurveToLine bijv aantal segmenten per kwadrant (default 32). Valide/niet-valide is dus geen absoluut iets.

Ja hoor, met ST_AsText(geom). Heb bovenstaand voorbeeld van BGT Wegdeel object 'G0307.f86336b663854a3b9d00dd4d89a49b56' zelfs wat geformatteerd:

CURVEPOLYGON(
COMPOUNDCURVE(
  (155054.911 463342.298,155054.91 463342.26,155052.61 463342.203,155043.19 463341.853,155040.683 463341.79,155030.359 463341.39,155027.87 
    463341.28,155018.473 463340.946,155015.933 463340.846,155006.346 463340.46,154998.535 463340.169),
  CIRCULARSTRING(154998.535 463340.169,154996.962 463340.023,154995.398 463339.798),
  (154995.398 463339.798,154993.552 463339.46,154992.094 463339.23,154991.575 463339.149,154987.001 463338.511),
  CIRCULARSTRING(154987.001 463338.511,154983.087 463337.782,154979.197 463336.937),
  (154979.197 463336.937,154979.915 463335.61,154982.614 463330.733),
    CIRCULARSTRING(154982.614 463330.733,154982.54 463331.016,154982.584 463331.304),
  CIRCULARSTRING(154982.584 463331.304,154984.552 463334.328,154987.691 463336.105),
  (154987.691 463336.105,154992.8 463337.642),
  CIRCULARSTRING(154992.8 463337.642,154995.238 463338.235,154997.723 463338.591),
  (154997.723 463338.591,155000 463338.684,155067.679 463341.204,155103.991 463342.557,155105.936 463342.712),
  CIRCULARSTRING(155105.936 463342.712,155106.96 463342.814,155107.962 463343.048),
  CIRCULARSTRING(155107.962 463343.048,155108.867 463343.384,155109.725 463343.828),
  CIRCULARSTRING(155109.725 463343.828,155110.8 463344.538,155111.833 463345.307),
  CIRCULARSTRING(155111.833 463345.307,155112.535 463345.614,155113.294 463345.509),
  CIRCULARSTRING(155113.294 463345.509,155111.328 463346.302,155109.315 463346.963),
  CIRCULARSTRING(155109.315 463346.963,155107.731 463347.379,155106.124 463347.696),
  CIRCULARSTRING(155106.124 463347.696,155106.829 463347.328,155107.209 463346.629),
  (155107.209 463346.629,155107.261 463345.484),
  CIRCULARSTRING(155107.261 463345.484,155107.012 463344.75,155106.341 463344.363),
  (155106.341 463344.363,155103.734 
    463344.045,155101.835 463343.98,155095.332 463343.756,155092.9 463343.7,155090.37 463343.62,155080.286 463343.24,155077.76 
    463343.146,155067.617 463342.78,155065.102 463342.676,155054.911 463342.298)
  )
)

Klopt, is heel context-gevoelig. Een geometrie die perfect valide is voor een Top10NL bijvoorbeeld zou in een BGT absoluut niet valide zijn. En zo is er nog wel meer dat context behoeft als je 't over validering hebt.

Voor zover ik weet is dat ook niet officieel vastgelegd, maar dat kan @Jochem ons vast wel vertellen. In de praktijk is 5 cijfers achter de komma voor EPSG:28992 natuurlijk al veel te veel: met 3 cijfers achter de komma zit je al op millimeters, en dat is zelfs voor een BGT al teveel. Inwinning speelt hier natuurlijk ook een rol. Ik zou zelf voor een technische validatie van BGT geometrie voor 2 cijfers achter de komma kiezen, dan zit je dus op centimeters. Voor bijvoorbeeld een topologie-validatie is dat een prima nivo.
Natuurlijk zijn er net zo goed argumenten te verzinnen om wel op de millimeter te valideren, afhankelijk van wat je doel is. Ben ook wel nieuwsgierig naar hoe anderen hier over denken.

Volgens Wikipedia gebruikt PostGis extended wkt, waar curves in opgenomen zijn. In het ‘gewone’ wkt lijken inderdaad geen curves te zitten.

De tolerantie voor de validatie van geometrieën lijkt me inderdaad vooral afhankelijk van de context, zoals de toepassing van de data en de nauwkeurigheid van de data-inwinningsmethode. De eenheden van een CRS hebben natuurlijk wel invloed op de tolerantie: voor graden heb je ca. 5 cijfers achter de komma meer nodig dan voor meters. Het is echter niet mogelijk om voor een CRS een vaste tolerantie voor te schrijven. Er is hooguit een een ondergrens aan hoe klein je de tolerantie kan maken, dat kan iets verschillen per CRS.

WGS 84 (EPSG:4326) is een datum-ensemble zonder eenduidige definitie en zonder beschikbare nauwkeurige referentiepunten, de maximale haalbare nauwkeurigheid is ca. 1 m (EPSG.org vermeldt een nauwkeurigheid van 2 m).
RD (EPSG:28992) is beschikbaar d.m.v. referentiepunten zoals kernnetpunten en GNSS-referentiestations van de NSGI of gecertificeerde stations van derden met een nauwkeurigheid van ca. 1 cm, ook de definitieverschillen blijven onder die ordegrootte (EPSG.org vermeldt geen nauwkeurigheid).
ETRS89 (en ITRS via een tijdsafhankelijke transformatie) is beschikbaar d.m.v. dezelfde referentiepunten en kan bij specificatie van een specifieke realisatie en epoche, zoals het in Nederland gebruikte ETRF2000 (EPSG:9067), zelfs nog iets nauwkeuriger dan 1 cm, zonder die specificatie is de nauwkeurigheid enkele centimeters (EPSG.org vermeldt een nauwkeurigheid van 0,1 m voor het datum-ensemble EPSG:4258).

NB: Het is vaak verstandig om voor berekeningen (en dus ook toleranties) een orde van grootte nauwkeuriger te doen. Daarom stellen we als NSGI bijvoorbeeld ook de eis dat de transformatie van/naar RD en NAP binnen 1 mm moet kloppen om gebruik van de merknaam RDNAPTRANS™ aan te kunnen vragen. Voor geo-data in RD (EPSG:28992) stelt de NSGI geen eisen, dat is aan de bronhouders.

2 likes

Das wel een aardig idee. BGT schrijft 3 decimalen voor, dus dan ben je valide op een orde van grootte groter. Dat betekent dat er ruimte is voor kleine verschuivingen zonder gelijk grote risico’s op invaliditeit.

Dan hiervoor, die had ik gemist.

Dank alle reacties!
Lastig een conclusie te geven voor dit topic. Ik denk nog steeds dat “cijfers achter komma” niet het enige probleem is. Het gaat, in praktisch gebruik, ook om de parameters van een “curve expansie functie”. Een terugmelding zoals ik eerder voor BGT heb gedaan, kan verworpen worden in dat grijze gebied.

Als afnemers moeten we pragmatisch zijn dus maar “repareren” ipv “NOT ST_IsValid()” uitsluiten. Er is zelfs een stuk wetenschap hiervoor, door, en met literatuurverwijzingen naar, niet de minste auteurs: Tidying feature geometries with sf

‘Pragmatisch repareren’ is wat we momenteel in NLExtract doen, als onderdeel BGT Lean SQL script.
In de laatste commit wordt gezorgd dat alle vlak-geometrie na expansie valide is, en er geen geometrie, of deel daarvan, uit origineel (BGT met Curves), verloren gaat. Ik heb dit nu best-effort gedaan. Wie weet willen ontwikkelaars onder ons nog eens licht daarop schijnen. Bij voorkeur reacties geven op betreffend NLExtract issue en/of PRs.