VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
exampleCoordinateDisplay

Table of Contents

Overview

This example shows how to create and install a new Coordinate Display through a plugin.

Expected Result

exampleCoordinateDisplay.png
Coordinate Display Result

Example details

It implements the abstract class DtCoordinateDisplay to provide for the display of coordinates in the Swiss National Grid (CH1903) coordinate system.

The file exampleCoordinateDisplayPlugin.h sets up the necessary DLL export macros

#ifdef _WIN32
#ifdef EXAMPLECOORDINATEDISPLAY_EXPORTS
#define DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN __declspec ( dllexport )
#else
#define DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN __declspec ( dllimport )
#endif
#else
#define DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN
#endif
#define DT_DE_PLUGIN_EXPORT_MACRO DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN

The file exampleCoordinateDisplayPluginInit.cxx contains the implementation of the methods needed to initialize the plugin.

initDeModule is the method that will be called to initialize the plugin. It calls the init function and simply returns true.

// Declare & export the plugin initialization function (bool initDeModule(DtDe* de))
#include "sngDisplay.h"
#include <vrvCore/DtDe.h>
using namespace makVrv;
namespace vrvExampleCoordinateDisplayPlugin
{
void installCoordinateDisplay(DtDe& de)
{
// If you are adding multiple custom coordinate systems, you should
// call addCoordinateDisplay for all of them
}

The init method does the plugin initialization.

void init(DtDe& de)
It first ensures that the plugin is only initialized once by calling the standard initialization exclusion macro:

It then checks to make sure the plugin is only initialized for master display engines:

if (de.isInMasterMode())

Provided it is a master display engine, it connects the installCoordinateDisplay method to the display engine's signal_initializeDefaultState, which will be raised after the display engine's shared state has been initialized (a prerequisite for installing the coordinate display):

de.signal_initializeDefaultState.connect(std::bind(

The installCoordinateDisplay function installs an SngCoordinateDisplayObject.

void installCoordinateDisplay(DtDe& de)

It creates an instance of an SngCoordinateDisplay and adds it to the coordinate system's list of coordinate display objects:

// call addCoordinateDisplay for all of them
de.sharedState().coordinateSystem().displays().addCoordinateDisplay(
new SngCoordinateDisplay( de.sharedState().coordinateSystem() ) );

sngDisplay.h contains the declaration of the SngCoordinateDisplay class.

SngCoordinateDisplay inherits from makVrv::DtCoordinateDisplay:

It defines a static constant to provide a numerical identifier to the type of coordinate system it displays. Note that this must be unique. In the example, we use the first available user-defined value:

Declarations are provided to override the following DtCoordinateDisplay methods:

virtual makVrv::DtUnicode xAxisLabel() const;
virtual makVrv::DtUnicode yAxisLabel() const;
virtual makVrv::DtUnicode zAxisLabel() const;
const DtVector& geocPos, int decimals, double gridSpacing, bool minimal = false) override;
const DtVector& geocPos, int decimals, double gridSpacing, bool minimal = false) override;
virtual std::vector<std::string> convertPositionToStringList(
DistanceUnits unit, const DtVector& geocPos, int decimals) const override;
virtual std::vector<makVrv::DtUnicode> convertPositionToNotatedStringList(
DistanceUnits unit, makVrv::DtUnicode unitNotation, const DtVector& geocPos, int decimals, bool minimal = false) const override;
virtual void convertToGeocentric( const std::string& x,
const std::string& y, const std::string& z, DistanceUnits distUnits,
DistanceUnits altUnits, DtVector& vector);
virtual makVrv::DtUnicode name() const;
DtVector convertFromGeocentric( const DtVector& geoc ) const;
DtTaitBryan headingPitchRollFor( const DtVector& location,
const DtTaitBryan& geocOri ) const;
DtTaitBryan localOrientationFor( const DtVector& location,
const DtTaitBryan& geocOri ) const;
DtTaitBryan orientationFor( const DtVector& location,
const DtTaitBryan& geocOri, bool local ) const;
void regularExpressionValidator( std::string& x, std::string& y,
std::string& z );

Two protected methods unique to the class are provided for converting between SNG and WGS84 coordinates:

static void convertWGS84ToSNG(const DtVector& InVector,
DtVector& OutVector);
static void convertSNGToWGS84(const DtVector& InVecPos,
DtVector& OutVecPos );

sngDisplay.cxx contains the implementation of these methods.

Building the Example

VR-Vantage includes pre-built versions of the example plug-in. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.

Running the Example

This example is a plug-in. You can run it by running ./bin64/exampleCoordinateDisplay_stealth.bat (on Windows) or ./bin64/exampleCoordinateDisplay_stealth.sh (on Linux). Load "MAK Earth (online).earth" terrain, open the Observer Information Panel ("View->Observer Information Panel"), select the "SNG System" entry from the "System" dropdown box. While moving the observer, you will see the location displayed in the Observer Information Panel change based on the newly added coordinate system. Also note that in the 'Settings->Display Settings...->Grid Lines Settings' dialog page, "SNG System" is listed as an entry but it is disabled. This is because we loaded the MAK Earth (online) terrain which is a geocentric terrain. The example source code indicates the added coordinate display can only be used with grid lines when a 'Flat Earth' terrain is loaded. For more information about running examples, please see Running Applications and Examples.

Example Source Files


exampleCoordinateDisplayPlugin.h

/******************************************************************************
** Copyright (c) 2019 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#pragma once
#ifdef _WIN32
#ifdef EXAMPLECOORDINATEDISPLAY_EXPORTS
#define DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN __declspec ( dllexport )
#else
#define DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN __declspec ( dllimport )
#endif
#else
#define DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN
#endif
#define DT_DE_PLUGIN_EXPORT_MACRO DT_DLL_EXAMPLECOORDINATEDISPLAYPLUGIN

exampleCoordinateDisplayPluginInit.cxx

/******************************************************************************
** Copyright (c) 2023 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
// Declare & export the plugin initialization function (bool initDeModule(DtDe* de))
#include "sngDisplay.h"
#include <vrvCore/DtDe.h>
using namespace makVrv;
namespace vrvExampleCoordinateDisplayPlugin
{
void installCoordinateDisplay(DtDe& de)
{
// If you are adding multiple custom coordinate systems, you should
// call addCoordinateDisplay for all of them
}
void init(DtDe& de)
{
// Ensure that init only gets called once
// (not strictly necessary here, but this is good practice in general)
// We only want to add the coordinate display if we are running in master mode.
if (de.isInMasterMode())
{
// The coordinate display must be created after the DE's initialization of
// shared state is finished, but before any de observer announcements.
&installCoordinateDisplay, std::ref(de) ));
}
}
}
{
// Setup the plug-in. Normally, the init function and functionality
// should be in its own library.
return true;
}

sngDisplay.h

/******************************************************************************
** Copyright (c) 2022 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#pragma once
{
public:
// Extend the CoordSys enumeration
static const CoordSys CoordSysSNG =
virtual makVrv::DtUnicode xAxisLabel() const;
virtual makVrv::DtUnicode yAxisLabel() const;
virtual makVrv::DtUnicode zAxisLabel() const;
const DtVector& geocPos, int decimals, double gridSpacing, bool minimal = false) override;
const DtVector& geocPos, int decimals, double gridSpacing, bool minimal = false) override;
virtual std::vector<std::string> convertPositionToStringList(
DistanceUnits unit, const DtVector& geocPos, int decimals) const override;
virtual std::vector<makVrv::DtUnicode> convertPositionToNotatedStringList(
DistanceUnits unit, makVrv::DtUnicode unitNotation, const DtVector& geocPos, int decimals, bool minimal = false) const override;
virtual void convertToGeocentric( const std::string& x,
const std::string& y, const std::string& z, DistanceUnits distUnits,
DistanceUnits altUnits, DtVector& vector);
virtual makVrv::DtUnicode name() const;
DtVector convertFromGeocentric( const DtVector& geoc ) const;
DtTaitBryan headingPitchRollFor( const DtVector& location,
const DtTaitBryan& geocOri ) const;
DtTaitBryan localOrientationFor( const DtVector& location,
const DtTaitBryan& geocOri ) const;
DtTaitBryan orientationFor( const DtVector& location,
const DtTaitBryan& geocOri, bool local ) const;
void regularExpressionValidator( std::string& x, std::string& y,
std::string& z );
protected:
static void convertWGS84ToSNG(const DtVector& InVector,
DtVector& OutVector);
static void convertSNGToWGS84(const DtVector& InVecPos,
DtVector& OutVecPos );
};

sngDisplay.cxx

/******************************************************************************
** Copyright (c) 2022 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
#include "sngDisplay.h"
// Additional includes for the SNG Display
#include <matrix/vlTaitBryan.h>
#ifdef __linux__
#include <stdio.h>
#endif
#define PI 3.14159265
#define RAD2DEG(x) (x * 180/PI)
#define DEG2RAD(x) (x * PI/180)
using namespace makVrv;
{
addSupportedCSForGridLines( DtCoordinateConverter::FlatEarth );
}
{
}
{
return DtUnicode::tr("SNG System");
}
{
return DtUnicode::tr("E");
}
{
return DtUnicode::tr("N");
}
{
return DtUnicode::tr("Alt");
}
const DtVector& geocPos, int decimals, double gridSpacing, bool minimal/*=false*/)
{
std::vector<std::string> lst = convertPositionToStringList( unit, geocPos, decimals );
return DtUnicode::fromAscii( lst[1] );
}
const DtVector& geocPos, int decimals, double gridSpacing, bool minimal/*=false*/)
{
std::vector<std::string> lst = convertPositionToStringList( unit, geocPos, decimals );
return DtUnicode::fromAscii( lst[0] );
}
const DtVector& geocPos, int decimals) const
{
DtGeodeticCoord geodeticPosition;
geodeticPosition.setGeocentric(geocPos);
DtVector InVector(RAD2DEG(geodeticPosition.lat()), RAD2DEG(geodeticPosition.lon()), geodeticPosition.alt());
DtVector OutVector;
convertWGS84ToSNG(InVector, OutVector);
const DtDistanceUnitConverter* altConverter =
double alt = altConverter->metersToLocal(OutVector.z());
char buffer[256];
std::vector<std::string> results;
DtSnprintf(buffer, 256, "%.0f", OutVector.x());
results.push_back(std::string(buffer));
DtSnprintf(buffer, 256, "%.0f", OutVector.y());
results.push_back(std::string(buffer));
DtSnprintf(buffer, 256, "%.*f", decimals, alt);
results.push_back(std::string(buffer));
return results;
}
DistanceUnits unit, makVrv::DtUnicode unitNotation, const DtVector& geocPos, int decimals, bool minimal/*=false*/) const
{
std::vector<std::string> nonNotatedResult = convertPositionToStringList(unit, geocPos, decimals);
// copy over non-notated vector
std::vector<DtUnicode> results;
for (std::string result : nonNotatedResult)
{
results.push_back(DtUnicode::fromAscii(result));
}
{
// The default unit of measurement to revert to is meters
unitNotation = DtUnicode::fromAscii("m");
}
// add notation
for (DtUnicode& result : results)
{
result += DtUnicodeChar(' ');
result += unitNotation;
}
return results;
}
void SngCoordinateDisplay::convertToGeocentric(const std::string& x, const std::string& y, const std::string& z,
DtVector& vector)
{
DtVector InVector( distConverter->localToMeters( atof(x.c_str() ) ),
distConverter->localToMeters( atof( y.c_str()) ),
altConverter->localToMeters( atof( z.c_str() ) ) );
DtVector OutVector;
convertSNGToWGS84(InVector, OutVector);
DtGeodeticCoord geod;
geod.setLat(DEG2RAD(OutVector.x()));
geod.setLon(DEG2RAD(OutVector.y()));
geod.setAlt(OutVector.z());
vector = geod.geocentric();
}
void SngCoordinateDisplay::convertWGS84ToSNG( const DtVector& InVecPos, DtVector& OutVecPos )
{
if ( InVecPos.x() == 0.0 && InVecPos.y() == 0.0 && InVecPos.z() == 0.0 )
{
return;
}
double lamdaTag = ( InVecPos.y() * 3600 - 26782.5 ) / 10000.0;
double lamdaTag2 = lamdaTag * lamdaTag;
double lamdaTag3 = lamdaTag2 * lamdaTag;
double phiTag = ( InVecPos.x() * 3600 - 169028.66 ) / 10000.0;
double phiTag2 = phiTag * phiTag;
double phiTag3 = phiTag2 * phiTag;
OutVecPos.setY( 200147.07 +
(308807.95 * phiTag) +
(3745.25 * lamdaTag2) +
(76.63 * phiTag2) -
(194.56 * lamdaTag2 * phiTag) +
(119.79 * phiTag3) );
OutVecPos.setX( 600072.37 +
(211455.93 * lamdaTag) -
(10938.51 * lamdaTag * phiTag) -
(0.36 * lamdaTag * phiTag2) -
(44.54 * lamdaTag3) );
OutVecPos.setZ(InVecPos.z() -
49.55 +
(2.73 * lamdaTag) +
(6.94 * phiTag) );
}
void SngCoordinateDisplay::convertSNGToWGS84(const DtVector& InVecPos, DtVector& OutVecPos )
{
if ( InVecPos.x() == 0.0 && InVecPos.y() == 0.0 && InVecPos.z() == 0.0 )
{
return;
}
double yTag = ( InVecPos.x() - 600000 ) / 1000000;
double yTag2 = yTag * yTag;
double yTag3 = yTag2 * yTag;
double xTag = ( InVecPos.y() - 200000 ) / 1000000;
double xTag2 = xTag * xTag;
double xTag3 = xTag2 * xTag;
OutVecPos.setX(( 2.6779094 +
(4.728992 * yTag) +
(0.791484 * yTag * xTag ) +
(0.1306 * yTag * xTag2) -
(0.0436 * yTag3) ) *
(100.0 / 36.0) );
OutVecPos.setY(( 16.9023892 +
(3.238272 * xTag) -
(0.270978 * yTag2) -
(0.002528 * xTag2) -
(0.0447 * yTag2 * xTag) -
(0.0140 * xTag3) ) *
(100.0/36.0) );
OutVecPos.setZ( InVecPos.z() +
49.55 -
(12.60 * yTag) -
(22.64 * xTag) );
}
{
DtVector localVec;
myCoordinateSystem.netToLocalPos( geoc, localVec );
return localVec;
}
DtTaitBryan SngCoordinateDisplay::headingPitchRollFor( const DtVector& location, const DtTaitBryan& geocOri ) const
{
return orientationFor( location, geocOri, false );
}
DtTaitBryan SngCoordinateDisplay::localOrientationFor( const DtVector& location, const DtTaitBryan& geocOri ) const
{
return orientationFor( location, geocOri, true );
}
void SngCoordinateDisplay::regularExpressionValidator( std::string& x, std::string& y, std::string& z )
{
x = "^-?[0-9]{1,9}\\.[0-9]{1,9}";
y = x;
z = x;
}
DtTaitBryan SngCoordinateDisplay::orientationFor( const DtVector& location, const DtTaitBryan& geocOri, bool local ) const
{
DtVector localPos;
DtTaitBryan localOri;
myCoordinateSystem.netToLocalPos( location, localPos );
myCoordinateSystem.netToLocalOri( localPos, geocOri, localOri );
// Clamp to [0,2Pi]
if ( localOri.psi() < 0 )
{
localOri.setPsi( localOri.psi() + 2 * PI );
}
return localOri;
}
{
if ( isSupportedPositionUnit( unit ) )
{
return unit;
}
}
{
if ( isSupportedPositionUnit( unit ) )
{
return unit;
}
}
{
if ( isSupportedPositionUnit( unit ) )
{
return unit;
}
}

[<< Examples] [Home] [Top of Page]


Document ID: Generated on Wed Mar 27 22:49:11 EDT 2024 from SVN revision 264633
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)