GeoCalc provides multiple methods for getting DatumShifts. If you know exactly what DatumShift you need, you can get it using the DataSource:;GetDatumShift 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 DatumShifts are needed, so the DataSource provides two methods to help you find the necessary DatumShifts. These methods are called EstablishDatumShift and GetValidDatumShifts. GeoCalc also provides a graphical way to find DatumShifts, in the form of the DatumShiftPicker dialog. This dialog can be used to find all of the valid DatumShifts and select the best ones.
In order to compile the code samples contained in this lesson, it will be necessary to include the WDataSource.h, WDispose.h, and WDatumShiftPicker.h header files.
We will first need to create and load a DataSource, since this is what contains all of the DatumShift definitions we will want to select. For more information about using the DataSource, see lesson 4.
DataSource * dataSource = 0;
dataSource = DataSource::CreateDataSource();
dataSource->LoadFile(L"c:\\bmg\\geocalcpbw\\data\\geocalc.xml", false, L"c:\\bmg\\geocalcpbw\\data\\custom.xml");
This method will allow you to specify some properties about the necessary DatumShifts, and then it will find some set of DatumShifts that satisfies these properties. This method requires two arguments: a CoordTransform object and a DatumShiftPreferences object. First, let's construct the CoordTransform. We will go into more depth about CoordTransforms in Lesson 7 and Lesson 8, but here we will just set the SourceCoordSys and TargetCoordSys properties, which indicate the input and output systems of the coordinate transformation.
CoordSys * source = dataSource->GetProjectedCoordSys(L"BMG", L"ME-27E");
CoordSys * target = dataSource->GetGeodeticCoordSys(L"BMG", L"WGS84_coordinate_system");
CoordTransform * ct = 0;
ct = CoordTransform::CreateCoordTransform(*source, *target);
Here, we have constructed a CoordTransform that will convert coordinates from the US State Plane 27 Maine East system to the WGS84 geodetic system. Since these systems use different HorizontalDatums, we will need some DatumShifts in order to convert points. Before we use the EstablishDatumShift method to get a set of DatumShifts, we must create a DatumShiftPreferences object that describes some properties about the necessary DatumShifts. Suppose we want a set of DatumShifts that uses the Molodensky method, we don't care if the DatumShifts go through an intermediate HorizontalDatum, and we don't care about checking whether Envelopes match up. Then we would construct the DatumShiftPreferences object like this:
DatumShiftPreferences * shiftPrefs = 0;
shiftPrefs = DatumShiftPreferences::CreateDatumShiftPreferences();
shiftPrefs->set_Method(DatumShift::ClassType::Molodensky);
int options = DatumShiftPreferences::ProcFlags::Direct |
DatumShiftPreferences::ProcFlags::ViaIntermediary |
DatumShiftPreferences::ProcFlags::IgnoreArea;
shiftPrefs->set_Options(options);
Now we are ready to get our DatumShifts with a call to the EstablishDatumShift method:
if(! dataSource->EstablishDatumShift(*ct, *shiftPrefs))
{
// Then no DatumShifts could be found
return;
}
If this method succeeds, then the CoordTransform::DatumShifts property will be populated with some DatumShifts that satisfy the properties described in the DatumShiftPreferences object and will shift from the SourceCoordSys to the TargetCoordSys of the CoordTransform.
This method will find all sets of DatumShifts that satisfy our requirements and then let us decide which set will work best. It requires four arguments, the first of which is the source CoordSys for the desired DatumShifts, the second of which is the target CoordSys for the DatumShifts, the third of which is a DatumShiftPreferencesEx object that describes the nature of the desired DatumShifts, and the fourth of which is a DatumShiftInfoSetCollection object that will hold information about the DatumShifts that fit our requirements. Let's start by constructing a CoordTransform in the same way we did above. Once again, we will go into more depth about the CoordTransform object in Lesson 7 and Lesson 8.
CoordSys * source = dataSource->GetProjectedCoordSys(L"BMG", L"ME-27E");
CoordSys * target = dataSource->GetGeodeticCoordSys(L"BMG", L"WGS84_coordinate_system");
CoordTransform * ct = 0;
ct = CoordTransform::CreateCoordTransform(*source, *target);
Now we must construct a DatumShiftPreferencesEx object that describes the nature of the DatumShifts that we want. Let's suppose we are interested in DatumShifts that use either the Molodesky or Bursa-Wolfe method, and that we don't care if the DatumShifts use an intermediate HorizontalDatum, or if the Envelopes match. Then we would define our DatumShiftPreferencesEx like this:
DatumShiftPreferencesEx * shiftPrefsEx = 0;
shiftPrefsEx = DatumShiftPreferencesEx::CreateDatumShiftPreferencesEx();
int flagz = DatumShiftPreferencesEx::BitFlag::Molodensky_flag |
DatumShiftPreferencesEx::BitFlag::BursaWolfe_flag;
shiftPrefsEx->set_BitFlags((DatumShiftPreferencesEx::BitFlag)flagz);
shiftPrefsEx->set_OnlyGoThruIntermediate(false);
There is one more step we must take before we will be ready to use the GetValidDatumShifts method: we must construct a DatumShiftInfoSetCollection object to hold the result of the method:
DatumShiftInfoSetCollection * shiftSets = 0;
shiftSets = new DatumShiftInfoSetCollection();
Now we are ready to find our DatumShifts:
if(! dataSource->GetValidDatumShifts(ct->get_SourceCoordSys(), ct->get_TargetCoordSys(), *shiftPrefsEx, *shiftSets))
{
// Then no DatumShifts could be found
return;
}
We now have a DatumShiftInfoSetCollection that is full of some number of DatumShiftInfoSets, each of which is full of some number of DatumShiftInfo objects. Each DatumShiftInfoSet represents a complete set of DatumShifts that will shift from our CoordTransform's SourceCoordSys to its TargetCoordSys. Each DatumShiftInfo object contains all of the information necessary to get a DatumShift from the DataSource. We are now presented with the task of determining which DatumShiftInfoSet should be used to populate our CoordTransform::DatumShifts property, and this task is outside the scope of this tutorial. For this lesson, let's just use the first DatumShiftInfoSet in the collection:
ct->get_DatumShifts().Clear();
DatumShiftInfoSetCollection::iterator dsiSet = shiftSets->begin();
DatumShiftInfoSet::iterator dsi;
for(dsi = (*dsiSet).begin(); dsi != (*dsiSet).end(); dsi++)
{
DatumShift * ds = dataSource->GetDatumShift(dsi->get_Code());
if(dsi->get_ReverseUsage())
{
ds->set_ReverseUsage(true);
}
ct->get_DatumShifts().AddBack(*ds);
Disposal::Dispose(ds);
}
Our CoordTransform now has all of the DatumShifts it will need to perform the transformation. For more information about using CoordTransforms, see Lesson 7 and Lesson 8.
The DatumShiftPicker dialog provides a graphical interface that accomplishes the same task as the GetValidDatumShifts method. You supply the dialog with the source and target CoordSys objects as well as a DatumShiftPreferencesEx object, and it finds all of the DatumShifts that meet those criteria. Once the DatumShifts are found, they are displayed to the users so that the user can select which ones will work best. The selected DatumShift objects are then put into a DatumShiftCollection for use by the user.
As with the previous methods, let's start by constructing a CoordTransform object. We will go into more depth about the CoordTransform object in Lesson 7 and Lesson 8.
CoordSys * source = dataSource->GetProjectedCoordSys(L"BMG", L"ME-27E");
CoordSys * target = dataSource->GetGeodeticCoordSys(L"BMG", L"WGS84_coordinate_system");
CoordTransform * ct = 0;
ct = CoordTransform::CreateCoordTransform(*source, *target);
Now we must construct a DatumShiftPreferencesEx object that describes the nature of the DatumShifts that we want. Let's suppose we are interested in DatumShifts that use either the Molodesky or Bursa-Wolfe method, and that we don't care if the DatumShifts use an intermediate HorizontalDatum, or if the Envelopes match. Then we would define our DatumShiftPreferencesEx like this:
DatumShiftPreferencesEx * shiftPrefsEx = 0;
shiftPrefsEx = DatumShiftPreferencesEx::CreateDatumShiftPreferencesEx();
int flagz = DatumShiftPreferencesEx::BitFlag::Molodensky_flag |
DatumShiftPreferencesEx::BitFlag::BursaWolfe_flag;
shiftPrefsEx->set_BitFlags((DatumShiftPreferencesEx::BitFlag)flagz);
shiftPrefsEx->set_OnlyGoThruIntermediate(false);
We now have enough information to construct the DatumShiftPicker dialog. The constructor requires four arguments, the first of which is an instance of the DataSource, the second of which is the source CoordSys for the desired DatumShifts, the third of which is the target CoordSys for the desired DatumShifts, and the fourth of which is the DatumShiftPreferencesEx object that describes the nature of the desired DatumShifts.
DatumShiftPicker * dsPicker = 0;
dsPicker = DatumShiftPicker::CreateDatumShiftPicker(dataSource, ct->get_SourceCoordSys(), ct->get_TargetCoordSys(), *shiftPrefsEx);
Once it has been constructed, the DatumShiftPicker will not be displayed until we call the Show method. The Show method requires a single argument, which is the DatumShiftCollection that will hold the DatumShifts that the user selects, and it returns a member of the EDialogState enumeration that indicates the result of showing the dialog. Here is how we show the dialog:
DatumShiftCollection * selectedShifts = 0;
selectedShifts = DatumShiftCollection::CreateDatumShiftCollection();
EDialogState state = dsPicker->Show(&selectedShifts);
if(state == eDialogStateSuccess)
{
ct->set_DatumShifts(*selectedShifts);
}
Here is an example of the appearance of the DatumShiftPicker dialog:

If the return value is either eDialogStateNoShiftNeeded or eDialogStateNoChoices, then the dialog was not ever shown. The return value eDialogStateNoShiftNeeded indicates that the dialog was not shown because there was no DatumShift required to perform the CoordTransform. This can occur when both the SourceCoordSys and the TargetCoordSys use the same HorizontalDatum. The return value eDialogStateNoChoices indicates that a DatumShift is required for the CoordTransform, but a suitable DatumShift could not be found in the DataSource. This can occur if the SourceCoordSys and TargetCoordSys use user-defined HorizontalDatum for which there are not DatumShifts. If the return value is eDialogStateCancel, then the user clicked the Cancel button, and no DatumShifts were selected. If the return value is eDialogStateSuccess, then the dialog was displayed, the user selected some DatumShifts, and the selected DatumShifts were put into the DatumShiftCollection passed to the Show method.
The DatumShiftPicker dialog also provides the option of choosing to not to apply any DatumShifts to the CoordTransform. This option can be selected by choosing "None" in the Category Pane of the DatumShiftPicker. 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.
Finally, we must clean up after ourselves and free the memory that we have allocated in this lesson using the Disposal::Dispose method:
if(ct) Disposal::Dispose(ct);
if(source) Disposal::Dispose(source);
if(target) Disposal::Dispose(target);
if(shiftPrefs) Disposal::Dispose(shiftPrefs);
if(shiftPrefsEx) Disposal::Dispose(shiftPrefsEx);
if(shiftSets) delete shiftSets;
if(dsPicker) Disposal::Dispose(dsPicker);
if(selectedShifts) Disposal::Dispose(selectedShifts);
if(dataSource) Disposal::Dispose(dataSource);