Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OGR LVBAG Driver: addressable objects conversions should follow XSD #3221

Closed
justb4 opened this issue Nov 25, 2020 · 12 comments · Fixed by #3417
Closed

OGR LVBAG Driver: addressable objects conversions should follow XSD #3221

justb4 opened this issue Nov 25, 2020 · 12 comments · Fixed by #3417

Comments

@justb4
Copy link
Contributor

justb4 commented Nov 25, 2020

"Addressable objects" within the BAG are Object Types that have (one or more) addresses.
Three types Verblijfsobject (VBO, hard to translate: "Living-unit", "Apartment"), Ligplaats (LIG, on water, mainly for living boats), Standplaats (STA, on land, like camp-ground). Will use these abbrevs below, and PND for Pand (Building).

These objects are defined within an XSD, see imbag/IMBAGLV/objecten/v20200601/IMBAGLV_Objecten-2.1.0.xsd (attached here). Several design decisions there are not very obvious, but should still be addressed in the LVBAG Driver. Will expand below for each issue. Most have to do with "multiplicity".

It may help to look at the Python object definitions in NLExtract BAG v1 and the BAG Postgres tables.

Expected behavior and actual behavior.

N-M Relation PND-VBO

A VBO is usually N:1 to a PND Building, i.e. a PND contains (maaktDeelUitVan/"Is-part-of") one or more VBOs. But there are also cases where a VBO belongs to more than 1 PND. Hence the relation PND-VBO in the XSD is N-M. This should be reflected in the LVBAG output.
Currently only one PND related to a VBO is assumed.

The relevant XSD excerpt:

					<xs:element name="maaktDeelUitVan" minOccurs="1" maxOccurs="1">
						<xs:annotation>
							<xs:documentation>Een verblijfsobject maakt onderdeel uit van een pand.</xs:documentation>
						</xs:annotation>
						<xs:complexType>
							<xs:choice minOccurs="1" maxOccurs="unbounded">
								<xs:element ref="Objecten-ref:PandRef"/>
							</xs:choice>
						</xs:complexType>
					</xs:element>

Within NLExtract this was solved by generating a relation-table ("tussentabel") verblijfsobjectpand that enumerates all PND-VBO relations.
LVBAG could do something similar like generating a PND-VBO object. This object should also contain the VBO voorkomen attributes. Generating an identifier array StringList (preferred) or comma-separated for maaktDeelUitVan would also be possible and more compact.

One or more "usage-purposes" ("gebruiksdoelen") VBO

The relevant XSD excerpt:

					<xs:element name="gebruiksdoel" type="Objecten:Gebruiksdoel" minOccurs="1" maxOccurs="unbounded">
						<xs:annotation>
							<xs:documentation>Een categorisering van de gebruiksdoelen van het betreffende verblijfsobject, zoals dit formeel door de overheid als zodanig is toegestaan.</xs:documentation>
						</xs:annotation>
					</xs:element>

Within NLExtract this was solved by generating a relation-table ("tussentabel") verblijfsobjectgebruiksdoel .
But LVBAG could also solve this more compact by generating a comma-separated list as a string.
Or more formally a string array type StringList (preferred). ogr2ogr can expand to comma-separated if needed with -fieldTypeToString StringList.

VBO handle sub-addresses

XSD excerpt:

		<xs:annotation>
			<xs:documentation>Een Adresseerbaar object is een (abstract) object waaraan adressen kunnen worden toegekend</xs:documentation>
		</xs:annotation>
	</xs:element>
	<xs:complexType name="_AdresseerbaarObject" abstract="true">
		<xs:sequence>
			<xs:element name="heeftAlsHoofdadres" minOccurs="1" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>Een adresseerbaar object heeft als hoofadres een nummeraanduiding.</xs:documentation>
				</xs:annotation>
				<xs:complexType>
					<xs:choice minOccurs="1" maxOccurs="1">
						<xs:element ref="Objecten-ref:NummeraanduidingRef"/>
					</xs:choice>
				</xs:complexType>
			</xs:element>
			<xs:element name="voorkomen" minOccurs="1" maxOccurs="1">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="Historie:Voorkomen" minOccurs="1" maxOccurs="1"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="heeftAlsNevenadres" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>Een adresseerbaar object heeft als nevenadres een nummeraanduiding.</xs:documentation>
				</xs:annotation>
				<xs:complexType>
					<xs:choice minOccurs="1" maxOccurs="unbounded">
						<xs:element ref="Objecten-ref:NummeraanduidingRef"/>
					</xs:choice>
				</xs:complexType>
			</xs:element>
		</xs:sequence>
	</xs:complexType>
	<xs:element name="Verblijfsobject" type="Objecten:Verblijfsobject" abstract="false">
		<xs:annotation>
			<xs:documentation>Een Verblijfsobject is de kleinste binnen één of meerdere panden gelegen en voor woon -, bedrijfsmatige - of recreatieve doeleinden geschikte eenheid van gebruik, die ontsloten wordt via een eigen toegang vanaf de openbare weg, een erf of een gedeelde verkeersruimte en die onderwerp kan zijn van rechtshandelingen.</xs:documentation>
		</xs:annotation>
	</xs:element>
	<xs:complexType name="Verblijfsobject" abstract="false">
		<xs:complexContent>
			<xs:extension base="Objecten:_AdresseerbaarObject">
				<xs:sequence>
					<xs:element name="identificatie" minOccurs="1" maxOccurs="1">
						<xs:annotation>
							<xs:documentation>De unieke aanduiding van een verblijfsobject.</xs:documentation>
						</xs:annotation>

A VBO, STA, LIG ("addresseerbaarobject") always has only one main address (heeftAlsHoofdadres) and zero or more sub-adresses (heeftAlsNevenadres).

In NLExtract BAG v1 a nevenadres object was generated for each occurrence with this definition:

CREATE TABLE adresseerbaarobjectnevenadres (
  identificatie VARCHAR(16),
  aanduidingRecordInactief BOOLEAN,
  aanduidingRecordCorrectie INTEGER,
  begindatumTijdvakGeldigheid TIMESTAMP WITH TIME ZONE,
  einddatumTijdvakGeldigheid TIMESTAMP WITH TIME ZONE,
  ligplaatsStatus ligplaatsStatus,
  standplaatsStatus standplaatsStatus,
  verblijfsobjectStatus verblijfsobjectStatus,
  geom_valid BOOLEAN,
  nevenadres VARCHAR(16),
  PRIMARY KEY (gid)
);

identificatie refers to the main VBO address, nevenadres. But this solution is maybe too complex.
Not sure why that was done.

Like with the other multiplicities a string array type StringList of nevenadres identifiers (referring to Nummeraanduiding objects) could be generated.

VBO Geometry may be POINT or POLYGON

Relevant XSD excerpt:

					<xs:element name="geometrie" type="Objecten:PuntOfVlak" minOccurs="1" maxOccurs="1">
						<xs:annotation>
							<xs:documentation>De minimaal tweedimensionale geometrische representatie van een verblijfsobject.</xs:documentation>
						</xs:annotation>
					</xs:element>

with

	<xs:element name="PuntOfVlak" type="Objecten:PuntOfVlak" abstract="false"/>
	<xs:complexType name="PuntOfVlak" abstract="false">
		<xs:annotation>
			<xs:documentation>Ofwel een punt, ofwel een vlak. </xs:documentation>
		</xs:annotation>
		<xs:choice minOccurs="1" maxOccurs="1">
			<xs:element name="punt" type="gml:PointPropertyType">
				<xs:annotation>
					<xs:documentation>Gebruik Point.</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="vlak" type="gml:SurfacePropertyType">
				<xs:annotation>
					<xs:documentation>Gebruik surface, conform NEN3610 Simple Feature Profile Niveau 2 (niet Polygon)</xs:documentation>
				</xs:annotation>
			</xs:element>
		</xs:choice>
	</xs:complexType>

In NLExtract BAG v1 this was solved by generating two fields POINT geopunt and POLYGON geovlak. This is my preferred solution. Defining a single multi-typed geom field as GEOMETRY also has issues.

Operating system

Any

GDAL version and provenance

GDAL 3.2.0, released 2020/10/26
IMBAGLV_Objecten-2.1.0.xsd.txt

@yorickdewid
Copy link
Contributor

yorickdewid commented Dec 28, 2020

N-M Relation PND-VBO

A VBO is usually N:1 to a PND Building, i.e. a PND contains (maaktDeelUitVan/"Is-part-of") one or more VBOs. But there are also cases where a VBO belongs to more than 1 PND. Hence the relation PND-VBO in the XSD is N-M. This should be reflected in the LVBAG output.
Currently only one PND related to a VBO is assumed.

The relevant XSD excerpt:

					<xs:element name="maaktDeelUitVan" minOccurs="1" maxOccurs="1">
						<xs:annotation>
							<xs:documentation>Een verblijfsobject maakt onderdeel uit van een pand.</xs:documentation>
						</xs:annotation>
						<xs:complexType>
							<xs:choice minOccurs="1" maxOccurs="unbounded">
								<xs:element ref="Objecten-ref:PandRef"/>
							</xs:choice>
						</xs:complexType>
					</xs:element>

Within NLExtract this was solved by generating a relation-table ("tussentabel") verblijfsobjectpand that enumerates all PND-VBO relations.
LVBAG could do something similar like generating a PND-VBO object. This object should also contain the VBO voorkomen attributes. Generating an identifier array StringList (preferred) or comma-separated for maaktDeelUitVan would also be possible and more compact.

The only occurrence of Object-ref is in VBO objects pointing to either NUM/PND. There are no known PND references that point back, even if the schema allows for it. In the BAG 1.0 every PND feature points to the VBO which in turn points to a NUM. The VBO-PND relation is reversed in 2.0. Is there an example of PND -> VBO?

One or more "usage-purposes" ("gebruiksdoelen") VBO

The relevant XSD excerpt:

					<xs:element name="gebruiksdoel" type="Objecten:Gebruiksdoel" minOccurs="1" maxOccurs="unbounded">
						<xs:annotation>
							<xs:documentation>Een categorisering van de gebruiksdoelen van het betreffende verblijfsobject, zoals dit formeel door de overheid als zodanig is toegestaan.</xs:documentation>
						</xs:annotation>
					</xs:element>

Within NLExtract this was solved by generating a relation-table ("tussentabel") verblijfsobjectgebruiksdoel .
But LVBAG could also solve this more compact by generating a comma-separated list as a string.
Or more formally a string array type StringList (preferred). ogr2ogr can expand to comma-separated if needed with -fieldTypeToString StringList.

This should be an improvement. We'll use the GDAL provided StringList. Move into separate issue, assign me to the issue.

VBO handle sub-addresses

XSD excerpt:

		<xs:annotation>
			<xs:documentation>Een Adresseerbaar object is een (abstract) object waaraan adressen kunnen worden toegekend</xs:documentation>
		</xs:annotation>
	</xs:element>
	<xs:complexType name="_AdresseerbaarObject" abstract="true">
		<xs:sequence>
			<xs:element name="heeftAlsHoofdadres" minOccurs="1" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>Een adresseerbaar object heeft als hoofadres een nummeraanduiding.</xs:documentation>
				</xs:annotation>
				<xs:complexType>
					<xs:choice minOccurs="1" maxOccurs="1">
						<xs:element ref="Objecten-ref:NummeraanduidingRef"/>
					</xs:choice>
				</xs:complexType>
			</xs:element>
			<xs:element name="voorkomen" minOccurs="1" maxOccurs="1">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="Historie:Voorkomen" minOccurs="1" maxOccurs="1"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="heeftAlsNevenadres" minOccurs="0" maxOccurs="1">
				<xs:annotation>
					<xs:documentation>Een adresseerbaar object heeft als nevenadres een nummeraanduiding.</xs:documentation>
				</xs:annotation>
				<xs:complexType>
					<xs:choice minOccurs="1" maxOccurs="unbounded">
						<xs:element ref="Objecten-ref:NummeraanduidingRef"/>
					</xs:choice>
				</xs:complexType>
			</xs:element>
		</xs:sequence>
	</xs:complexType>
	<xs:element name="Verblijfsobject" type="Objecten:Verblijfsobject" abstract="false">
		<xs:annotation>
			<xs:documentation>Een Verblijfsobject is de kleinste binnen één of meerdere panden gelegen en voor woon -, bedrijfsmatige - of recreatieve doeleinden geschikte eenheid van gebruik, die ontsloten wordt via een eigen toegang vanaf de openbare weg, een erf of een gedeelde verkeersruimte en die onderwerp kan zijn van rechtshandelingen.</xs:documentation>
		</xs:annotation>
	</xs:element>
	<xs:complexType name="Verblijfsobject" abstract="false">
		<xs:complexContent>
			<xs:extension base="Objecten:_AdresseerbaarObject">
				<xs:sequence>
					<xs:element name="identificatie" minOccurs="1" maxOccurs="1">
						<xs:annotation>
							<xs:documentation>De unieke aanduiding van een verblijfsobject.</xs:documentation>
						</xs:annotation>

A VBO, STA, LIG ("addresseerbaarobject") always has only one main address (heeftAlsHoofdadres) and zero or more sub-adresses (heeftAlsNevenadres).

In NLExtract BAG v1 a nevenadres object was generated for each occurrence with this definition:

CREATE TABLE adresseerbaarobjectnevenadres (
  identificatie VARCHAR(16),
  aanduidingRecordInactief BOOLEAN,
  aanduidingRecordCorrectie INTEGER,
  begindatumTijdvakGeldigheid TIMESTAMP WITH TIME ZONE,
  einddatumTijdvakGeldigheid TIMESTAMP WITH TIME ZONE,
  ligplaatsStatus ligplaatsStatus,
  standplaatsStatus standplaatsStatus,
  verblijfsobjectStatus verblijfsobjectStatus,
  geom_valid BOOLEAN,
  nevenadres VARCHAR(16),
  PRIMARY KEY (gid)
);

identificatie refers to the main VBO address, nevenadres. But this solution is maybe too complex.
Not sure why that was done.

Like with the other multiplicities a string array type StringList of nevenadres identifiers (referring to Nummeraanduiding objects) could be generated.

Not only an improvement but also a bug, NummeraanduidingRef is always overwritten with the last entry per feature, often the secondary address. If we make NummeraanduidingRef a StringList then order is of importance. Report as separate bug, assign me to the issue.

VBO Geometry may be POINT or POLYGON

Relevant XSD excerpt:

					<xs:element name="geometrie" type="Objecten:PuntOfVlak" minOccurs="1" maxOccurs="1">
						<xs:annotation>
							<xs:documentation>De minimaal tweedimensionale geometrische representatie van een verblijfsobject.</xs:documentation>
						</xs:annotation>
					</xs:element>

with

	<xs:element name="PuntOfVlak" type="Objecten:PuntOfVlak" abstract="false"/>
	<xs:complexType name="PuntOfVlak" abstract="false">
		<xs:annotation>
			<xs:documentation>Ofwel een punt, ofwel een vlak. </xs:documentation>
		</xs:annotation>
		<xs:choice minOccurs="1" maxOccurs="1">
			<xs:element name="punt" type="gml:PointPropertyType">
				<xs:annotation>
					<xs:documentation>Gebruik Point.</xs:documentation>
				</xs:annotation>
			</xs:element>
			<xs:element name="vlak" type="gml:SurfacePropertyType">
				<xs:annotation>
					<xs:documentation>Gebruik surface, conform NEN3610 Simple Feature Profile Niveau 2 (niet Polygon)</xs:documentation>
				</xs:annotation>
			</xs:element>
		</xs:choice>
	</xs:complexType>

In NLExtract BAG v1 this was solved by generating two fields POINT geopunt and POLYGON geovlak. This is my preferred solution. Defining a single multi-typed geom field as GEOMETRY also has issues.

VBO should never contain polygon but always a point. We recalculate the point if we encounter a (multi)polygon.
image

@justb4
Copy link
Contributor Author

justb4 commented Jan 18, 2021

@yorickdewid thanks for answers. Indeed this issue is rather broad, I count 4 sub-issues:

  1. N to M PND-VBO relation
  2. 1..N "usage-purposes" ("gebruiksdoelen") to VBO
  3. VBO can have 0..N sub-addresses
  4. VBO may have Polygon or Point geometry

As indicated I will open new issues for points 2. and 3. here.

Ad 1) There are quite some occurrences where a single VBO belongs to more than one PND. The XSD contains the relation (to PND) only in the VBO Object def. PND does not contain any ref to VBO.

In BAG v1 PostGIS table made with NLExtract I found 20771 occurrences (where VBO belongs to more than one PND) via this query:

select identificatie, count(*)
from bagactueel.verblijfsobjectpandactueelbestaand
group by identificatie
HAVING count(*) > 1
order by identificatie

I took one VBO id, that should belong to 3 PNDs: VBO id = 0014010010985179.
Indeed, when using the Kadaster BAGViewer I see that this VBO belongs to PND id's
0014100010931333, 0014100010917258, 0014100022186929. See also this screenshot or via this URL:

image

Other VBO id's are 0014010011054152 (2 PNDs) 0014010011054197 (4 PNDs), etc.

Not sure what best solution is.
In NLExtract with BAG v1 we used a relation-table (verblijfsobjectpand), also to track (VBO) history/lifecycle attributes. Nasty thing is also that PND and VBO have separate lifecycles so these relationships may change over time. But shall I open separate issue?

ad 4) ok, though we may loose information. Not sure why that design decision was taken.

@justb4
Copy link
Contributor Author

justb4 commented Jan 19, 2021

Ad 1) See also this discussion (with answer from Kadaster-BAG), though in Dutch:
https://geoforum.nl/t/bag-2-0-nog-steeds-n-m-relatie-verblijfsobject-pand/5339

@yorickdewid
Copy link
Contributor

yorickdewid commented Jan 27, 2021

See #3417. This wil be part of GDAL 3.2.2.

Field gebruiksdoel can containt multiple values

OGRFeature(Verblijfsobject):0
  gebruiksdoel (StringList) = (2:woonfunctie,gezondheidszorgfunctie)

Datasource LIG STA VBO can have an optional secondary address

OGRFeature(Verblijfsobject):0
  hoofdadresNummeraanduidingRef (String) = NL.IMBAG.Nummeraanduiding.0855200000037747
  nevenadresNummeraanduidingRef (String) = NL.IMBAG.Nummeraanduiding.0855200000106110

/offtopic; please check https://gdal.org/drivers/vector/lvbag.html to see if anything is missing.

@justb4
Copy link
Contributor Author

justb4 commented Jan 28, 2021

Thanks @yorickdewid !
As PR #3417 is addressing points 2) (multiple gebruiksdoelen) and 3) (nevenadressen) above and we agreed on point 4) (VBO always Point geom), we have point 1) VBO-PND N-M relation left.

Think the implementation for 1) could be similar to nevenadressen: have stringlist of gerelateerdpand in a VBO object.

@yorickdewid
Copy link
Contributor

In following of #3417

OGRFeature(Verblijfsobject):0
  hoofdadresNummeraanduidingRef (String) = NL.IMBAG.Nummeraanduiding.0518200000692257
  nevenadresNummeraanduidingRef (StringList) = (3:NL.IMBAG.Nummeraanduiding.0518200000692258,NL.IMBAG.Nummeraanduiding.0518200000692259,NL.IMBAG.Nummeraanduiding.0518200000692260)

@justb4
Copy link
Contributor Author

justb4 commented Jan 29, 2021

@yorickdewid great for Nevenadres!

Are you willing to also make this construct i.e. pandRef (StringList) for Building (Pand) related to a Verblijfsobject (as indicated above) in the related PR? Or should we open a new issue/PR?

The XSD construct in <xs:complexType name="Verblijfsobject" ... is:

<xs:element name="maaktDeelUitVan" minOccurs="1" maxOccurs="1">
	<xs:annotation>
		<xs:documentation>Een verblijfsobject maakt onderdeel uit van een pand.</xs:documentation>
	</xs:annotation>
	<xs:complexType>
		<xs:choice minOccurs="1" maxOccurs="unbounded">
			<xs:element ref="Objecten-ref:PandRef"/>
		</xs:choice>
	</xs:complexType>
</xs:element>

The annotation is wrong here, should read: Een verblijfsobject maakt onderdeel uit van een of meer panden. As for testdata the VBO 0014010010985179 is related to three Pand objects (see above).

@yorickdewid
Copy link
Contributor

Anymore of these?

@justb4
Copy link
Contributor Author

justb4 commented Feb 1, 2021

@yorickdewid Not that I know for now. There are 3 such multiplicity-cases (gebruiksdoel, heeftAlsNevenadres and maaktDeelUitVan). Also when I search for maxOccurs="unbounded" in IMBAGLV_Objecten_2.1.0.xsd.

@yorickdewid
Copy link
Contributor

Now that PandRef is a StringList does this not solve point 1 and by that the entire issue?

@justb4
Copy link
Contributor Author

justb4 commented Feb 1, 2021

Yes!

@justb4
Copy link
Contributor Author

justb4 commented Feb 16, 2021

@rouault As this one is solved via #3417 maybe tag it for release 3.2.2 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants