Use Domains - 52North/IlwisCore GitHub Wiki
[Domains] (https://github.com/52North/IlwisCore/wiki/Domain) are central in understanding how Ilwis deals with data and types.
Any numeric data that has a (semi) continous range of possible values. I say semi, because the resolution enforces that set of numbers that are actually available
INumericDomain numbers( new NumericRange(10, 50,1));
Constructs an integer domain between 10 and 50 (inclusive). The resolution of 1 (or any other non fractional positive number) will make sure that numbers are only integers.
INumericDomain numbers( new NumericRange(10,50));
Will create a similar domain but this time, because there is no resolution defined, it is a domain with floating point numbers with arbitrary precission.
INumericDomain numbers ( new NumericRange(10, 50, 0.1));
Again a similar domain. The resolution is 0.1. So 22.1 is part of the domain but 34.094 not. Apart from user-defined numeric domains there is also a set of predfined numeric domains
INumericDomain values("value"); // grand parent of all numeric domains; infinite range (almost) and arbitray precision.
INumericDomain values("image"); // 8-bits unsigned integers
INumericDomain values("image16"); // 16-bits unsigned integers
INumericDomain values("NDVI"); // -1, to 1 floating point
...
And then there is the non existing time domain
ITimeDomain times(new TimeInterval("20081104","20100130"));
Note that ITimeDomain is just a typedef for INumericDomain. TimeInterval is a specialized range that works with time values.
It has the usual containement functions
SPNumericRange myrange( new NumericRange(12,56));
INumericDomain numbers ( new NumericRange(10, 50, 0.1));
if ( numbers->contains(22.1))
cout << "I am in!"";
if ( !numbers->contains(myrange))
cout << "I am not";
Domains are the central in understanding what data actually means. For example, each RasterCoverage has a data-type some it must have a domain. Mostely domains are used in conjunction with the a concept (class) called the DataDefinition. A DataDefinition is basically a domain and a range. Though domain itself has a range, this range is the theoretical range of that data-type. The range of the data-definition is the actual range as encountered in that data-source.
IRasterCoverage raster("file:///d:/data/someraster.img");
IDomain numbers = raster->datadefinition().domain<>();
cout << "min value in the domain" << numbers->range<NumericRange>()->min();
cout << "max value in the domain" << numbers->range<NumericRange>()->max();
cout << "min value in the coverage" << raster->datadef().range<NumericRange>()->min();
cout << "maxv value in the coverage" << raster->datadef().range<NumericRange>()->max();
The domain returned from the datadefinition is a generic domain(internally it is numeric in this case). The method will cast it to the correct type. The range returned from the datadefintion is also a generic range, so we also need the cast it to a specialized case ( the range template does this).
An item domains is basically a range definition. So definining the range is important
NamedIdentifierRange idrange;
idrange << "Rome" << "London" << "Paris" << "Amsterdam" << "Berlin"; // fills the range
INamedIdentifierDomain iddomain; // uninitialized and still invalid domain
iddomain.prepare(); //initializes it, it is valid but no content yet
iddomain->range(idrange); // content added to it
INameIdentifierDomain otherids;
otherids.prepare();
otherids->range(iddomain->range()->clone()); // copies content of previous domain
Very similar to NamedIdentifier range. Range construction can be different though
ThematicRange classes;
classes << "broad-leaved forest|3.1.1|substantial component of trees in the Anthophyta" <<
"coniferous forest|3.1.2|evergreen conifers predominate" <<
"mixed forst|3.1.3" <<
"Natural grassland"
IThematicDomain landcover;
landcover.prepare();
landcover->range(classes);
The items in range can have 1 (only name), 2 ( name and code) or 3( name, code, description) properties, seperated by a '|' symbol.
Thematic domains can also be created by using predefined thematic domains (e.g. Corine).
IThematicDomain corine("code=domain:corine");
IThematicDomain wetlands("code=domain:ramsar");
The definition of these domains can be found under the installation folder of Ilwis-objects.
Thematic domains respect the normal rules for parent/child relations so
IThematicDomain corine("code=domain:corine");
classes->parent(corine);
if ( classes->contains("vineyards") == Domain::cPARENT)
cout << "is in parent";
Interval domains deal with numerical intervals. The range construction is similar to thematic domains
IntervalRange range1, rang2;
range1 << "first level|0|100" << "second level|101|400" << "end level|401|1000";
// or with resolution
range1 << "low|-200|100|10" << "medium|100|1000|20" << "high|1000|5000|100";
IIntervalDomain intervals;
intervals.prepare();
intervals->range(range1);
There are always either 3 or 4 elements(with resolution) in the definition of a interval element. As with all domains there are the usual containment methods
if (intervals->contains(145) == Domain::cSELF)
cout << "number is allowed";
A text domain is just a data type marker. The domain itself has no content as basically any thing that can be represented as a text is part of it. So there is no range. A text domain only has meaning in combination with the data source it is attached to. For example a column in a table might have a text domain. The reason a text domain exists is that it provides a common interface to interface with as everything other data source has a domain. There can be no additional information attached to the strings of the text domain. This also means that it is not usable in certain roles. E.g you cant make a raster with a text domain as it would be far too expensive to define for each pixel a text value. You can do it with for example a NamedIdentifierDomain because it has as attached meaning the raw value (an integer) so the raster can defined efficiently.