Polygon features from XML GML files
GML polygon
This example shows how polygon data can be read and processed from a GML data source. The example reads and processes pand geometries from the BAG.
We advice to put the templates in a separate configuration file.
container pand { attribute<string> FileName(File): ['9999PND08012016-000001.xml','9999PND008012016-000003.xml']; attribute<String> XmlData (File) : StorageType = "strfiles" , StorageName = "%SourceDataDir%/BAG"; container ParsedXML := parse_xml(XmlData, scheme); container geoBuilder := ProcessGmlPolygon(ParsedXML/bag_LVC_pand,false); template scheme { unit<uint32> bag_LVC_pand { attribute<string> bag_LVC_identificatie; unit<uint32> gml_Polygon { unit<uint32> gml_posList { attribute<string> srsDimension; attribute<string> count; } } unit<uint32> gml_Interior { unit<uint32> gml_posList { attribute<string> srsDimension; attribute<string> count; } } } } // templates for processing polygon geometries template ProcessGmlPolygon { // begin case parameters unit<uint32> gmlContext; parameter<bool> hasMultiplePolygons; // end case parameters container impl := ProcessGmlPolygonImpl(gmlContext/gml_Polygon); parameter<string> geometry_expr:= hasMultiplePolygons ? 'templates/optimized_union( impl/gmlPolygon , gmlContext , impl/Polygon/result , impl/gmlPolygon/Parent_rel )' : 'templates/one2one_union( impl/gmlPolygon , gmlContext , impl/Polygon/result , impl/gmlPolygon/Parent_rel )'; container geometry := = geometry_expr; attribute<rdc_mm> result (gmlContext, polygon) := geometry/result; } template ProcessGmlPolygonImpl { // begin case parameters unit<uint32> gmlPolygon; // end case parameters container Exterior := ProcessLinearRing(gmlPolygon, true); container Interior := ProcessLinearRing(gmlPolygon/gml_Interior, false); container Polygon := ProcessPolygon( gmlPolygon, Exterior/geometry_mm, gmlPolygon/gml_Interior, Interior/geometry_mm, gmlPolygon/gml_Interior/Parent_rel ); } template ProcessLinearRing { // begin case parameters unit<uint32> parsedXMLsrc; parameter<bool> isExt; // exterior // end case parameters container impl { container posList := ProcessPosList(parsedXMLsrc/gml_posList, isExt); container union := one2one_union( parsedXMLsrc/gml_posList , parsedXMLsrc , posList/result , parsedXMLsrc/gml_posList/Parent_rel ); } attribute<rdc_mm> geometry_mm(poly,parsedXMLsrc) := impl/union/result; } template ProcessPosList { // begin case parameters unit<uint32> posList; parameter<bool> isExterior; // end case parameters unit<uint32> impl := posList { attribute<string> values := _ValuesTable/Values[value_rel]; attribute<string> str_sequence := '{'+string(uint32(count) * uint32(srsDimension)) +':'+ values +'}' , IntegrityCheck = "srsDimension == '2' || srsDimension == '3'"; attribute<Float64> f64_sequence(poly) := Float64Seq(str_sequence); unit<uint32> posListunit := range(uint32, 0, #posList) { attribute<uint32> nrCoordPerPoint := union_data(posListunit, uint32(srsDimension)); } unit<uint32> coordinates := sequence2points(union_data(posListunit, f64_sequence)); unit<uint32> p := select_with_org_rel( coordinates/ordinal % posListunit/nrCoordPerPoint[coordinates/SequenceNr] == 0 ) { attribute<float64> x := coordinates/point[org_rel]; attribute<float64> y := coordinates/point[org_rel + 1]; attribute<rdc_mm> p_mm := point(Round(y * 1000.0), Round(x * 1000.0), rdc_mm); attribute<posListunit> s := coordinates/SequenceNr[org_rel]; attribute<uint32> fo := coordinates/ordinal[org_rel] / posListunit/nrCoordPerPoint[s]; attribute<uint32> ro := pcount(s)[s]- fo - 1; } attribute<rdc_mm> geometry_mm (poly) := union_data( posList , points2sequence_pso( p/p_mm, p/s , isExterior ? p/ro : p/fo ) ); } attribute<rdc_mm> result (posList, poly) := impl/geometry_mm[rdc_mm]; } template ProcessPolygon { // begin case parameters unit<uint32> Exterior; attribute<rdc_mm> ExtGeometry(Exterior, poly); unit<uint32> Interior; attribute<rdc_mm> IntGeometry(Interior, poly); attribute<Exterior> Parent_rel(Interior); // end case parameters container impl { container IntUnion := optimized_union( Interior, Exterior, IntGeometry, Parent_rel ); attribute<uint32> count(Exterior) := pcount(parent_rel); unit<uint32> ExtCopy := range(Exterior, 0, #Exterior) { attribute<uint32> count2 := union_data(., count); } unit<uint32> nonTrivialExterior := select_with_org_rel(ExtCopy/count2 > 0) { attribute<Exterior> Exterior_rel := value(org_rel, Exterior); attribute<rdc_mm> diff(poly) := ExtGeometry[Exterior_rel]- IntUnion/result[Exterior_rel]; attribute<rdc_mm> result(poly,Exterior) := impl/nonTrivialExterior/diff[ invert(impl/nonTrivialExterior/Exterior_rel) ]; } attribute<rdc_mm> result(poly,Exterior) := impl/count == 0 ? ExtGeometry : impl/result; attribute<int32> area (Exterior) := area(result, Int32); } template union { // begin case parameters unit<uint32> child; unit<uint32> parent; attribute<rdc_mm> geometry(child, poly); attribute<parent> parent_rel(child); // end case parameters attribute<rdc_mm> result(poly,parent) := partitioned_union_polygon(geometry, parent_rel); } template optimized_union { // begin case parameters unit<uint32> child; unit<uint32> parent; attribute<rdc_mm> geometry(child, poly); attribute<parent> parent_rel(child); // end case parameters container impl { attribute<uint32> count(parent) := pcount(parent_rel); unit<uint32> childCopy := range(child, 0, #child); unit<uint32> nonTrivialChild := select_with_org_rel((count != 1)[union_data(childCopy, parent_rel)]) { attribute<child> child_rel := value(org_rel, child); attribute<rdc_mm> union(poly,parent) := partitioned_union_polygon( geometry[child_rel] , parent_rel[child_rel] ); } } attribute<rdc_mm> result (poly,parent) := impl/count <= 1 ? geometry[invert(parent_rel)] : impl/nonTrivialChild/union; attribute<Int32> area (parent) := area(result, Int32); } template one2one_union { // begin case parameters unit<uint32> child; unit<uint32> parent; attribute<rdc_mm> geometry(child, poly); attribute<parent> parent_rel(child); // end case parameters container impl { parameter<bool> Check := (#child == #parent) && all(parent_rel == ID(child)); } attribute<rdc_mm> result(poly,parent) := union_data(parent, geometry) , IntegrityCheck = "impl/Check"; }