Defining soil schemes
1.0 Texture Classes
This section will show you how to define a soil classification scheme in a data file, so that the soiltex class is able to load your scheme using the member function LoadScheme. This section will illustrate a hypothetical, simple soil classification scheme called XYZ (Fig. 1).
Fig. 1. The hypothetical XYZ soil classification scheme
The XYZ scheme has five texture classes, and note that all their borders (boundaries) are straight, not curved. This is a very important observation because soiltex class cannot handle curved borders.
Each of the XYZ texture classes can be described as a polygon located in a bi-axial (x, y) coordinate system, where the x-axis is %sand, and the y-axis is %clay. For example, the silt texture class in Fig. 1 is a polygon having three vertices (corners) of (30, 0), (0, 0), and (0, 30), where the first coordinate (30, 0) denotes 30% sand and 0% clay; the second (0, 0) is 0% for both sand and clay, and the third (0, 30) is 0% sand and 30% clay.
Please note that the z-axis is unused; only the x- and y-axis are used to describe the polygon vertices.
Describing the polygon vertices for other texture classes, the full result is (Table 1):
All the vertices in Table 1 are specified in a counter-clockwise direction, but you could also do this in a clockwise direction. This does not matter, as long as the vertices of a polygon are specified consecutively. It also does not matter which vertex of a polygon you start with. The silt texture polygon could alternatively be described as (0, 0), (0, 30), (30, 0).
Once you have defined the vertices of all texture class polygons, you will put this information in a plain text file in the following format:
[texture] XYZ sand clay silt silt 1 30 0 0 0 0 30 # silt loam 2 40 0 30 0 0 30 0 50 40 50 # clay 3 50 50 0 50 0 100 # sandy loam 4 70 0 40 0 40 50 50 50 70 30 # sand 5 100 0 70 0 70 30 #
where the first line of the file is the tag name "[texture]" so that soiltex class is able to know where the definitions start in the data file. If you want to put any comments in the file, you must put them before the "[texture]" tag.
The second line in the file is "XYZ" which is the name of the soil classification scheme.
The third to fifth line in the file denote the names of the chart axis x, y and z, respectively. In this example, x-axis is "sand", y-axis is "clay" and z-axis is "silt". Note that for some schemes, the x-, y- and z-axis are not always for "sand", "clay" and "silt", respectively; their meanings depend on the soil classification scheme (i.e., see the INEAC scheme).
The definitions of the texture classes start at the seventh line onwards (sixth line is left blank for easy readability, but you may start the definitions at the sixth line, if you wish), and they must follow this general format:
<name of texture class>
The <name of texture class> is the name of the texture class such as "silt", "silt loam", or "sandy loam". The <integer code of texture class> is a unique integer code identifying the texture class. The <list of polygon vertices> are the (x, y) coordinates of the texture class vertices (e.g., Table 1). Each value must be separated by tabs or spaces only. Lastly, the marker '#' denotes the end of definition for a texture class. Every definition of a texture class must end with this marker.
Finally, save the above data file as a plain text file, and you can load this scheme into a soiltex object by calling LoadScheme. Before using your scheme, however, it is a good idea to call IsSchemeValid to ensure your scheme is valid.
It is much easier to define the soil classification in a file, and load it into a soiltex object. However, you can also define the classification scheme using the soiltex member functions. From the XYZ example above, the following code excerpt is one way you can do this:
std::vector<tal::TEXTURE> vtc; // holds all definitions // definition of first texture: vtc.push_back(tal::TEXTURE()); vtc.mName = "silt"; vtc.mCode = 1; vtc.mPolygon.Add(tal::POINT(30, 0)); vtc.mPolygon.Add(tal::POINT(0, 0)); vtc.mPolygon.Add(tal::POINT(0, 30)); ... // definition of last texture: vtc.push_back(tal::TEXTURE()); vtc.mName = "sand"; vtc.mCode = 5; vtc.mPolygon.Add(tal::POINT(100, 0)); vtc.mPolygon.Add(tal::POINT(70, 0)); vtc.mPolygon.Add(tal::POINT(70, 30)); tal::soiltex soil; // our soiltex object soil.SetSchemeName("XYZ"); // give our scheme a name soil.SetAxisX("sand"); // x-axis is for sand soil.SetAxisY("clay"); // y-axis is for clay soil.SetAxisZ("silt"); // z-axis is for silt soil.SetTexture(vtc); // definitions of all texture classes
2.0 Modified borders
Modified borders refer to the change of default behaviours of borders. For example, consider 40% sand and 40% clay in the XYZ scheme. In Fig. 1, this particle-size distribution lies exactly at the border of two texture classes: silt loam and sandy loam. By default, the texture class result is "silt loam - sandy loam". However, some classification schemes like the USDA scheme do not follow this default behaviour for all their borders.
This section, using the XYZ example, will show you how to alter the behaviour of some borders. Assume you want to change the behaviour of the following borders (Table 2):
In Table 2, when the particle-size distribution is exactly at the border of silt loam and sandy loam, the texture class is "sandy loam". Likewise, for a border case of silt loam, sandy loam and clay, the texture class is "sandy loam - clay".
You will now define the modified borders in a data file in the following format:
[texture] XYZ ... sand 5 100 0 70 0 70 30 # [border] 2 4 = 4 # 2 3 4 = 3 4 #
where the definitions for all modified borders are specified after the definitions for the texture classes in the same data file. The definitions for the modified borders start with tag name "[border]". This is followed by the definitions for every case of modified borders, and they follow this general format:
<list of default borders> = <list of desired border result>
The <list of default borders> is a list of default borders, denoted by their unique integer codes, and <list of desired border result> is a list of desired border result, denoted by their unique integer codes. Every integer code in the list must be delimited by spaces or tabs only.
Referring to Table 2, the definition "2 4 = 4" means when the particle-size distribution is exactly at the border of silt loam (code 2) and sandy loam (4), the texture class is sandy loam (4). Likewise, "2 3 4 = 3 4" means the desired texture class is clay (3) and sandy loam (4) for cases when the particle-size distribution is exactly at the border of three texture classes: silt loam (2), clay (3), and sandy loam (4).
Lastly, the definition for every case of modified borders must end with the marker '#'.
It is much easier to define the modified borders in a file, and load it into a soiltex object. However, you can also define the modified borders using the soiltex member functions. From the XYZ example above, the following code excerpt is one way you can do this:
std::vector<tal::MODBOD> vmb; // holds all definitions // definition of first case: vmb.push_back(tal::MODBOD()); vmb.mFrom.push_back(2); vmb.mFrom.push_back(4); vmb.mTo.push_back(4); // "2 4 = 4" // definition of second case: vmb.push_back(tal::MODBOD()); vmb.mFrom.push_back(2); vmb.mFrom.push_back(3); vmb.mFrom.push_back(4); vmb.mTo.push_back(3); vmb.mTo.push_back(4); // "2 3 4 = 3 4" soil.SetModBorder(vmb); // soil is a soiltex object // from the code in section 1.1