Lesson 6: Selecting Transforms

Overview

GeoCalc provides multiple methods for finding Coordinate Transformations between various Coordinate Systems. These transformations for both vertical and horizontal coordinate systems are derived from a base class called CoordTransform. If you know exactly what CoordTransform(s) you need, you can get them using the DataSource::GetCoordinateTransform method as described above in Lesson 4, or you can get it using the ObjectPicker or DataSourcePicker as described in Lesson 5. Often, it is not known exactly which CoordTransforms are required two more between coordinate systems, so the DataSource provides a method to help you find the best results for your given situation. This methods is called EstablishTransform. GeoCalc also provides a graphical interface that can be used to find CoordTransforms in the form of the TransformPicker dialog. We can provide this dialog with all the parameters that we want to use for limiting the available options, and the user will be presented with a visual interface listing any transform that meets the criteria.

In order to compile the code samples contained in this lesson, it will be necessary to include the WDataSource.h, WDispose.h, WTransformPreferences.h, WDatumTransform.h and WTransformPicker.h header files

We will first need to create and load a DataSource, since this is what contains all of the CoordTransform definitions we will want to select. For more information about using the DataSource, see Lesson 4.  

DataSource * dataSource = 0;

dataSource = DataSource::CreateDataSource();

dataSource->LoadFile(BMG_T("c:\\bmg\\geocalcpbw\\data\\geodata.xml"), BMG_T("C:\\bmg\\GeoCalcPBW\\data\\geodata.xvw"), true, BMG_T("C:\\bmg\\GeoCalcPBW\\data\custom.xml"), 0, 0, 0);

 

Method #1 - EstablishTransform

This method is extended by the Datasource class, and allows us to specify some properties about the necessary CoordTransforms, and then it will find some set of CoordTransforms that satisfies these properties.  

This method requires two arguments: a ConcatenatedTransform object and a TransformPreferences object.  

First, let's construct the ConcatenatedTransform.  

We will go into more depth about ConcatenatedTransform in Lesson 7 and Lesson 8, but here we will just set a single Source and Target, which indicate the input and output systems of the coordinate transformation.

CoordSys * source = dataSource->GetProjectedCoordSys(BMG_T("BMG"), BMG_T("ME-27E"));

CoordSys * target = dataSource->GetGeodeticCoordSys(BMG_T("BMG"), BMG_T("WGS84_coordinate_system"));

ConcatenatedTransform * concatTransform = 0;

concatTransform = ConcatenatedTransform::CreateConcatenatedTransform();

concatTransform->get_Sources().AddBack(*source);

concatTransform->get_Targets().AddBack(*target);

In the above code we have constructed a ConcatenatedTransform that will convert coordinates from the US State Plane 27 Maine East system to the WGS84 geodetic system. Since these systems use different BaseObjects, we will need some CoordTransforms in order to convert points. Before we use the EstablishTransform method to get a set of CoordTransforms, we must create a TransformPreferences object that describes the criteria we are going to use to limit the number of CoordTransforms returned to the user.  

Suppose we want a set of CoordTransforms that uses the Molodensky method, we don't want the CoordTransforms to go through an intermediate HorizontalDatum, and we want only transforms valid for the area of the point we are about to transform.  

Then we would construct the TransformPreferences object like this:

std::vector<GEOCALCPBW_NAMESPACE::DatumTransform::ClassType> allowedDatumTypes;

allowedDatumTypes.push_back(DatumTransform::Molodensky);

CoordPoint * areaPt = GeodeticPoint::CreateGeodeticPoint(2);

areaPt->set_InUnits(-69.79015279, 44.28761110); //A point in ME-27E

TransformPreferences * transPrefs = 0;

transPrefs = TransformPreferences::CreateTransformPreferences();

transPrefs->set_DatumTypes(allowedDatumTypes);

transPrefs->set_Restriction(TransformPreferences::RestrictionTypeDirectOnly);

transPrefs->get_Area().set_MinPoint(*areaPt);

transPrefs->get_Area().set_MaxPoint(*areaPt);

 

Now we are ready to get our CoordTransforms with a call to the EstablishTransform method:

 

if(! dataSource->EstablishTransform(*transPrefs, *concatTransform))

{

//Then no CoordTransforms could be found

return;

}

If this method succeeds, then the returned ConcatenatedTransform will be populated with a CoordTransform that satisfies the properties described in the TransformPreferences object, and will be ready to transform points between the source and target systems.

 

Method #2: TransformPicker Dialog

The TransformPicker dialog provides a graphical interface that allows the user to pick the Coordinate Transformations used in converting between our source and target coordinate reference systems. The dialog is provided with a template ConcatenatedTransform object, a TransformPreferences object, and a DataSource object, and it finds all of the CoordTransforms that meet the criteria specified in the TransformPreferences object which can provide a transform from the source systems to the target systems. Once the CoordTransforms are found, they are displayed to the user, so that they can select which ones will work best for their data. The selected CoordTransform objects are then returned in a fully defined ConcatenatedTransform that can be used immediately to transform points.

As with the previous methods, let's start by constructing a ConcatenatedTransform object. We will go into more depth about the ConcatenatedTransform object in Lesson 7 and Lesson 8.

CoordSys * source = dataSource->GetProjectedCoordSys(BMG_T("BMG"), BMG_T("ME-27E));

CoordSys * target = dataSource->GetGeodeticCoordSys(BMG_T("BMG"), BMG_T("WGS84_coordinate_system"));

ConcatenatedTransform * concatTransform = 0;

concatTransform = ConcatenatedTransform::CreateConcatenatedTransform();

concatTransform->get_Sources().AddBack(*source);

concatTransform->get_Targets().AddBack(*target);

Now we must construct a TransformPreferences object that describes the criteria we want to use for limiting the number of CoordTransforms displayed to the user. Let's suppose we are interested in CoordTransforms that use the NADCON method, are suited for use in Iowa, and we don't want the CoordTransforms to go through an intermediate GeodeticCoordSys. Then we would define our TransformPreferences like this:

std::vector<GEOCALCPBW_NAMESPACE::DatumTransform::ClassType> allowedDatumTypes;

allowedDatumTypes.push_back(DatumTransform::Nadcon);

AreaOfUse * AoU = dataSource->GetAreaOfUse(L"2198"); //AoU for Iowa;

TransformPreferences * transPrefs = 0;

transPrefs = TransformPreferences::CreateTransformPreferences();

transPrefs->set_DatumTypes(allowedDatumTypes);

transPrefs->set_Restriction(TransformPreferences::RestrictionTypeDirectOnly);

transPrefs->set_Area(*AoU);

We now have enough information to construct the TransformPicker dialog. The constructor requires three arguments, the first of which is an instance of the DataSource, the second of which is a ConcatenatedTransform containing the source and target coordinate reference systems, the third of which is the TransformPreferences object that describes the nature of the desired CoordTransforms.

GEOCALCPBW_NAMESPACE::TransformPicker * tPicker = 0;

tPicker = TransformPicker::CreateTransformPicker(dataSource, concatTransform, transPrefs);

Once it has been constructed, the TransformPicker will not be displayed until we call the Show method. The Show method requires a single argument, which is the ConcatenatedTransform which you want populated by the selected CoordTransforms. The Show() method returns a member of the EDialogState enumeration that indicates the result of showing the dialog.  

Here is how we show the dialog:

EDialogState state = tPicker->Show(concatTransform);

if(state == eDialogStateSuccess)

{

//The ConcatenatedTransform is ready to transform points

}

Here is an example of the appearance of the TransformPicker dialog:

As mentioned above, the Show method returns one of the following EDialogState types:

  1. eDialogStateNoTransformNeeded indicates that the dialog was not shown, because no CoordTransforms are required to perform the transformation.

  2. eDialogStateNoChoices indicates that some CoordTransforms are required for the transform, but no suitable CoordTransforms could be found in the DataSource.  

  3. eDialogStateCancel indicates that the user clicked the Cancel button, and no CoordTransforms were selected.  

  4. eDialogStateSuccess indicates that the dialog was displayed, the user selected some CoordTransforms, and the selected CoordTransforms were put into the ConcatenatedTransform passed to the Show method.

The TransformPicker dialog also provides the option of choosing to not to apply any CoordTransforms to the ConcatenatedTransform. This option can be selected by choosing "None" in the Category Pane of the TransformPicker.

 

Method #3 - HTDP Datum Transformations

HTDP transformations are selected like all other CoordTransforms. The only difference is the  way in which you setup the template ConcatenatedTransform. Since HTDP measures change over time, it relies on a specific input and output epoch date. This is specified using the SourceEpoch and TargetEpoch parameters on our ConcatenatedTransform. It is important to note that the only way to take advantage of the HTDP transformation is by using a source and target coordinate reference system that are based on an HTDP compatible geodetic coordinate system. 

What follows is an example of a basic conversion between two HTDP enabled HorizontalDatums. As in the earlier examples, we will start by constructing a simple ConcatenatedTransform.

CCoordSys * source = dataSource->GetProjectedCoordSys(L"BMG", L"ME83-E");

CoordSys * target = dataSource->GetGeodeticCoordSys(L"BMG", L"WGS84_coordinate_system");

ConcatenatedTransform * concatTransform = 0;

concatTransform = ConcatenatedTransform::CreateConcatenatedTransform();

concatTransform->get_Sources().AddBack(*source);

concatTransform->get_Targets().AddBack(*target);

In this case, the input coordinate system is on NAD83(1986) and the output coordinate reference system is a WGS84 geodetic. Once the ConcatenatedTransform exists, we can add the epochs to it. The input and output epoch dates must be defined in a decimal year format.  

double startepoch = TimeUtils::ToDecimalYears(1999,2,14);

double endepoch = TimeUtils::ToDecimalYears(2010,3,15);

concatTransform->set_SourceEpoch(startepoch);

concatTransform->set_TargetEpoch(endepoch);

Now when we create and display a standard TransformPicker dialog, it will contain a new category for HTDP CoordTransforms if available.

TransformPreferences * transPrefs = 0;

transPrefs = TransformPreferences::CreateTransformPreferences();

GEOCALCPBW_NAMESPACE::TransformPicker * tPicker = 0;

tPicker = TransformPicker::CreateTransformPicker(dataSource, concatTransform, transPrefs);

EDialogState state = tPicker->Show(concatTransform);

if(state == eDialogStateSuccess)

{

//The ConcatenatedTransform is ready to transform points

}

 

Clean Up

Finally, we must clean up after ourselves and free the memory that we have allocated in this lesson using the Disposal::Dispose method:

if(concatTransform) Disposal::Dispose(concatTransform);

if(source) Disposal::Dispose(source);

if(target) Disposal::Dispose(target);

if(transPrefs) Disposal::Dispose(transPrefs);

if(tPicker) Disposal::Dispose(tPicker);

if(dataSource) Disposal::Dispose(dataSource);