Polygon features from XML GML files - ObjectVision/GeoDMS GitHub Wiki
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";
}