In addition to the two-dimensional coordinate transformations described in Lesson 7, the CoordTransform object is also capable of performing three-dimensional coordinate transformations. Such a transformation can be performed when both the source and target coordinate systems have a valid VerticalReference.
Since all of the definitions we will be using reside in the DataSource, we will start by creating and loading a DataSource. For more information about the DataSource object, see Lesson 4.
Dim gcDataSource As New DataSource
gcDataSource.LoadFile ("c:\bmg\GeoCalcCOM\data\geocalc.xml")
var
gcDataSource : DataSource;
begin
gcDataSource := CoDataSource.Create;
gcDataSource.LoadFile('c:\bmg\GeoCalcCOM\data\geocalc.xml');
Performing a three-dimensional coordinate transformation is very similar to performing a two-dimensional coordinate transformation. As before, we must start by constructing a CoordTransform object, which will facilitate this transformation. In order to construct a CoordTransform, we will need to retrieve some ICoordSys definitions and some VerticalReferences from the DataSource. Since we want this to be a non-trivial lesson, let's pick some interesting objects. First, we want two different types of ICoordSys objects: a ProjectedCoordSys and a GeodeticCoordSys. Second, we want to select ICoordSys objects that use different HorizontalDatums so that we will need to use some DatumShifts. Finally, we should select two different VerticalReferences so that we need to perform a vertical transformation. These objects will suffice for this lesson:
Dim source As GeodeticCoordSys
Set source = gcDataSource.GetGeodeticCoordSys("BMG", "SIRGAS_GEODETIC")
source.VerticalReference = gcDataSource.GetVerticalReference("BMG", "CVD_GEOCOL04")
Dim target As ProjectedCoordSys
Set target = gcDataSource.GetProjectedCoordSys("BMG", "UTM-18N")
target.InnerGeodetic.VerticalReference = gcDataSource.GetVerticalReference("BMG", "ELLIPSOID_HEIGHT")
var
source : GeodeticCoordSys;
target : ProjectedCoordSys;
begin
source := gcDataSource.GetGeodeticCoordSys('BMG', 'SIRGAS_GEODETIC') as GeodeticCoordSys;
source.VerticalReference := gcDataSource.GetVerticalReference('BMG', 'CVD_GEOCOL04');
target := gcDataSource.GetProjectedCoordSys('BMG', 'UTM-18N');
(target.InnerGeodetic as GeodeticCoordSys).VerticalReference := gcDataSource.GetVerticalReference('BMG', 'ELLIPSOID_HEIGHT');
Here we have select the Sirgas GeodeticCoordSys with the Colombia Geoid Model of 2004 VerticalReference as our source coordinate system, and the UTM 18N ProjectedCoordSys with the ellipsoid height VerticalReference as our target coordinate system. So we are now ready to construct our CoordTransform:
Dim ct As New CoordTransform
ct.SourceCoordSys = source
ct.TargetCoordSys = target
var
ct : CoordTransform;
begin
ct := CoCoordTransform.Create;
ct.SourceCoordSys := source;
ct.TargetCoordSys := target;
Since our source and target coordinate systems use different HorizontalDatums, we will need to perform one or more DatumShifts. There are multiple ways to find the DatumShifts needed for a CoordTransform, and Lesson 6 describes these methods. For the purpose of this lesson, we will just retrieve a single DatumShift from the DataSource and put it into our CoordTransform::DatumShifts collection:
Dim ds As DatumShift
Set ds = gcDataSource.GetDatumShift("BMG", "SIRGAS_to_WGS84")
Set ds = ct.DatumShifts.InsertBack(ds)
var
ds : DatumShift;
begin
ds := gcDataSource.GetDatumShift('BMG', 'SIRGAS_to_WGS84');
ds := ct.DatumShifts.InsertBack(ds);
It is also possible to intentionally not use a DatumShift by not populating the DatumShifts property. Users should be aware that some coordinate shift may occur when shifting between ProjectedCoordSys' even though no DatumShift is being used. This can be occur if the source and target HorizontalDatums use different Ellipsoids.
Since our source and target coordinate systems use different VerticalReferences, we will need to perform a vertical transformation. This requires that we call the CoordTransform::InitializeVerticalTransform method before we try to transform any points with this CoordTransform.
Most of the HeightModels and VerticalDatums supported by GeoCalc require additional data files that were not installed with GeoCalc. All of these files can be obtained free of charge from our website. A description of the files needed by each HeightModel and VerticalDatum, as well as a link through which they can be downloaded, can be found on the description page for each HeightModel and each VerticalDatum. For the transformation described in this lesson, we will require the files for the Colombia Geoid Model of 2004. Without these files, the InitializeVerticalTransform method will raise an error.
Now that we have the necessary files, we can call the InitializeVerticalTransform method:
On Error GoTo InitVertTransError
If Not ct.InitializeVerticalTransform Then
MsgBox ("Unable to initialize a vertical transform")
End If
'''
InitVertTransError:
MsgBox (Err.Description)
try
if not ct.InitializeVerticalTransform then
begin
ShowMessage('InitializeVerticalTransform failed');
end;
except
on e : EOleException do ShowMessage(e.Message);
end;
The InitializeVerticalTransform method may raise an error. This indicates that GeoCalc is not capable of performing the requested vertical transformation. There could be several reasons for this, but the most common cause of this error is that one of our VerticalReferences uses a HeightModel that uses a HorizontalDatum that is not used by either the source or target ICoordSys. However, if you have set things up in the same way as is done in this lesson, you should not receive this error (nor should you receive any error for that matter).
Our CoordTransform is now set up and ready to perform a three dimensional coordinate transformation. As with the two-dimensional transformation as described in Lesson 7, we have the option of transforming either a single point or a list of points. Here we will only transform a single point. If you would like to transform many points at once, please see the section 'Transforming a Collection of Points' in lesson 7. The method of transforming multiple three-dimensional points is the same as the method for transforming multiple two-dimensional points.
We must take care when selecting a point to transform, because the Colombia Geoid Model of 2004 is only defined from 5 to 15 north latitude and from 66 to 80 west longitude. If we try to transform a point outside of that area, we will receive an error. Here is the GeodeticPoint we will transform, along with the expected value of the resulting ProjectedPoint:
|
|
Sirgas Geodetic |
|
|
UTM 18N |
|
Latitude |
10 Degrees |
|
North |
1105578.58919244 Meters |
|
Longitude |
-76 Degrees |
|
East |
390399.22748554 Meters |
|
Height |
123 Meters |
|
Height |
120.75025305 Meters |
Here is how we perform the transformation:
Dim inPt As ICoordPoint
Dim outPt As ICoordPoint
Dim temp As ICloneable
Set temp = ct.SourceCoordSys.PointStyle
Set inPt = temp.Clone
Set temp = ct.TargetCoordSys.PointStyle
Set outPt = temp.Clone
inPt.SetInUnits -76, 10, 123
ct.ConvertAhead inPt, outPt
Dim lon As Double
Dim lat As Double
Dim height As Double
outPt.GetInUnits lon, lat, height
var
inPt : ICoordPoint;
outPt : ICoordPoint;
lon : double;
lat : double;
height : double;
begin
(ct.SourceCoordSys.PointStyle as ICloneable).Clone(IInterface(inPt));
(ct.TargetCoordSys.PointStyle as ICloneable).Clone(IInterface(outPt));
inPt.SetInUnits(-76, 10, 123);
ct.ConvertAhead(inPt, outPt);
outPt.GetInUnits(lon, lat, height);
The values of east, north, and height should now match the corresponding values shown above.