[mapguide-commits] r4212 - in trunk/MgDev/Common: CoordinateSystem
Geometry/CoordinateSystem Geometry/GeometryConsoleTest
Geometry/Spatial
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Tue Sep 8 18:16:32 EDT 2009
Author: NormOlsen
Date: 2009-09-08 18:16:31 -0400 (Tue, 08 Sep 2009)
New Revision: 4212
Modified:
trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h
trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h
trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h
trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h
trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp
trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h
trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp
trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.h
trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h
trunk/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.cpp
trunk/MgDev/Common/Geometry/Spatial/MathUtility.cpp
trunk/MgDev/Common/Geometry/Spatial/MathUtility.h
trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h
Log:
This submission includes most of the grid/graticule package per RFC 76. This version has been significantly debugged and, to a large degree, works as advertised. While no 100%, the code is being submitted to support other developers who need the updated portions of this API in order to continue their development efforts.
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -15,11 +15,12 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-#include "Spatial/MathUtility.h"
#include "GeometryCommon.h"
#include "CoordSysCommon.h"
#include "CoordSysUtil.h"
#include "CriticalSection.h"
+#include "Spatial/MathUtility.h"
+#include "Spatial/SpatialUtility.h"
#include "CoordSys.h"
#include "CoordSysGrids.h"
@@ -145,21 +146,29 @@
void CCoordinateSystemGridSpecification::SetGridBase(double eastingBase,double northingBase)
{
m_EastingBase = eastingBase;
- m_NorthingBase = m_EastingBase;
+ m_NorthingBase = northingBase;
}
void CCoordinateSystemGridSpecification::SetGridIncrement(double eastingIncrement,double northingIncrement)
{
m_EastingIncrement = eastingIncrement;
- m_NorthingIncrement = m_EastingIncrement;
+ m_NorthingIncrement = northingIncrement;
}
void CCoordinateSystemGridSpecification::SetTickIncrements(double eastingIncrement,double northingIncrement)
{
m_TickEastingIncrement = eastingIncrement;
- m_TickNorthingIncrement = m_TickEastingIncrement;
+ m_TickNorthingIncrement = northingIncrement;
}
void CCoordinateSystemGridSpecification::SetUnits (INT32 unitCode,INT32 unitType)
{
- //TODO: Should verify the validty of the two parameters.
+ bool codeOk;
+ INT32 lclUnitType;
+
+ codeOk = GetUnitInfo(unitCode,&lclUnitType,NULL);
+ if (!codeOk || unitType != lclUnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.SetUnits", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
m_UnitCode = unitCode;
m_UnitType = unitType;
}
@@ -168,86 +177,196 @@
m_CurvePrecision = curvePrecision;
}
-// The following function are identical to the published version, with the
+// The following functions are identical to the published version, with the
// exception that the value returned are always converted to the units of
// the provided coordinate system. Typically, the coodinate system
// provided as an argument will be that of the "grid" coordinate system.
double CCoordinateSystemGridSpecification::GetEastingBase (MgCoordinateSystem* gridCS)
{
+ INT32 gridUnitType;
+ INT32 gridCrsUnitCode;
+ double unitConversion;
+
MgCoordinateSystemCatalog* catalogPtr = gridCS->GetCatalog ();
MgCoordinateSystemUnitInformation* unitInfoPtr = catalogPtr->GetUnitInformation ();
+ gridCrsUnitCode = gridCS->GetUnitCode ();
+
+ // Verify that the unit type of the specification match the unit type
+ // of the grid coordinate system of the grid object.
+ GetUnitInfo(gridCrsUnitCode,&gridUnitType,NULL);
+ if (gridUnitType != m_UnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.GetEastingBase", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
- // TODO:
- // Should verify that the unit types of the "this" object and the provided
- // coordinate system are the same.
- double unitConversion = 1.0 / gridCS->GetUnitScale ();
+ // Calculate the appropriate units conversion factor.
if (m_UnitType == MgCoordinateSystemUnitType::Linear)
{
- unitConversion *= unitInfoPtr->GetLinearUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+ unitInfoPtr->GetLinearUnitScale (gridCrsUnitCode);
}
else
{
- unitConversion *= unitInfoPtr->GetAngularUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+ unitInfoPtr->GetAngularUnitScale (gridCrsUnitCode);
}
return (m_EastingBase * unitConversion);
}
double CCoordinateSystemGridSpecification::GetNorthingBase (MgCoordinateSystem* gridCS)
{
+ INT32 gridUnitType;
+ INT32 gridCrsUnitCode;
+ double unitConversion;
+
MgCoordinateSystemCatalog* catalogPtr = gridCS->GetCatalog ();
MgCoordinateSystemUnitInformation* unitInfoPtr = catalogPtr->GetUnitInformation ();
+ gridCrsUnitCode = gridCS->GetUnitCode ();
- // TODO:
- // Should verify that the unit types of the "this" object and the provided
- // coordinate system are the same.
- double unitConversion = 1.0 / gridCS->GetUnitScale ();
+ // Verify that the unit type of the specification match the unit type
+ // of the grid coordinate system of the grid object.
+ GetUnitInfo(gridCrsUnitCode,&gridUnitType,NULL);
+ if (gridUnitType != m_UnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.GetNorthingBase", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ // Calculate the appropriate units conversion factor.
if (m_UnitType == MgCoordinateSystemUnitType::Linear)
{
- unitConversion *= unitInfoPtr->GetLinearUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+ unitInfoPtr->GetLinearUnitScale (gridCrsUnitCode);
}
else
{
- unitConversion *= unitInfoPtr->GetAngularUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+ unitInfoPtr->GetAngularUnitScale (gridCrsUnitCode);
}
return (m_NorthingBase * unitConversion);
}
double CCoordinateSystemGridSpecification::GetEastingIncrement(MgCoordinateSystem* gridCS)
{
+ INT32 gridUnitType;
+ INT32 gridCrsUnitCode;
+ double unitConversion;
+
MgCoordinateSystemCatalog* catalogPtr = gridCS->GetCatalog ();
MgCoordinateSystemUnitInformation* unitInfoPtr = catalogPtr->GetUnitInformation ();
+ gridCrsUnitCode = gridCS->GetUnitCode ();
- // TODO:
- // Should verify that the unit types of the "this" object and the provided
- // coordinate system are the same.
- double unitConversion = 1.0 / gridCS->GetUnitScale ();
+ // Verify that the unit type of the specification match the unit type
+ // of the grid coordinate system of the grid object.
+ GetUnitInfo(gridCrsUnitCode,&gridUnitType,NULL);
+ if (gridUnitType != m_UnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.GetEastingIncrement", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ // Calculate the appropriate units conversion factor.
if (m_UnitType == MgCoordinateSystemUnitType::Linear)
{
- unitConversion *= unitInfoPtr->GetLinearUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+ unitInfoPtr->GetLinearUnitScale (gridCrsUnitCode);
}
else
{
- unitConversion *= unitInfoPtr->GetAngularUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+ unitInfoPtr->GetAngularUnitScale (gridCrsUnitCode);
}
return (m_EastingIncrement * unitConversion);
}
double CCoordinateSystemGridSpecification::GetNorthingIncrement(MgCoordinateSystem* gridCS)
{
+ INT32 gridUnitType;
+ INT32 gridCrsUnitCode;
+ double unitConversion;
+
MgCoordinateSystemCatalog* catalogPtr = gridCS->GetCatalog ();
MgCoordinateSystemUnitInformation* unitInfoPtr = catalogPtr->GetUnitInformation ();
+ gridCrsUnitCode = gridCS->GetUnitCode ();
- // TODO:
- // Should verify that the unit types of the "this" object and the provided
- // coordinate system are the same.
- double unitConversion = 1.0 / gridCS->GetUnitScale ();
+ // Verify that the unit type of the specification match the unit type
+ // of the grid coordinate system of the grid object.
+ GetUnitInfo(gridCrsUnitCode,&gridUnitType,NULL);
+ if (gridUnitType != m_UnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.GetNorthingIncrement", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ // Calculate the appropriate units conversion factor.
if (m_UnitType == MgCoordinateSystemUnitType::Linear)
{
- unitConversion *= unitInfoPtr->GetLinearUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+ unitInfoPtr->GetLinearUnitScale (gridCrsUnitCode);
}
else
{
- unitConversion *= unitInfoPtr->GetAngularUnitScale (m_UnitCode);
+ unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+ unitInfoPtr->GetAngularUnitScale (gridCrsUnitCode);
}
return (m_NorthingIncrement * unitConversion);
}
+double CCoordinateSystemGridSpecification::GetTickEastingIncrement(MgCoordinateSystem* gridCS)
+{
+ INT32 gridUnitType;
+ INT32 gridCrsUnitCode;
+ double unitConversion;
+
+ MgCoordinateSystemCatalog* catalogPtr = gridCS->GetCatalog ();
+ MgCoordinateSystemUnitInformation* unitInfoPtr = catalogPtr->GetUnitInformation ();
+ gridCrsUnitCode = gridCS->GetUnitCode ();
+
+ // Verify that the unit type of the specification match the unit type
+ // of the grid coordinate system of the grid object.
+ GetUnitInfo(gridCrsUnitCode,&gridUnitType,NULL);
+ if (gridUnitType != m_UnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.GetTickEastingIncremen", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ // Calculate the appropriate units conversion factor.
+ if (m_UnitType == MgCoordinateSystemUnitType::Linear)
+ {
+ unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+ unitInfoPtr->GetLinearUnitScale (gridCrsUnitCode);
+ }
+ else
+ {
+ unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+ unitInfoPtr->GetAngularUnitScale (gridCrsUnitCode);
+ }
+ return (m_TickEastingIncrement * unitConversion);
+}
+double CCoordinateSystemGridSpecification::GetTickNorthingIncrement(MgCoordinateSystem* gridCS)
+{
+ INT32 gridUnitType;
+ INT32 gridCrsUnitCode;
+ double unitConversion;
+
+ MgCoordinateSystemCatalog* catalogPtr = gridCS->GetCatalog ();
+ MgCoordinateSystemUnitInformation* unitInfoPtr = catalogPtr->GetUnitInformation ();
+ gridCrsUnitCode = gridCS->GetUnitCode ();
+
+ // Verify that the unit type of the specification match the unit type
+ // of the grid coordinate system of the grid object.
+ GetUnitInfo(gridCrsUnitCode,&gridUnitType,NULL);
+ if (gridUnitType != m_UnitType)
+ {
+ throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.GetTickNorthingIncrement", __LINE__, __WFILE__, NULL, L"", NULL);
+ }
+
+ // Calculate the appropriate units conversion factor.
+ if (m_UnitType == MgCoordinateSystemUnitType::Linear)
+ {
+ unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+ unitInfoPtr->GetLinearUnitScale (gridCrsUnitCode);
+ }
+ else
+ {
+ unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+ unitInfoPtr->GetAngularUnitScale (gridCrsUnitCode);
+ }
+ return (m_TickNorthingIncrement * unitConversion);
+}
double CCoordinateSystemGridSpecification::GetCurvePrecision (MgCoordinateSystem* gridCS)
{
double precisionInCsUnits (1.0);
@@ -289,17 +408,15 @@
delete this;
}
-//=============================================================================
-// CCoordinateSystemGridBoundary -- The boundary of the grid or graticule.
-//
-// In the case of geographic coordinates, internal longitude ordinates may
-// exceed 180 and latitude ordinates may exceed 90 to support wrap around in
-// a rational fashion.
-//
-// In this initial release, the boundary will be a rectangle, and this will
-// be enforced by the constructors which are supported. Expansion to support
-// more complex boundaries will be added by providing more constructors.
-//
+///////////////////////////////////////////////////////////////////////////////
+///<summary>
+/// The boundary of the grid or graticule. In the case of geographic
+/// coordinates, internal longitude ordinates may exceed 180 and latitude
+/// ordinates may exceed 90 to support wrap around in a rational fashion.
+/// In this initial release, the boundary will be a rectangle, and this will
+/// be enforced by the constructors which are supported. Expansion to support
+/// more complex boundaries will be added by providing more constructors.
+///</summary>
const INT32 CCoordinateSystemGridBoundary::MaxCurvePoints = 511;
CCoordinateSystemGridBoundary::CCoordinateSystemGridBoundary () : MgCoordinateSystemGridBoundary (),
m_Large (false),
@@ -449,17 +566,20 @@
}
}
result = new MgPolygon (exteriorRing,interiorRings);
- MG_CATCH_AND_THROW(L"MgCoordinateSystemGridBoundary.GetBoundaryExtents")
+ MG_CATCH_AND_THROW(L"MgCoordinateSystemGridBoundary.GetBoundary")
return result.Detach ();
}
MgLineStringCollection* CCoordinateSystemGridBoundary::ClipLineString (MgLineString* lineString) const
{
MgGeometryFactory factory;
Ptr<MgLineStringCollection> collection;
+ Ptr<MgCoordinateIterator> polyItr;
+ Ptr<MgCoordinateIterator> lineItr;
MG_TRY()
- collection = new MgLineStringCollection ();
- collection->Add (lineString);
+ polyItr = m_GridBoundary->GetCoordinates ();
+ lineItr = lineString->GetCoordinates ();
+ collection = MgSpatialUtility::ClipStringToPolygon (polyItr,lineItr);
MG_CATCH_AND_THROW(L"MgCoordinateSystemGridBoundary.ClipLineString")
return collection.Detach ();
}
@@ -485,7 +605,7 @@
MG_TRY ()
// NOTE: Boundaries are required to proceed in a counterclockwise
// direction, but this function will be used to transform both
- // exterior and interior rings. SO in this function we cannot count
+ // exterior and interior rings. So in this function we cannot count
// on any specific order. We should be able to rely on the fact that
// each ring presented to us is indeed closed.
@@ -493,31 +613,36 @@
// create an empty MgCoordinateCollection, and then spend most of our
// time adding points to this collection. The primary source of these
// points will be the MgLineStrings returned by the
- // MgCoordinateSystemTransform::GridLIne object. Perhaps that function
+ // MgCoordinateSystemTransform::GridLine object. Perhaps that function
// should be modified to return an MgCoordinateCollection? Probably
// doesn't make much difference as you can't (at least at thie time)
// add one coordinate collection to another. Too Bad!!!
targetCollection = new MgCoordinateCollection ();
-
+
ringItr = linearRing->GetCoordinates ();
ringItr->MoveNext ();
- curFromPnt = ringItr->GetCurrent ();
- copyBufr = transform->Transform (curFromPnt);
+ curToPnt = ringItr->GetCurrent ();
+ copyBufr = transform->Transform (curToPnt);
targetCollection->Add (copyBufr);
while (ringItr->MoveNext ())
{
// Convert the current segment.
+ curFromPnt = curToPnt;
curToPnt = ringItr->GetCurrent ();
convertedSegment = transform->GridLine (curFromPnt,curToPnt,curvePrecision,m_MaxCurvePoints);
-
+
// Copy the converted segment to the target coordinate collection.
lineItr = convertedSegment->GetCoordinates ();
-
- // To prevent duplicate points, we always skip adding the initial point
- // of a converted line string. We dealt with the initial point of the
- // first segment above.
+
+ // To prevent duplicate points, we always skip adding the initial
+ // point of a converted line string. We dealt with the initial
+ // point of the first segment above. The first point of each
+ // additional line segment will have been processed as the "to"
+ // point of the last segment processed. Always adding the last
+ // point of each segment means we don't need to worry about an
+ // extra point when we are done.
lineItr->MoveNext ();
-
+
// Copy the remainder of the converted line segment.
while (lineItr->MoveNext ())
{
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -57,6 +57,8 @@
double GetNorthingBase (MgCoordinateSystem* gridCS);
double GetEastingIncrement(MgCoordinateSystem* gridCS);
double GetNorthingIncrement(MgCoordinateSystem* gridCS);
+ double GetTickEastingIncrement(MgCoordinateSystem* gridCS);
+ double GetTickNorthingIncrement(MgCoordinateSystem* gridCS);
double GetCurvePrecision(MgCoordinateSystem* gridCS);
protected:
@@ -84,26 +86,148 @@
class CCoordinateSystemGridBoundary : public MgCoordinateSystemGridBoundary
{
public:
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Default value representing the limit at which curve generation will
+ /// always stop so as to reduce the possibility of an infinite loop. The
+ /// limit is applied after each generation cycle, so the actual number of
+ /// points in a line may be as much as twice this value. All GridBoundary
+ /// objects will have there m_MaxCurvePoints member variable initialized
+ /// to this value.
static const INT32 MaxCurvePoints;
- // Contrary to other envelope objects, the first of these overloads specifically
- // requires that the southwest argument indeed be southwest of the northeast
- // argument. Necessary to support geographic coordinate systems (i.e. +/- 180).
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Default Constructor. Use one of the two SetBoundary overlaods defined
+ /// below in order to create a valid GridBoundary object after using this
+ /// default constructor.
+ CCoordinateSystemGridBoundary (void);
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Primary Constructor. Contrary to other envelope objects, this
+ /// particular overload specifically requires that the southwest argument
+ /// indeed be southwest of the northeast argument. (The assumption here is
+ /// that the X coordinate is the easting and the Y coordinate is the
+ /// northing.) This is necessary to support geographic coordinate systems
+ /// (i.e. +/- 180). To support future development plans, the boundary is
+ /// maintained as an arbitrary MgPolygon object. In the initial release,
+ /// only rectangular boundaries will be tested and officially supported.
+ /// \param southwest
+ /// Southwest corner of the boundary in which a grid is to be drawn. This
+ /// point must be southwest of the northeast location.
+ /// \param northeast
+ /// Northeast corner of the boundary in which a grid is to be drawn.
+ /// This point must be northeast of the southwest location.
+ /// \remarks
+ /// Externally, parameters are typically in frame coordinates; internally,
+ /// may be in internal coordinates (such as UTM when used internal to the
+ /// MGRS object).
CCoordinateSystemGridBoundary (MgCoordinate* southwest,MgCoordinate* northeast);
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Secondary Constructor. This particular overload simply adds a reference
+ /// to provided polygon as the boundary.
CCoordinateSystemGridBoundary (MgPolygon* boundary);
+
+ //////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Destructor, no surprises here.
~CCoordinateSystemGridBoundary (void);
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Resets the grid boundary to that specified by the two arguments.
+ /// \param southwest
+ /// Southwest corner of the boundary in which a grid is to be drawn. This
+ /// point must be southwest of the northeast location.
+ /// \param northeast
+ /// Northeast corner of the boundary in which a grid is to be drawn.
+ /// This point must be northeast of the southwest location.
void SetBoundaryExtents (MgCoordinate* southwest,MgCoordinate* northeast);
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Resets the grid boundary to that specified by the polygon argument.
+ /// \param boundary
+ /// Polygon which defines the new grid boundary.
void SetBoundaryExtents (MgPolygon* boundary);
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the current grid boundary in the form of an MgPolygon object.
+ /// \remarks
+ /// While initially, grid boundaries are simple rectangels, during grid
+ /// generation a boundary may be converted from one coordinate system
+ /// to another. In so doing, the straight lines of the initial rectangle
+ /// a often replaced with a complex curve representing the boundary in
+ /// the new coordinate system.
MgPolygon* GetBoundary (void) const;
- CCoordinateSystemGridBoundary (void);
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the extents of the grid boundary.
+ /// \param eastMin
+ /// The minimum easting (i.e. X) ordinate value is returned here.
+ /// \param eastMax
+ /// The maximum easting (i.e. X) ordinate value is returned here.
+ /// \param northMin
+ /// The minimum northing (i.e. Y) ordinate value is returned here.
+ /// \param northMax
+ /// The maximum northing (i.e. Y) ordinate value is returned here.
+ /// \remarks
+ /// Especially useful after the internal boundary is converted to a
+ /// different coordinate system.
void GetBoundaryExtents (double& eastMin,double& eastMax,double& northMin,double& northMax) const;
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the internal grid boundary, in the form of an MgPolygon object,
+ /// after the boundary hbas been converted using the provided coordinate
+ /// system transform.
+ /// \param transform
+ /// The transformation used to convert the grid boundary.
+ /// \param precision
+ /// A value which indicates, in target coordinate system units, how
+ /// precisely any complex curve approximation generated must match the
+ /// the true complex curve.
+ /// \remarks
+ /// The transformation must be a coordinate system transformation. The
+ /// existing grid boundary is assumed to be defined in terms of the
+ /// transformation's source coordinate system, and is converted to the
+ /// transformation's target coordinate system. In the conversion process,
+ /// a straight line segment is usually replaced with a multi-segment
+ /// approximation. The maximum distance (in target system units) will
+ /// not exceed the value specified by the precision parameter. Regardless
+ /// of the precision specification, the curve generation process shuts down
+ /// when the number of segments exceeds the value specified by the
+ /// m_MaxCurvePoints member variable.
MgPolygon* GetBoundary (MgCoordinateSystemTransform* transform,double precision = 1.0);
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the result of clipping the provided line string to the internal
+ /// region (exterior ring) of the grid boundary.
+ /// \param lineString
+ /// A line string in the same coordinate system as the grid boundary.
+ /// \remarks
+ /// The result is a <b>collection</b> of line strings, thus supporting the
+ /// proper clipping of a line string which enters and leaves the grid
+ /// boundary more than once. The algorithm is <b>slow</b> as it is written
+ /// to handle arbitrary polygons. The algoirthm is designed to support
+ /// concave polygons, but this has not bee tested. Interior rings in the
+ /// internal polygon object are ignored at this time.
MgLineStringCollection* ClipLineString (MgLineString* lineString) const;
protected:
+
+ ////////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Satifies the pur virtual function of the MgDispose base class from which
+ /// this object is derived. Essentially causes the destructor to be called.
void Dispose (void);
private:
- // The transform used in the folloing function is more sophisicated than the
+ // The transform used in the following function is more sophisicated than the
// standard Transform function.
MgLinearRing* TransformLinearRing (MgLinearRing* linearString,
MgCoordinateSystemTransform* transformation,
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -337,7 +337,11 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CCoordinateSystemMgrs::SetBoundary(MgCoordinateSystemGridBoundary* pGridBoundary)
{
+ // Save the boundary.
m_GridBoundary = SAFE_ADDREF (pGridBoundary);
+
+ // Create a CCoordinateSystemOneGrid which is appropriate for generating
+ // MGRS graticule requests.
m_ZoneCollection = FrameBoundaryToZones (m_GridBoundary,m_pCsTarget,m_bUseFrameDatum);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -349,25 +353,52 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MgCoordinateSystemGridLineCollection* CCoordinateSystemMgrs::GetGridLines (MgCoordinateSystemGridSpecification* specification)
{
+ bool specIsGrid;
+
INT32 index;
+ INT32 unitType;
INT32 zoneCount;
Ptr<CCoordinateSystemMgrsZone> mgrsZoneGrid;
+ Ptr<MgCoordinateSystemGridLineCollection> aGridLineCollection;
Ptr<CCoordinateSystemGridLineCollection> theGridLineCollection;
MG_TRY ()
theGridLineCollection = new CCoordinateSystemGridLineCollection ();
- zoneCount = m_ZoneCollection->GetCount ();
- for (index = 0;index < zoneCount;index += 1)
+ unitType = specification->GetUnitType();
+ specIsGrid = (unitType == MgCoordinateSystemUnitType::Linear);
+ if (specIsGrid)
{
- mgrsZoneGrid = m_ZoneCollection->GetItem (index);
- Ptr<MgCoordinateSystemGridLineCollection> aGridLineCollection;
- aGridLineCollection = mgrsZoneGrid->GetGridLines (specification);
- theGridLineCollection->AddCollection (aGridLineCollection);
+ // The specification calls for a grid.
+ zoneCount = m_ZoneCollection->GetCount ();
+ for (index = 0;index < zoneCount;index += 1)
+ {
+ mgrsZoneGrid = m_ZoneCollection->GetItem (index);
+ aGridLineCollection = mgrsZoneGrid->GetGridLines (specification);
+ theGridLineCollection->AddCollection (aGridLineCollection);
+ }
}
+ else
+ {
+ // The specification calls for a graticule.
+ if (m_GraticuleUtm)
+ {
+ aGridLineCollection = m_GraticuleUtm->GetGridLines (specification);
+ theGridLineCollection->AddCollection (aGridLineCollection);
+ }
+ if (m_GraticuleUpsNorth)
+ {
+ aGridLineCollection = m_GraticuleUpsNorth->GetGridLines (specification);
+ theGridLineCollection->AddCollection (aGridLineCollection);
+ }
+ if (m_GraticuleUpsSouth)
+ {
+ aGridLineCollection = m_GraticuleUpsSouth->GetGridLines (specification);
+ theGridLineCollection->AddCollection (aGridLineCollection);
+ }
+ }
MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::GetGridLines")
return static_cast<MgCoordinateSystemGridLineCollection*>(theGridLineCollection.Detach());
}
-
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MgCoordinateSystemGridRegionCollection* CCoordinateSystemMgrs::GetGridRegions (MgCoordinateSystemGridSpecification* specification)
{
@@ -392,23 +423,50 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MgCoordinateSystemGridTickCollection* CCoordinateSystemMgrs::GetGridTicks (MgCoordinateSystemGridSpecification* specification)
{
+ bool specIsGrid;
+
INT32 index;
+ INT32 unitType;
INT32 zoneCount;
Ptr<CCoordinateSystemMgrsZone> mgrsZoneGrid;
+ Ptr<MgCoordinateSystemGridTickCollection> aGridTickCollection;
Ptr<CCoordinateSystemGridTickCollection> theGridTickCollection;
MG_TRY ()
theGridTickCollection = new CCoordinateSystemGridTickCollection ();
- zoneCount = m_ZoneCollection->GetCount ();
- for (index = 0;index < zoneCount;index += 1)
+ unitType = specification->GetUnitType();
+ specIsGrid = (unitType == MgCoordinateSystemUnitType::Linear);
+ if (specIsGrid)
{
- mgrsZoneGrid = m_ZoneCollection->GetItem (index);
- Ptr<MgCoordinateSystemGridTickCollection> aGridTickCollection;
- aGridTickCollection = mgrsZoneGrid->GetBoundaryTicks (specification);
- theGridTickCollection->AddCollection (aGridTickCollection);
- // TODO: Need to remove from the collection any grid ticks which are
- // internal to the m_GridBoundary object of this object.
+ zoneCount = m_ZoneCollection->GetCount ();
+ for (index = 0;index < zoneCount;index += 1)
+ {
+ mgrsZoneGrid = m_ZoneCollection->GetItem (index);
+ aGridTickCollection = mgrsZoneGrid->GetBoundaryTicks (specification);
+ theGridTickCollection->AddCollection (aGridTickCollection);
+ }
}
+ else
+ {
+ if (m_GraticuleUtm)
+ {
+ aGridTickCollection = m_GraticuleUtm->GetBoundaryTicks (specification);
+ theGridTickCollection->AddCollection (aGridTickCollection);
+ }
+ else if (m_GraticuleUtm)
+ {
+ aGridTickCollection = m_GraticuleUpsNorth->GetBoundaryTicks (specification);
+ theGridTickCollection->AddCollection (aGridTickCollection);
+ }
+ else if (m_GraticuleUtm)
+ {
+ aGridTickCollection = m_GraticuleUpsSouth->GetBoundaryTicks (specification);
+ theGridTickCollection->AddCollection (aGridTickCollection);
+ }
+ }
+ // TODO: Need to remove from the collection any grid ticks which are
+ // internal to the m_GridBoundary object of this object. This will be
+ // tricky, as the tick positions will usually be right on the boundary.
MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::GetGridRTicks")
return static_cast<MgCoordinateSystemGridTickCollection*>(theGridTickCollection.Detach());
}
@@ -606,9 +664,10 @@
{
m_bExceptionsOn = bOn;
}
-// Returns a collection of CCoordinateSYstemMgrsZone objects.
-// These objects derive from OneGrid, so they have both coordinate systems in them.
-//
+///////////////////////////////////////////////////////////////////////////////
+// This member returns a collection of CCoordinateSystemMgrsZone objects.
+// These objects derive from CCoordinateSystemOneGrid, so they have both
+// the grid and frame coordinate systems in them.
CCoordinateSystemMgrsZoneCollection* CCoordinateSystemMgrs::FrameBoundaryToZones (MgCoordinateSystemGridBoundary* frameBoundary,
MgCoordinateSystem* frameCRS,
bool useFrameDatum)
@@ -619,18 +678,18 @@
double cm; // central meridian;
double eastLimit, westLimit; // limits of a UTM zone
- double eastMin, eastMax; // frame boundary extrema
- double northMin, northMax; // frame boundary extrema
+ double eastMin, eastMax; // frame boundary extrema in 'LL84' (or 'LL')
+ double northMin, northMax; // frame boundary extrema in 'LL84' (or 'LL')
Ptr<MgPolygon> pPolygon;
Ptr<MgCoordinate> pSouthwest;
Ptr<MgCoordinate> pNortheast;
- Ptr<MgCoordinateSystem> llCS;
+ Ptr<MgCoordinateSystem> llCRS;
Ptr<MgCoordinateSystem> utmCRS;
- Ptr<MgCoordinateSystemTransform> llTransform;
- Ptr<MgCoordinateSystemTransform> utmTransform;
- Ptr<MgCoordinateSystemGridBoundary> utmBoundary;
+ Ptr<MgCoordinateSystemTransform> toLlTransform; // frame to 'LL' transform
+ Ptr<MgCoordinateSystemTransform> toFrameTransform; // 'LL' to frame transform
Ptr<MgCoordinateSystemGridBoundary> llBoundary;
+ Ptr<MgCoordinateSystemGridBoundary> reducedFrameBoundary;
Ptr<CCoordinateSystemMgrsZone> mgrsZoneGrid;
Ptr<CCoordinateSystemMgrsZoneCollection> zoneCollection;
STRING utmCsCode;
@@ -643,9 +702,10 @@
// Convert the polygon portion of the Grid Boundary object to long/lat
// coordinates and extract the min/max from the resulting polygon.
- llCS = csFactory->CreateFromCode (L"LL");
- llTransform = csFactory->GetTransform(frameCRS,llCS);
- pPolygon = frameBoundary->GetBoundary (llTransform,1.0E-05);
+ llCRS = csFactory->CreateFromCode (useFrameDatum ? L"LL" : L"LL84");
+ toLlTransform = csFactory->GetTransform(frameCRS,llCRS);
+ toFrameTransform = csFactory->GetTransform(llCRS,frameCRS);
+ pPolygon = frameBoundary->GetBoundary (toLlTransform,1.0E-05);
llBoundary = csFactory->GridBoundary (pPolygon);
llBoundary->GetBoundaryExtents (eastMin,eastMax,northMin,northMax);
@@ -654,109 +714,122 @@
{
// There is a portion of the frame boundary in the south polar region.
zoneNbr = -61;
- utmCsCode = ZoneNbrToUtmCs (zoneNbr);
- utmCRS = csFactory->CreateFromCode (utmCsCode);
- utmTransform = csFactory->GetTransform (llCS,utmCRS);
pSouthwest->SetX (eastMin);
pSouthwest->SetY (northMin);
pNortheast->SetX (eastMax);
pNortheast->SetY (-80.0);
llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
- pPolygon = llBoundary->GetBoundary (utmTransform,1.0);
- utmBoundary = csFactory->GridBoundary (pPolygon);
- mgrsZoneGrid = new CCoordinateSystemMgrsZone (utmBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
+ pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+ reducedFrameBoundary = csFactory->GridBoundary (pPolygon);
+ mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
zoneCollection->Add (mgrsZoneGrid);
+
+ // Construct the m_GraticuleUpsSouth member, it may be needed.
+ m_GraticuleUpsSouth = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
}
if (northMax > 84.0)
{
- // There is a portion of the frame boundary in the south polar region.
+ // There is a portion of the frame boundary in the north polar region.
zoneNbr = 61;
- utmCsCode = ZoneNbrToUtmCs (zoneNbr);
- utmCRS = csFactory->CreateFromCode (utmCsCode);
- utmTransform = csFactory->GetTransform (llCS,utmCRS);
pSouthwest->SetX (eastMin);
pSouthwest->SetY (84.0);
pNortheast->SetX (eastMax);
pNortheast->SetY (northMax);
llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
- pPolygon = llBoundary->GetBoundary (utmTransform,1.0);
- utmBoundary = csFactory->GridBoundary (pPolygon);
- mgrsZoneGrid = new CCoordinateSystemMgrsZone (utmBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
+ pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+ reducedFrameBoundary = csFactory->GridBoundary (pPolygon);
+ mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
zoneCollection->Add (mgrsZoneGrid);
+
+ // Construct the m_GraticuleUpsNorth member, it may be needed.
+ m_GraticuleUpsNorth = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
}
if (northMax > -80.0 && northMin < 84.0)
{
- // There is a portion of the frame boundary in the non-polar region
- // covered by normal UTM zones. These can be either northern zones,
- // or southern zones; perhaps both. We'll do the northern zones
- // first.
+ // A portion of the frame boundary is in the region covered by the
+ // normal (i.e. non-polar) UTM zones. Determine the particular UTM
+ // zones we need to generate.
+ zoneMin = ((static_cast<INT32>(eastMin) + 180) / 6) + 1;
+ zoneMax = ((static_cast<INT32>(eastMax) + 180) / 6) + 1;
+
if (northMax > 0.0)
{
- // There are some northern zones. The northMin and northMax
- // are the same for all of these. What changes is the central
- // meridian which means the eastern and western limits change.
- zoneMin = ((static_cast<INT32>(eastMin) + 180) / 6) + 1;
- zoneMax = ((static_cast<INT32>(eastMax) + 180) / 6) + 1;
+ // There are some northern zones.
- pSouthwest->SetY ((northMin <= 0.0) ? 0.0 : northMin);
- pNortheast->SetY ((northMax >= 84.0) ? 84.0 : northMax);
+ // We will need to generate, for each UTM zone, the extents
+ // of that particular UTM zone trimmed to the extents of the
+ // provided frame boundary. The north/south portions
+ // are the same for each zone, so we do that once here outside
+ // the loop.
+ pSouthwest->SetY ((northMin < 0.0) ? 0.0 : northMin);
+ pNortheast->SetY ((northMax > 84.0) ? 84.0 : northMax);
+
+ // OK, generate a CCoordinateSystemMgrsZone object for each
+ // UTM zone which intersects the frame boundary provided.
+ // Usually only one, but we must be able to handle the
+ // multiple zone case.
for (zoneNbr = zoneMin;zoneNbr <= zoneMax;zoneNbr += 1)
{
- // Here once for each normal UTM zone in the northern
- // hemisphere which intersects the provided frame grid
- // boundary.
- utmCsCode = ZoneNbrToUtmCs (zoneNbr);
- utmCRS = csFactory->CreateFromCode (utmCsCode);
- utmTransform = csFactory->GetTransform (llCS,utmCRS);
+ // 1> Compute the 'LL' boundary of this UTM zone.
+ // North/South done above, here we need only deal
+ // with east/west.
cm = static_cast<double>((zoneNbr * 6) - 183);
westLimit = cm - 3.0;
+ eastLimit = cm + 3.0;
+
+ // 2> Apply the extents of the provided frame boundary.
if (westLimit < eastMin) westLimit = eastMin;
- eastLimit = cm + 3.0;
if (eastLimit > eastMax) eastLimit = eastMax;
+
+ // 3> Create, in terms of LL coordinates, the frame
+ // boundary as is appropriate for this particular zone.
pSouthwest->SetX (westLimit);
pNortheast->SetX (eastLimit);
+
+ // 4> Convert this reduced frame boundary back to frame
+ // coordinates.
+ // TODO: We should not use a hard coded curve precision value here.
llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
- pPolygon = llBoundary->GetBoundary (utmTransform,1.0);
- utmBoundary = csFactory->GridBoundary (pPolygon);
- mgrsZoneGrid = new CCoordinateSystemMgrsZone (utmBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
+ pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+ reducedFrameBoundary = csFactory->GridBoundary (pPolygon);
+ mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
zoneCollection->Add (mgrsZoneGrid);
- }
+ }
}
if (northMin < 0.0)
{
- // There are some southern zones. The northMin and northMax
- // are the same for all of these. What changes is the central
- // meridian which means the eastern and western limits change.
- // There are some northern zones. The northMin and northMax
- // are the same for all of these. What changes is the central
- // meridian which means the eastern and western limits change.
- zoneMin = ((static_cast<INT32>(eastMin) + 180) / 6) + 1;
- zoneMax = ((static_cast<INT32>(eastMax) + 180) / 6) + 1;
-
+ // Pretty much the same as the northern zones processed
+ // above, but without the laborious comments.
pSouthwest->SetY ((northMin < -80.0) ? -80.0 : northMin);
pNortheast->SetY ((northMax > 0.0) ? 0.0 : northMax);
for (zoneNbr = zoneMin;zoneNbr <= zoneMax;zoneNbr += 1)
{
- // Here once for each normal UTM zone in the southern
- // hemisphere which intersects the provided frame grid
- // boundary.
- utmCsCode = ZoneNbrToUtmCs (-zoneNbr);
- utmCRS = csFactory->CreateFromCode (utmCsCode);
- utmTransform = csFactory->GetTransform (llCS,utmCRS);
cm = static_cast<double>((zoneNbr * 6) - 183);
westLimit = cm - 3.0;
+ eastLimit = cm + 3.0;
if (westLimit < eastMin) westLimit = eastMin;
- eastLimit = cm + 3.0;
if (eastLimit > eastMax) eastLimit = eastMax;
pSouthwest->SetX (westLimit);
pNortheast->SetX (eastLimit);
+
llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
- pPolygon = llBoundary->GetBoundary (utmTransform,1.0);
- utmBoundary = csFactory->GridBoundary (pPolygon);
- mgrsZoneGrid = new CCoordinateSystemMgrsZone (utmBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
+ pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+ reducedFrameBoundary = csFactory->GridBoundary (pPolygon);
+ mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
zoneCollection->Add (mgrsZoneGrid);
}
}
+
+ // Need a CCoordinateSystemOneGrid object which can produce the 6 x 8 graticule
+ // for the entire regon.
+ pSouthwest->SetX (eastMin);
+ pNortheast->SetX (eastMax);
+ pSouthwest->SetY ((northMin < -80.0) ? -80.0 : northMin);
+ pNortheast->SetY ((northMax > 84.0) ? 84.0 : northMax);
+ llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
+ pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+ reducedFrameBoundary = csFactory->GridBoundary (pPolygon);
+ m_GraticuleUpsNorth = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
}
MG_CATCH_AND_THROW(L"MgCoordinateSystemOneGrid::GetGridLines")
return zoneCollection.Detach ();
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -122,6 +122,16 @@
Ptr<MgCoordinateSystemGridBoundary> m_GridBoundary;
Ptr<CCoordinateSystemMgrsZoneCollection> m_ZoneCollection;
+ // The following CCoordinateSystemOneGrid objects are used to generate
+ // graticules, and thus have a grid CRS which is geographic as opposed
+ // to projective. Thus, these are somewhat special objects. These
+ // pointers may be null if they are not needed which is usually the
+ // case for the polar regions. The "need" is based on the frame
+ // boundary.
+ Ptr<CCoordinateSystemOneGrid> m_GraticuleUtm;
+ Ptr<CCoordinateSystemOneGrid> m_GraticuleUpsNorth;
+ Ptr<CCoordinateSystemOneGrid> m_GraticuleUpsSouth;
+
private:
CCoordinateSystemMgrs();
CCoordinateSystemMgrs(const CCoordinateSystemMgrs&);
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -45,17 +45,24 @@
STRING utmZoneCode = CCoordinateSystemMgrs::ZoneNbrToUtmCs (m_UtmZone);
utmZoneCRS = csFactory.CreateFromCode (utmZoneCode);
SetUp (frameBoundary,utmZoneCRS,frameCRS);
+
+ SetUserID (m_UtmZone);
}
CCoordinateSystemMgrsZone::~CCoordinateSystemMgrsZone (void)
{
}
-
CCoordinateSystemGridRegionCollection* CCoordinateSystemMgrsZone::GetGridRegions (MgCoordinateSystemGridSpecification* specification)
{
BuildRegionCollection (specification);
return SAFE_ADDREF(m_RegionCollection.p);
}
-
+INT32 CCoordinateSystemMgrsZone::GetUtmZoneNbr (void)
+{
+ // m_UtmZoneNbr is positive for northern hemisphere, negative for the
+ // southern hemisphere. Polar regions are assigned the value of 61. Zero
+ // is the uninitialized/unknown/error value.
+ return m_UtmZone;
+}
void CCoordinateSystemMgrsZone::BuildRegionCollection (MgCoordinateSystemGridSpecification* specification)
{
double curvePrecision;
@@ -114,7 +121,7 @@
lngMax = centralMeridian + 3.0;
// Need to account for the fact that the frame boundary may cross
- // a MGRS Gris Zone Designation boundary (i.e. the 8 degree chunks
+ // an MGRS Grid Zone Designation boundary (i.e. the 8 degree chunks
// of latitude). Thus, there may be more than just one major region.
delta = fabs (fmod (latMin,8.0));
firstLat = static_cast<INT32>(latMin - ((latMin >= 0.0) ? delta : (8.0 - delta)));
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -40,10 +40,12 @@
// * If useFrameDatum is true, the Grid coordinate system will be adjusted
// to use the datum of the provided frame coordinate system. Otherwise,
// the Grid datum is hardcoded to WGS84.
+// * Is used only to generate projected grids. Graticules are handled
+// separately. Thus, the grid coordinate system is always a projected
+// coordinate system.
class CCoordinateSystemMgrsZone : public CCoordinateSystemOneGrid
{
public:
- //
CCoordinateSystemMgrsZone (MgCoordinateSystemGridBoundary* frameBoundary,
INT32 utmZoneNbr,
bool useFrameDatum,
@@ -52,12 +54,18 @@
~CCoordinateSystemMgrsZone (void);
CCoordinateSystemGridRegionCollection* GetGridRegions (MgCoordinateSystemGridSpecification* specification);
+ INT32 GetUtmZoneNbr (void);
+
protected:
void BuildRegionCollection (MgCoordinateSystemGridSpecification* specification);
private:
void BuildMajorRegions (double boundaryPrecision);
void BuildMinorRegions (double boundaryPrecision);
+ ///////////////////////////////////////////////////////////////////////////
// Data members
+ // m_UtmZoneNbr is positive for northern hemisphere, negative for the
+ // southern hemisphere. Polar regions are assigned the value of 61.
+ // Zero is the uninitialized/unknown/error value.
INT32 m_UtmZone;
INT8 m_LetteringScheme;
Ptr<CCoordinateSystemGridRegionCollection> m_RegionCollection;
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -33,7 +33,7 @@
CCoordinateSystemOneGrid::CCoordinateSystemOneGrid () : MgGuardDisposable (),
m_UserID (0),
m_MaxCurvePoints (MaxCurvePoints),
- m_RegionLabel (),
+ m_Label (),
m_GridCRS (),
m_FrameCRS (),
m_ToFrameXform (),
@@ -51,7 +51,7 @@
MgGuardDisposable (),
m_UserID (0),
m_MaxCurvePoints (MaxCurvePoints),
- m_RegionLabel (),
+ m_Label (),
m_GridCRS (),
m_FrameCRS (),
m_ToFrameXform (),
@@ -80,14 +80,31 @@
m_FrameCRS = SAFE_ADDREF (frameCRS);
m_ToFrameXform = csFactory.GetTransform (m_GridCRS,m_FrameCRS);
m_ToGridXform = csFactory.GetTransform (m_FrameCRS,m_GridCRS);
-}
+}
+bool CCoordinateSystemOneGrid::IsGeographic (void)
+{
+ bool isGeographic;
+ INT32 projectionCode;
+
+ projectionCode = m_GridCRS->GetProjectionCode ();
+ isGeographic = (projectionCode == MgCoordinateSystemProjectionCode::LL);
+ return isGeographic;
+}
+INT32 CCoordinateSystemOneGrid::GetUserID (void)
+{
+ return m_UserID;
+}
STRING CCoordinateSystemOneGrid::GetLabel (void)
{
- return m_RegionLabel;
+ return m_Label;
}
+void CCoordinateSystemOneGrid::SetUserID (INT32 userID)
+{
+ m_UserID = userID;
+}
void CCoordinateSystemOneGrid::SetLabel (CREFSTRING label)
{
- m_RegionLabel = label;
+ m_Label = label;
}
MgCoordinate* CCoordinateSystemOneGrid::ConvertToGrid (MgCoordinate* frameCoordinate)
{
@@ -99,6 +116,7 @@
}
MgCoordinateSystemGridLineCollection* CCoordinateSystemOneGrid::GetGridLines (MgCoordinateSystemGridSpecification* specs)
{
+ INT32 lineStringCount;
double value;
double delta;
double increment;
@@ -116,6 +134,7 @@
Ptr<CCoordinateSystemGridLineCollection> gridLineCollection = new CCoordinateSystemGridLineCollection ();
MG_TRY()
+ CCoordinateSystemGridSpecification* mySpecPtr = dynamic_cast<CCoordinateSystemGridSpecification*>(specs);
coordinate = new MgCoordinateXY ();
fromPnt = new MgCoordinateXY ();
toPnt = new MgCoordinateXY ();
@@ -124,7 +143,7 @@
// value has been changed, reproduce the m_GridBoundary
// member from the m_FrameBoundary member. At this point, we
// need the curve precision value in Grid system units.
- precision = specs->GetCurvePrecision ();
+ precision = mySpecPtr->GetCurvePrecision ();
GenerateGridBoundary (precision);
// Get the extents of the frame boundary, and then convert them to
@@ -135,36 +154,42 @@
// Adjust so the the grid limits are exact values with regard to the
// specified increments. Do this in an expansive way so the the grid
// limits always get larger, never smaller.
- increment = specs->GetEastingIncrement();
+ //
+ // Note that we need to have the increments and base values in terms
+ // of the grid coordinate system, regardless of the units used to
+ // specify them.
+ increment = mySpecPtr->GetEastingIncrement(m_GridCRS);
delta = fabs(fmod (eastMin,increment));
eastMin -= (eastMin >= 0.0) ? delta : (increment - delta);
delta = fabs(fmod (eastMax,increment));
eastMax += (eastMax >= 0.0) ? (increment - delta) : delta;
- increment = specs->GetNorthingIncrement();
+ increment = mySpecPtr->GetNorthingIncrement(m_GridCRS);
delta = fabs(fmod (northMin,increment));
northMin -= (northMin >= 0.0) ? delta : (increment - delta);
delta = fabs(fmod (northMax,increment));
northMax += (northMax >= 0.0) ? (increment - delta) : delta;
// Adjust for the base. Again, we always enlarge, never shrink.
- if (specs->GetEastingBase () > 0.0)
+ if (mySpecPtr->GetEastingBase () > 0.0)
{
- increment = specs->GetEastingIncrement ();
- delta = fmod (specs->GetEastingBase(),increment);
+ increment = mySpecPtr->GetEastingIncrement (m_GridCRS);
+ delta = fmod (mySpecPtr->GetEastingBase(m_GridCRS),increment);
eastMin += delta - increment;
eastMax += delta + increment;
}
- if (specs->GetNorthingBase () > 0.0)
+ if (mySpecPtr->GetNorthingBase () > 0.0)
{
- increment = specs->GetNorthingIncrement ();
- delta = fmod (specs->GetNorthingBase(),increment);
+ increment = mySpecPtr->GetNorthingIncrement (m_GridCRS);
+ delta = fmod (mySpecPtr->GetNorthingBase(m_GridCRS),increment);
northMin += delta - increment;
northMax += delta + increment;
}
// Given the specification, we double loop, generating lines.
- increment = specs->GetNorthingIncrement ();
+ // Forst loop, generatinf west/east lines starting at the southern edge
+ // proceeding to the north.
+ increment = mySpecPtr->GetNorthingIncrement (m_GridCRS);
for (value = northMin;value <= northMax;value += increment)
{
fromPnt->SetX (eastMin);
@@ -177,16 +202,20 @@
// actually leave, and then reenter, the grid boundary, so the
// result can be a multi-line sting.
lineStringCollection = m_FrameBoundary->ClipLineString (lineString);
-
- // Construct the Grid Line object and add it to the grid
- // line collection object.
- gridLine = new CCoordinateSystemGridLine (MgCoordinateSystemGridOrientation::NorthSouth,value);
- gridLine->SetSegmentCollection (lineStringCollection);
- gridLineCollection->Add (gridLine);
+ lineStringCount = lineStringCollection->GetCount ();
+ if (lineStringCount > 0)
+ {
+ // Construct the Grid Line object and add it to the grid
+ // line collection object.
+ gridLine = new CCoordinateSystemGridLine (MgCoordinateSystemGridOrientation::NorthSouth,value);
+ gridLine->SetSegmentCollection (lineStringCollection);
+ gridLineCollection->Add (gridLine);
+ }
}
- // Given the specification, we double loop, generating lines.
- increment = specs->GetEastingIncrement ();
+ // Second loop, the south/north lines, starting at the western edge
+ // proceeding to the east.
+ increment = mySpecPtr->GetEastingIncrement (m_GridCRS);
for (value = eastMin;value <= eastMax;value += increment)
{
fromPnt->SetX (value);
@@ -197,14 +226,17 @@
// Clip the line to the frame boundary. The grid line may
// actually leave, and then re-enter, the grid boundary, so the
- // result can be a multi-line sting.
+ // result can be a multi-line string.
lineStringCollection = m_FrameBoundary->ClipLineString (lineString);
-
- // Construct the Grid Line object and add it to the grid
- // line collection object.
- gridLine = new CCoordinateSystemGridLine (MgCoordinateSystemGridOrientation::EastWest,value);
- gridLine->SetSegmentCollection (lineStringCollection);
- gridLineCollection->Add (gridLine);
+ lineStringCount = lineStringCollection->GetCount ();
+ if (lineStringCount > 0)
+ {
+ // Construct the Grid Line object and add it to the grid
+ // line collection object.
+ gridLine = new CCoordinateSystemGridLine (MgCoordinateSystemGridOrientation::EastWest,value);
+ gridLine->SetSegmentCollection (lineStringCollection);
+ gridLineCollection->Add (gridLine);
+ }
}
MG_CATCH_AND_THROW(L"MgCoordinateSystemOneGrid::GetGridLines")
@@ -235,38 +267,39 @@
MG_TRY ()
+ CCoordinateSystemGridSpecification* mySpecPtr = dynamic_cast<CCoordinateSystemGridSpecification*>(specs);
tickCollection = new CCoordinateSystemGridTickCollection ();
// Get the grid extents.
- curvePrecision = specs->GetCurvePrecision();
+ curvePrecision = mySpecPtr->GetCurvePrecision();
GetGridExtents (eastMin,eastMax,northMin,northMax,curvePrecision);
// Expand the extents to become the lowest and highest tick values
// for each of the ordinates.
- increment = specs->GetTickEastingIncrement();
+ increment = mySpecPtr->GetTickEastingIncrement(m_GridCRS);
delta = fabs(fmod (eastMin,increment));
eastMin -= (eastMin >= 0.0) ? delta : (increment - delta);
delta = fabs(fmod (eastMax,increment));
eastMax += (eastMax >= 0.0) ? (increment - delta) : delta;
- increment = specs->GetTickNorthingIncrement();
+ increment = mySpecPtr->GetTickNorthingIncrement(m_GridCRS);
delta = fabs(fmod (northMin,increment));
northMin -= (northMin >= 0.0) ? delta : (increment - delta);
delta = fabs(fmod (northMax,increment));
northMax += (northMax >= 0.0) ? (increment - delta) : delta;
// Adjust for the base. Again, we always enlarge, never shrink.
- if (specs->GetEastingBase () > 0.0)
+ if (mySpecPtr->GetEastingBase () > 0.0)
{
- increment = specs->GetEastingIncrement ();
- delta = fmod (specs->GetEastingBase(),increment);
+ increment = mySpecPtr->GetEastingIncrement (m_GridCRS);
+ delta = fmod (mySpecPtr->GetEastingBase(m_GridCRS),increment);
eastMin += delta - increment;
eastMax += delta + increment;
}
- if (specs->GetNorthingBase () > 0.0)
+ if (mySpecPtr->GetNorthingBase () > 0.0)
{
- increment = specs->GetNorthingIncrement ();
- delta = fmod (specs->GetNorthingBase(),increment);
+ increment = mySpecPtr->GetNorthingIncrement (m_GridCRS);
+ delta = fmod (mySpecPtr->GetNorthingBase(m_GridCRS),increment);
northMin += delta - increment;
northMax += delta + increment;
}
@@ -287,7 +320,7 @@
// Do the easting ticks; that is tickmarks whose value is an
// easting ordinate value.
- increment = specs->GetTickEastingIncrement ();
+ increment = mySpecPtr->GetTickEastingIncrement (m_GridCRS);
orientation = MgCoordinateSystemGridOrientation::EastWest;
for (ordinateValue = eastMin;ordinateValue <= eastMax;ordinateValue += increment)
{
@@ -313,9 +346,9 @@
}
}
- // Do the easting ticks; that is tickmarks whose value is an
- // easting ordinate value.
- increment = specs->GetTickNorthingIncrement ();
+ // Do the northing ticks; that is tickmarks whose value is an
+ // northing ordinate value.
+ increment = mySpecPtr->GetTickNorthingIncrement (m_GridCRS);
orientation = MgCoordinateSystemGridOrientation::NorthSouth;
for (ordinateValue = northMin;ordinateValue <= northMax;ordinateValue += increment)
{
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -43,23 +43,28 @@
public:
static const INT32 MaxCurvePoints;
CCoordinateSystemOneGrid (void);
- CCoordinateSystemOneGrid (MgCoordinateSystemGridBoundary* frameBoundary,
- MgCoordinateSystem* gridCRS,
- MgCoordinateSystem* frameCRS);
- ~CCoordinateSystemOneGrid (void);
+ CCoordinateSystemOneGrid (MgCoordinateSystemGridBoundary* frameBoundary,
+ MgCoordinateSystem* gridCRS,
+ MgCoordinateSystem* frameCRS);
+ ~CCoordinateSystemOneGrid (void);
void SetUp (MgCoordinateSystemGridBoundary* frameBoundary,
MgCoordinateSystem* gridCRS,
MgCoordinateSystem* frameCRS);
+ // Returns true if the grid coordinate system is geographic; use this to
+ // determine if this is a graticule (as opposed to a grid).
+ bool IsGeographic (void);
+ INT32 GetUserID (void);
STRING GetLabel (void);
+ void SetUserID (INT32 userID);
+ void SetLabel (CREFSTRING label);
+
MgCoordinate* ConvertToGrid (MgCoordinate* frameCoordinate);
MgCoordinate* ConvertToFrame (MgCoordinate* gridCoordinate);
MgCoordinateSystemGridLineCollection* GetGridLines (MgCoordinateSystemGridSpecification* specs);
CCoordinateSystemGridTickCollection* GetBoundaryTicks (MgCoordinateSystemGridSpecification* specs);
- void SetLabel (CREFSTRING label);
-
protected:
MgCoordinateSystem* GetFrameCRS (void);
MgCoordinateSystem* GetGridCRS (void);
@@ -68,9 +73,9 @@
void GetGridExtents (double& eastMin,double& eastMax,double& northMin,double& northMax,double precision = 0.25);
void Dispose (void);
- INT32 m_UserID; // For user convenience (i.e. UTM zone)
+ INT32 m_UserID; // For user convenience (i.e. UTM zone)
INT32 m_MaxCurvePoints;
- STRING m_RegionLabel; // For user conveinence (i.e. MGRS)
+ STRING m_Label; // For user conveinence (i.e. MGRS)
Ptr<MgCoordinateSystem> m_GridCRS; // The grid coordinate system
Ptr<MgCoordinateSystem> m_FrameCRS; // The frame coordinate system
Ptr<MgCoordinateSystemTransform> m_ToFrameXform; // Converts grid coordinates to frame coordinates
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -1266,8 +1266,8 @@
deltaY = gridTo->GetY () - gridFrom->GetY ();
// We do not try to place northing ticks on a line which more horizontal than it
// is vertical; and vice versa.
- if (deltaX > deltaY && orientation == MgCoordinateSystemGridOrientation::EastWest ||
- deltaY > deltaX && orientation == MgCoordinateSystemGridOrientation::NorthSouth)
+ if ((deltaX > deltaY) && (orientation == MgCoordinateSystemGridOrientation::EastWest) ||
+ (deltaY > deltaX) && (orientation == MgCoordinateSystemGridOrientation::NorthSouth))
{
// Use some simple geomtery to calculate the approximate position of the
// the point on the provided line segment at which the indicated ordinate
Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -52,7 +52,6 @@
virtual INT32 GetLastTransformStatus();
virtual void ResetLastTransformStatus();
-
INTERNAL_API:
///////////////////////////////////////////////////////////////////////////
/// \brief
Modified: trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -571,9 +571,9 @@
return gridSpecification;
}
MgCoordinateSystemGridSpecification* MgCoordinateSystemFactory::GridSpecification (double increment,
- INT32 subdivisions,
- INT32 unitCode,
- double curvePrecision)
+ double tickIncrement,
+ INT32 unitCode,
+ double curvePrecision)
{
Ptr<MgCoordinateSystemGridSpecification> gridSpecification;
@@ -585,7 +585,7 @@
// all the parameters added and throw an exception if an error.
gridSpecification->SetGridBase (0.0,0.0);
gridSpecification->SetGridIncrement (increment,increment);
- gridSpecification->SetGridIncrement (subdivisions,subdivisions);
+ gridSpecification->SetGridIncrement (tickIncrement,tickIncrement);
gridSpecification->SetUnits (unitCode,MgCoordinateSystemUnitType::Linear);
gridSpecification->SetCurvePrecision (curvePrecision);
}
Modified: trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.h
===================================================================
--- trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -151,42 +151,390 @@
virtual bool IsValid(CREFSTRING wkt);
// Grids and Graticules -- General
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Constructs a grid boundary object. Externally, grid objects are in
+ /// viewport coordinates and define the extents of the region within
+ /// which a grid is to be drawn. Such objects are often simple
+ /// rectangles, but his is not a requirement.
+ /// </summary>
+ /// <param name="southwest">
+ /// The coordinates of the the southwest corner of a rectangular region
+ /// which represents the grid region. This point <b>MUST</b> indeed be
+ /// sothwest of the coordinate provided by the <c>northeast</c> parameter.
+ /// </param>
+ /// <param name="northeast">
+ /// The coordinates of the the northeast corner of a rectangular region
+ /// which represents the grid region. This point <b>MUST</b> indeed be
+ /// northeast of the coordinate provided by the <c>southwest</c> parameter.
+ /// </param>
+ /// <returns>
+ /// Returns the grid boundary in the ofrm used by the grid/graticule
+ /// sub-system.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown in the event of heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// Internally, the grid boundary is maintained as an MgPolygon object
+ /// with no interior rings. Otfen this is in the form of a rectangle,
+ /// but his should not be relied on.
+ /// </remarks>
virtual MgCoordinateSystemGridBoundary* GridBoundary(MgCoordinate* southwest,
MgCoordinate* northeast);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Constructs a grid boundary object. Externally, grid objects are in
+ /// viewport coordinates and define the extents of the region within
+ /// which a grid is to be drawn. Such objects are often simple
+ /// rectangles, but his is not a requirement.
+ /// </summary>
+ /// <param name="boundary">
+ /// The grid boundary in the form of a MgPolygon with no interior rings.
+ /// </param>
+ /// <returns>
+ /// Returns the boundary in the form used by the grid/graticule sub-system.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown in the event of heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// </remarks>
virtual MgCoordinateSystemGridBoundary* GridBoundary(MgPolygon* boundary);
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Constructs a grid specification object with all specifications set to
+ /// <b>invalid</b> values.
+ /// </summary>
+ /// <returns>
+ /// An object which carries all of the several parameter which determine
+ /// nature of a grid or graticule and any sub-feature tereof.
+ /// </returns>
+ /// <exception cref="std::bad_alloc">
+ /// Thrown in the event of a heap memory allocation failure.
+ /// </exception>
virtual MgCoordinateSystemGridSpecification* GridSpecification (void);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Constructs a grid specification object with all specifications set to
+ /// the values indicated by the supplied parameters.
+ /// </summary>
+ /// <param name="increment">
+ /// The distance between grid lines of a grid or graticule. This value is
+ /// used for both the easting and northing grid lines; and the value must
+ /// be in the units specified by the <c>unitCode</c> parameter.
+ /// </param>
+ /// <param name="tickIncrement">
+ /// The distance between tick marks of a grid or graticule. This value is
+ /// used for both the easting and northing tick marks; and the value must
+ /// be in the units specified by the <c>unitCode</c> parameter.
+ /// </param>
+ /// <param name="unitCode">
+ /// One of the values defined by the MgCoordinateSystemUnitCode object
+ /// which indicates the units in which the <c>increment</c>,
+ /// <c>tickIncrement</c>, and <c>curvePrecision</c> parameters are
+ /// specified.
+ /// </param>
+ /// <param name="curvePrecision">
+ /// In the units indicated by the <c>unitCode</c> parameter, the
+ /// <b>desired</b> maximum distance between the true complex curve and
+ /// the multi-segment approximation of the complex curve of any grid or
+ /// graticule line generated using this specification.
+ /// </param>
+ /// <returns>
+ /// A fully initialized grid specification object.
+ /// </returns>
+ /// <exception cref="std::bad_alloc">
+ /// Thrown in the event of a heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// This particular overload is designed for the most common situations.
+ /// It presumes the units used are of thelinear type, and thus this
+ /// particular overload cannot be used to generate a specification
+ /// object for use in graticule generation.
+ /// </remarks>
virtual MgCoordinateSystemGridSpecification* GridSpecification (double increment,
- INT32 subdivisions,
+ double tickIncrement,
INT32 unitCode,
double curvePrecision);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Constructs a grid specification object with all specifications set to
+ /// the values indicated by the supplied parameters.
+ /// </summary>
+ /// <param name="gridType">
+ /// A value defined by the MgCoordinateSystemGridSpecializationType object
+ /// which indicates the Type of specialized grid desired.
+ /// </param>
+ /// <param name="gridLevel">
+ /// A value which indicates the density of the grid desired. The exact
+ /// value of this parameter is dependent upon the value of the
+ /// <c>gridType</c> argument. See Remarks below.
+ /// </param>
+ /// <returns>
+ /// Returns a fully initialized grid specification structure.
+ /// </returns>
+ /// <exception cref="std::bad_alloc">
+ /// Thrown in the event of a heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// The value of the <c>gridLevel</c> parameter is depenent upon the
+ /// <c>gridType</c> argument. For each type of grid, there exists
+ /// a different set legal values for the <c>gridLevel</c> parameter.
+ /// For example, the most common usgae would have the <c>gridType</c>
+ /// parameter set to MgCoordinateSystemGridSpecializationType::MGRS
+ /// and therefore the value of the <c>gridLevel</c> argument would
+ /// need to be a value defined by the MgCoordinateSystemMgrsGridLevel
+ /// object.
+ /// </remarks>
virtual MgCoordinateSystemGridSpecification* GridSpecification (INT32 gridType,
INT32 gridLevel);
// Grids and Graticules -- Generic
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures generic grid object. A generic grid is one which simply
+ /// draws isolines of one coordinate system (the Grid coordinate system)
+ /// into the drawing space of another (the frame system).
+ /// </summary>
+ /// <param name="sGridCs">
+ /// The coordinate system code name of the grid coordinate system.
+ /// </param>
+ /// <param name="sFrameCs">
+ /// The coordinate system code name of the frame coordinate system.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on all
+ /// exceptional conditions.
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to the abstract interface class from which the
+ /// generic grid object (and all other grid objects) derive.
+ /// object derive.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// Refer to <see cref="MgCoordinateSystemFactory::CreateFromCode"> for
+ /// additional exception information.
+ /// </remarks>
virtual MgCoordinateSystemGridBase* GenericGrid (CREFSTRING sGridCs,
CREFSTRING sFrameCs,
bool bSetExceptionsOn);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures generic grid object. A generic grid is one which simply
+ /// draws isolines of one coordinate system (the Grid coordinate system)
+ /// into the drawing space of another (the frame system).
+ /// </summary>
+ /// <param name="pGridCs">
+ /// The grid coordinate system.
+ /// </param>
+ /// <param name="pFrameCs">
+ /// The frame coordinate system.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on all
+ /// exceptional conditions.
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to the abstract interface class from which the
+ /// generic grid object (and all other grid objects) derive.
+ /// object derive.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// Refer to <see cref="MgCoordinateSystemFactory::CreateFromCode"> for
+ /// additional exception information.
+ /// </remarks>
virtual MgCoordinateSystemGridBase* GenericGrid (MgCoordinateSystem* pGridCs,
MgCoordinateSystem* pFrameCs,
bool bSetExceptionsOn);
// Grids and Graticules -- MGRS
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures an MGRS grid object. The returned object is suitable only
+ /// for use in simple coordinate <-> MGRS string calculations.
+ /// </summary>
+ /// <param name="dEquatorialRadius">
+ /// Equatorial radius of the ellipsod upon which conversions to and from
+ /// MGRS strings are to be based.
+ /// </param>
+ /// <param name="dEccentricy">
+ /// Eccentricity of the ellipsod upon which conversions to and from
+ /// MGRS strings are to be based.
+ /// </param>
+ /// <param name="nLetteringScheme">
+ /// A value as defined in the <c>MgCoordinateSystemMgrsLetteringScheme</c>
+ /// object which specifies the lettering scheme to be used on MGRS
+ /// string conversions.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on coordinate
+ /// conversions which fail for any reason.
+ /// </param>
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to an <c>MgCoordinateSystemMgrs</c>
+ /// object which is suitable <b>only</b> for MGRS string conversions.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
virtual MgCoordinateSystemMgrs* GetMgrs(double dEquatorialRadius,double dEccentricity,
INT8 nLetteringScheme,
bool bSetExceptionsOn);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures an MGRS grid object. The returned object is suitable only
+ /// for use in simple coordinate <-> MGRS string calculations.
+ /// </summary>
+ /// <param name="sEllispoidCode">
+ /// Dictionary code name of the ellipsoid upon which conversions to and from
+ /// MGRS strings are to be based.
+ /// </param>
+ /// <param name="nLetteringScheme">
+ /// A value as defined in the <c>MgCoordinateSystemMgrsLetteringScheme</c>
+ /// object which specifies the lettering scheme to be used on MGRS
+ /// string conversions.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on coordinate
+ /// conversions which fail for any reason.
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to an <c>MgCoordinateSystemMgrs</c>
+ /// object which is suitable <b>only</b> for MGRS string conversions.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
virtual MgCoordinateSystemMgrs* GetMgrsEllipsoid(CREFSTRING sEllipsoidCode,
INT8 nLetteringScheme,
bool bSetExceptionsOn);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures an MGRS grid object. The returned object is suitable only
+ /// for use in simple coordinate <-> MGRS string calculations.
+ /// </summary>
+ /// <param name="sDatumCode">
+ /// Dictionary code name of the datum whose referenced ellipsoid is to be
+ /// used for all conversions to and from MGRS strings.
+ /// </param>
+ /// <param name="nLetteringScheme">
+ /// A value as defined in the <c>MgCoordinateSystemMgrsLetteringScheme</c>
+ /// object which specifies the lettering scheme to be used on MGRS
+ /// string conversions.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on coordinate
+ /// conversions which fail for any reason.
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to an <c>MgCoordinateSystemMgrs</c>
+ /// object which is suitable <b>only</b> for MGRS string conversions.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// The datum specification is simply a means of specifying the ellipsoid
+ /// upon which the calculations are to be based. It does <b>not</b> mean
+ /// that any datum shift calculations will be performed.
+ /// </remarks>
virtual MgCoordinateSystemMgrs* GetMgrsDatum(CREFSTRING sDatumCode,
INT8 nLetteringScheme,
bool bSetExceptionsOn);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures an MGRS grid object which is suitable for generating an
+ /// actual MGRS grid.
+ /// </summary>
+ /// <param name="pFrameCs">
+ /// The frame coordinate system.
+ /// </param>
+ /// <param name="bUseFrameDatum">
+ /// <c>true</c> causes the frame datum to be used for all geodetic calculations
+ /// neccessary to generate the grid; otherwise WGS84 is assumed.
+ /// <param name="nLetteringScheme">
+ /// A value as defined in the <c>MgCoordinateSystemMgrsLetteringScheme</c>
+ /// object which specifies the lettering scheme to be used on MGRS
+ /// string conversions.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on coordinate
+ /// conversions which fail for any reason. This applies only to MGRS string
+ /// conversions.
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to the abstract interface class from which the
+ /// MGRS grid object (and all other grid objects) derive.
+ /// object derive.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// Refer to <see cref="MgCoordinateSystemFactory::CreateFromCode"> for
+ /// additional exception information.<para>
+ /// Coordinate system transformation exceptions are always suppressed during
+ /// grid generation.
+ /// </remarks>
virtual MgCoordinateSystemGridBase* MgrsGrid (MgCoordinateSystem* pFrameCs,
- bool bUseTargetDatum,
+ bool bUseFrameDatum,
INT8 nLetteringScheme,
bool bSetExceptionsOn);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Manufactures an MGRS grid object which is suitable for generating an
+ /// actual MGRS grid.
+ /// </summary>
+ /// <param name="sFrameCs">
+ /// The dictionary code name of the frame coordinate system.
+ /// </param>
+ /// <param name="bUseFrameDatum">
+ /// <c>true</c> causes the frame datum to be used for all geodetic calculations
+ /// neccessary to generate the grid; otherwise WGS84 is assumed.
+ /// <param name="nLetteringScheme">
+ /// A value as defined in the <c>MgCoordinateSystemMgrsLetteringScheme</c>
+ /// object which specifies the lettering scheme to be used on MGRS
+ /// string conversions.
+ /// </param>
+ /// <param name="bSetExceptionsOn">
+ /// <c>true</c> indicates that exceptions are to be thrown on coordinate
+ /// conversions which fail for any reason. This applies only to MGRS string
+ /// conversions.
+ /// </param>
+ /// <returns>
+ /// Returns a disposable pointer to the abstract interface class from which the
+ /// MGRS grid object (and all other grid objects) derive.
+ /// object derive.
+ /// </returns>
+ /// <exception cref="MgOutOfMemoryException">
+ /// Thrown on heap memory allocation failure.
+ /// </exception>
+ /// <remarks>
+ /// Refer to <see cref="MgCoordinateSystemFactory::CreateFromCode"> for
+ /// additional exception information.<para>
+ /// Coordinate system transformation exceptions are always suppressed during
+ /// grid generation.
+ /// </remarks>
virtual MgCoordinateSystemGridBase* MgrsGrid (CREFSTRING sFrameCs,
- bool bUseTargetDatum,
+ bool bUseFrameDatum,
INT8 nLetteringScheme,
bool bSetExceptionsOn);
Modified: trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h
===================================================================
--- trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -17,9 +17,7 @@
//=============================================================================
// Class declararations
-class MgCoordinateSystemGridBoundary; // MgPolygon based extents of the grid;
- // currently only rectangles are
- // supported.
+class MgCoordinateSystemGridBoundary; // MgPolygon based extents of the grid
class MgCoordinateSystemGridBase; // abstract interface between grid generator
// and grid consumer
class MgCoordinateSystemGridGeneric; // derives from MgCoordinateSystemGridBase
@@ -49,10 +47,19 @@
// as a double
-//=============================================================================
-// An enumeration of the various types of specialized grids/graticules
-// currently supported. A specialized grid is one for which specific standards
-// exist to which the results of this feature are compliant with.
+
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// An enumeration of the various types of specialized grids/graticules
+/// currently supported. A specialized grid is one for which specific
+/// standards exist to which the results of this feature are compliant with.
+/// A generic grid is a simple non-standardized grid of a coordinate system
+/// drawn in a viewport based on another coordinate system. <p>
+/// The values assigned are intended to support grouping standardized grids
+/// with similar features and is currently entirely arbitrary. Using a
+/// numeric literal instead of thes names of the defined constants is a sure
+/// way to write code that will get broken in the future.
+/// </summary>
class MgCoordinateSystemGridSpecializationType
{
PUBLISHED_API:
@@ -64,18 +71,19 @@
static const INT32 Unknown = (65366); // indicates a failure of an algorithm
};
-//=============================================================================
-// An enumeration of the supported values for the 'm_Orientation' member of
-// several objects related to grids and graticules.
-//
-// This value is used to qualify objects which are of the "iso" type. I.e. a
-// grid line is referred to as an isoline as it is the locus of points which
-// have a specific value for either the easting or the northing. It is this
-// value which indicates which. Thus, a grid line which is classified as
-// having an "EastWest" orientation will be a isoline which is the locus of
-// points which share a common easting value, and the "m_Value" element of
-// that object will be an easting value.
-//
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// An enumeration of the supported values for the <c>m_Orientation</c> member
+/// of several objects related to grids and graticules. <p>
+/// This value is used to qualify objects which are of the "iso" type. I.e. a
+/// grid line is referred to as an isoline as it is the locus of points which
+/// have a specific value for either the easting or the northing. It is this
+/// value which indicates which. Thus, a grid line which is classified as
+/// having an "EastWest" orientation will be a isoline which is the locus of
+/// points which share a common <b>easting</b> value, and the "m_Value" element
+/// of that object will be an <b>easting</b> value. Note that in this example,
+/// the line is typically a vertical line.
+/// </summary>
class MgCoordinateSystemGridOrientation
{
PUBLISHED_API:
@@ -85,51 +93,519 @@
static const INT8 Unknown = 3; // indicates a failure of an algorithm
};
-//=============================================================================
-// MgCoordinateSystemGridSpecification
-//
-// This object is used to convey all the parameters necessary for the
-// generation of a grid/graticule lumped into a single object for convenience.
-// Thus, adding a parameter determined to be necessary does not alter a lot of
-// calling sequences.
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// <c>MgCoordinateSystemGridSpecification</c> is an object that is used to
+/// convey all the parameters necessary for the generation of a grid/graticule
+/// lumped into a single object for convenience. Thus, adding a parameter
+/// determined to be necessary at a later time does not alter a lot of calling
+/// sequences.<p>
+/// Note that this interface is an abstract interface. There is code
+/// associated with the implementation of this interface which is used to
+/// handle the conversion of parameters between the various unit systems.
+/// Thus, one obtains a <c>MgCoordinateSystemGridSpecification</c> from the
+/// <c>MgCoordinateSystemFactory</c> object.<p>
+/// Note that all values are provided in the units specified within the object.
+/// The units used in this object do <b>not</b> need to be the same as any
+/// coordinate system involved in the generation of a grid, although the
+/// <b>type</b> of unit must be consistent with the type of grid being drawn.
+/// That is, specifying a Angular unit type when drawing a UTM grid will cause
+/// an exception at the time the request for (say) grid lines is issued.
+/// </summary>
class MG_GEOMETRY_API MgCoordinateSystemGridSpecification : public MgGuardDisposable
{
PUBLISHED_API:
- virtual double GetEastingBase (void)=0; // the base value from which easting grid line values are computed.
- virtual double GetNorthingBase (void)=0; // the base value from which northing grid line values are computed.
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Gets the easting base value.
+ /// </summary>
+ /// <returns>
+ /// Returns the current value of the easting base member.
+ /// </returns>
+ /// <remarks>
+ /// The base value is the base upon which grid values are determined.
+ /// Thus, a grid with and increment of, say, two degrees, can actually
+ /// start at one (the base) yielding grid lines at 1, 3, 5, 7, etc.
+ /// </remarks>
+ virtual double GetEastingBase (void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Gets the northing base value.
+ /// </summary>
+ /// <returns>
+ /// Returns the current value of the northing base member.
+ /// </returns>
+ /// <remarks>
+ /// The base value is the base upon which grid values are determined.
+ /// Thus, a grid with and increment of, say, two degrees, can actually
+ /// start at one (the base) yielding grid lines at 1, 3, 5, 7, etc.
+ /// </remarks>
+ virtual double GetNorthingBase (void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Gets the easting increment value.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual double GetEastingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual double GetEastingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual double GetEastingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current value of the easting increment member.
+ ///
+ /// \remarks
+ /// The distance between grid lines representing easting values.
+ ///
virtual double GetEastingIncrement(void)=0; // the interval between easting grid lines
- virtual double GetNorthingIncrement(void)=0; // the interval between northing grid lines
- virtual double GetTickEastingIncrement(void)=0; // number of tic subdivisions between grid increments in the east/west direction
- virtual double GetTickNorthingIncrement(void)=0; // number of tic subdivisions between grid increments in the north/south direction
- virtual INT32 GetUnitType(void)=0; // a value from MgCoordinateSystemUnitType indicating the type of units of the
- // base and interval specifications
- virtual INT32 GetUnitCode(void)=0; // a value from MgCoordinateSystemUnitCode indicating the units of the
- // base and interval specifications
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Gets the northing increment value.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual double GetNorthingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual double GetNorthingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual double GetNorthingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current value of the northing increment member.
+ ///
+ /// \remarks
+ /// The distance between grid lines representing northing values.
+ ///
+ virtual double GetNorthingIncrement(void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Gets the tick easting increment value.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual double GetTickEastingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual double GetTickEastingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual double GetTickEastingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current value of the tick easting increment member.
+ ///
+ /// \remarks
+ /// The distance between ticks representing specific easting values.
+ ///
+ virtual double GetTickEastingIncrement(void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Gets the tick northing increment value.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual double GetTickNorthingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual double GetTickNorthingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual double GetTickNorthingIncrement ();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current value of the tick northing increment member.
+ ///
+ /// \remarks
+ /// The distance between ticks representing specific northing values.
+ ///
+ virtual double GetTickNorthingIncrement(void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Gets the current unit type setting.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual int GetUnitType();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual int GetUnitType();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual int GetUnitType();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current unit type setting.
+ ///
+ /// \remarks
+ /// The value returned is one of the values defined in the
+ /// MgCoordinateSystemUnitType object and essentially specifies if the unit
+ /// specification is of the linear or angular type.
+ ///
+ virtual INT32 GetUnitType(void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Gets the current unit code setting.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual int GetUnitCode();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual int GetUnitCode();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual int GetUnitCode();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current unit code setting.
+ ///
+ /// \remarks
+ /// The value returned is one of the values defined in the
+ /// MgCoordinateSystemUnitCode object and essentially specifies the unit in
+ /// which the base, increment (line and tick), and curve precision values
+ /// are specified.
+ ///
+ virtual INT32 GetUnitCode(void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Determines if two MgCoordinateSystemGridSpecification objects are the
+ /// same.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual bool IsSameAs (MgCoordinateSystenGridSpecification secondObject);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual bool IsSameAs (MgCoordinateSystenGridSpecification secondObject);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual bool IsSameAs (MgCoordinateSystenGridSpecification secondObject);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param specification (MgCoordinateSystemGridSpecification)
+ /// The second object to which the host object is to be compared to.
+ ///
+ /// \return
+ /// Returns true if the objects are identical.
+ ///
+ /// \remarks
+ /// Objects with a different unit settings are automatically considered
+ /// different. Therefore the intelligence necessary to compare values which
+ /// are identical in different units is <b>not</b> present.
+ ///
virtual bool IsSameAs(MgCoordinateSystemGridSpecification* specification)=0;
- virtual double GetCurvePrecision(void)=0; // the maximum difference between true complex curve and the polyline
- // approximation thereof, in the same units used to specify the
- // base and increment values (i.e. UnitCode).
- // If left unspecified (or set to zero) a value is automatically selected to be,
- // approximately, the equivalent of 1 meter in target system units.
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Get the current curve precision value.
+ /// same.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual double GetCurvePrecision ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual double GetCurvePrecision ();
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual double GetCurvePrecision ();
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \return
+ /// Returns the current curve precision value.
+ ///
+ /// \remarks
+ /// The curve precision value specifies the desired maximum distance between
+ /// a complex curve approximation and the actual complex curve. This value
+ /// may be left at zero, and a suitable default value will be choosen by the
+ /// grid generation engine at grid line generation time.
+ ///
+ virtual double GetCurvePrecision(void)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Sets the easting and northing base values.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual void SetGridBase (double eastingBase, double northingBase);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual void SetGridBase (double eastingBase, double northingBase);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual void SetGridBase (double eastingBase, double northingBase);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param eastingBase (double)
+ /// The base value to be used in calculating the easting grid and tick
+ /// values.
+ ///
+ /// \param northingBase (double)
+ /// The base value to be used in calculating the northing grid and tick
+ /// values.
+ ///
+ /// \remarks
+ /// While the increment values determine the distance between grid lines
+ /// and ticks, the base value specifies the base value at which the
+ /// initial grid line/tick is positioned. Actually, the base for any
+ /// grid is the algebraically highest value which is less than the
+ /// grid boundary minimum and which, when mod'ed with base, produces zero.
+ ///
+ /// That is, for example, an increment of 2 and a base of 1 will produce
+ /// grid values of 1, 3, 5, 7, etc.
+ ///
virtual void SetGridBase(double eastingBase,double northingBase) = 0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Sets the easting and northing grid line increment values.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual void SetGridIncrement (double eastingIncrement, double northingIncrement);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual void SetGridIncrement (double eastingIncrement, double northingIncrement);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual void SetGridIncrement (double eastingIncrement, double northingIncrement);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param eastingIncrement (double)
+ /// The distance between easting grid lines.
+ ///
+ /// \param northingIncrement (double)
+ /// The distance between northing grid lines.
+ ///
+ /// \remarks
+ /// In this context, easting refers to grid lines which represent a specific
+ /// easting value; the resulting lines usually being vertical (i.e. south to
+ /// north) grid lines. Northing refers to grid lines which represent a
+ /// specific northing value; the resulting lines usually being horizontal
+ /// (i.e. west to east).
+ ///
+ /// \bugs
+ /// This function should be named SetGridIncrements to be consistent with the
+ /// rest of the interface.
+ ///
virtual void SetGridIncrement(double eastingIncrement,double northingIncrement) = 0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Sets the easting and northing tick increment values.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual void SetTickIncrements (double eastingIncrement, double northingIncrement);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual void SetTickIncrements (double eastingIncrement, double northingIncrement);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual void SetTickIncrements (double eastingIncrement, double northingIncrement);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param eastingIncrement (double)
+ /// The distance between easting tick marks.
+ ///
+ /// \param northingIncrement (double)
+ /// The distance between northing tick marks.
+ ///
virtual void SetTickIncrements(double eastingIncrement,double northingIncrement) = 0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Sets the units used to define the desired grid.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual void SetUnits (int unitCode, int unitType);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual void SetUnits (int unitCode, int unitType);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual void SetUnits (int unitCode, int unitType);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param unitCode (int)
+ /// One of the integer values defined in the MgCoordinateSystemUnitCode
+ /// object which indicates the units used to define the grid parameters.
+ ///
+ /// \param unitType (int)
+ /// One of the integer values defined in the MgCoordinateSystemUnitType
+ /// object which indicates the type of units (linear vs angular) used to
+ /// define the grid parameters.
+ ///
+ /// \remarks
+ /// The unitCode and unitType parameters must be consistent with each other
+ /// or an exception is thrown. Also, the unit tyupe must be consistent
+ /// with the type of grid being requested or an exception will be thrown.
+ /// That is, you may not define a graticule (i.e. a grid of geographic
+ /// coordinates on a projected coordinate system map) using linear units.
+ /// SImilarly, you cannot use angular units to define a grid of a projected
+ /// coordinate system on a projected coordinate system map.
+ ///
virtual void SetUnits (INT32 unitCode,INT32 unitType) = 0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Sets the desired precision of complecx curve approximations.
+ ///
+ /// <!-- Syntax in .Net, Java, and PHP -->
+ /// \htmlinclude DotNetSyntaxTop.html
+ /// virtual void SetCurvePrecision (double curvePrecision);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude JavaSyntaxTop.html
+ /// virtual void SetCurvePrecision (double curvePrecision);
+ /// \htmlinclude SyntaxBottom.html
+ /// \htmlinclude PHPSyntaxTop.html
+ /// virtual void SetCurvePrecision (double curvePrecision);
+ /// \htmlinclude SyntaxBottom.html
+ ///
+ /// \param curvePrecision (double)
+ /// The desired maximum distance between an approximation of a complex curve
+ /// and the true curve.
+ ///
+ /// \remarks
+ /// Please note the term desired in this description. The generation of a
+ /// complex curve approximation is also controlled by a variable usually
+ /// called the MaximumCurvePoints. Thus, if this criteria is exceeded in
+ /// the curve generation process, the curve precision can and will often be
+ /// less than that requested. This provision is implemented to reduce the
+ /// probability of a runaway grid which consumes the entire machine.
+ ///
+ /// \bugs
+ /// The maximum curve point variable should be a part of this object.
+ ///
virtual void SetCurvePrecision (double curvePrecision) = 0;
INTERNAL_API:
- // The following function identically to the published version, with the
- // exception that the value returned is converted to the units of the
- // provided coordinate system. Typically, the provided coordinate system
- // is either the grid coordinate system OR the frame coordinate system.
- virtual double GetEastingBase (MgCoordinateSystem* gridCS)=0;
- virtual double GetNorthingBase (MgCoordinateSystem* gridCS)=0;
- virtual double GetEastingIncrement (MgCoordinateSystem* gridCS)=0;
- virtual double GetNorthingIncrement (MgCoordinateSystem* gridCS)=0;
- virtual double GetCurvePrecision (MgCoordinateSystem* gridCS)=0;
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the easting base value after conversion from the units
+ /// of this specification object to the units of the provided coordinate
+ /// system.
+ ///
+ /// \param gridCRS
+ /// The return value is converted to the units of this coordinate system.
+ ///
+ /// \return
+ /// Easting base value in units of the provided coordinate system.
+ ///
+ /// \exception
+ /// Will throw if the unit types of this specification and the provided
+ /// coordinate system are not the same.
+ ///
+ virtual double GetEastingBase (MgCoordinateSystem* gridCRS)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the northing base value after conversion from the units
+ /// of this specification object to the units of the provided coordinate
+ /// system.
+ ///
+ /// \param gridCRS
+ /// The return value is converted to the units of this coordinate system.
+ ///
+ /// \return
+ /// Northing base value in units of the provided coordinate system.
+ ///
+ /// \exception
+ /// Will throw if the unit types of this specification and the provided
+ /// coordinate system are not the same.
+ ///
+ virtual double GetNorthingBase (MgCoordinateSystem* gridCRS)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the easting grid increment value after conversion from the
+ /// units of this specification object to the units of the provided
+ /// coordinate system.
+ ///
+ /// \param gridCRS
+ /// The return value is converted to the units of this coordinate system.
+ ///
+ /// \return
+ /// Easting grid increment value in units of the provided coordinate system.
+ ///
+ /// \exception
+ /// Will throw if the unit types of this specification and the provided
+ /// coordinate system are not the same.
+ ///
+ virtual double GetEastingIncrement (MgCoordinateSystem* gridCRS)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the northing grid increment value after conversion from the
+ /// units of this specification object to the units of the provided
+ /// coordinate system.
+ ///
+ /// \param gridCRS
+ /// The return value is converted to the units of this coordinate system.
+ ///
+ /// \return
+ /// Northing grid increment value in units of the provided coordinate system.
+ ///
+ /// \exception
+ /// Will throw if the unit types of this specification and the provided
+ /// coordinate system are not the same.
+ ///
+ virtual double GetNorthingIncrement (MgCoordinateSystem* gridCRS)=0;
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// \brief
+ /// Returns the curve precision value after conversion from the units
+ /// of this specification object to the units of the provided coordinate
+ /// system.
+ ///
+ /// \param gridCRS
+ /// The return value is converted to the units of this coordinate system.
+ ///
+ /// \return
+ /// Curve precision value in units of the provided coordinate system.
+ ///
+ /// \exception
+ /// Will throw if the unit types of this specification and the provided
+ /// coordinate system are not the same.
+ ///
+ /// \remarks
+ /// If this specification object's curve precision value has not been set
+ /// or is otherwise set to zero, this function will manufacture a curve
+ /// precision value consistent with the coordinate system provided. Note
+ /// that this default value will be more liberal than conservative.
+ ///
+ /// \bugs
+ /// The automatically calculated curve precision value should be a function
+ /// of the Grid Boundary object which known how much geography is to be
+ /// included in the grid and is thus in a better position to determine
+ /// what the default value should be.
+ ///
+ virtual double GetCurvePrecision (MgCoordinateSystem* gridCRS)=0;
+
protected:
- INT32 GetClassId(){return m_cls_id;};
+ INT32 GetClassId(){return m_cls_id;};
CLASS_ID:
static const INT32 m_cls_id = CoordinateSystem_CoordinateSystemGridSpecification;
};
@@ -137,6 +613,17 @@
//=============================================================================
// External to this interface, boundary objects are always in the viewport
// (i.e. target) coordinate system.
+/// <summary>
+/// This object is used to maintain the definition of the boundary of a
+/// specific grid or graticule. Externally, a
+/// <c>MgCoordinateSystemGridBoundary</c> object will be in viewport
+/// coordinates. Internally, objects of this type are oftyen used to the
+/// carry grid boundaries in grid coordinates, and also greographic
+/// coordinates.<p>
+/// Grid boundaries iusually start out as rectangles, but are often converted
+/// to a series of complex curves approximated by multi-segment lines (i.e.
+/// line strings).
+/// </summsry>
class MG_GEOMETRY_API MgCoordinateSystemGridBoundary : public MgGuardDisposable
{
PUBLISHED_API:
Modified: trunk/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/GeometryConsoleTest/GeometryConsoleTest.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -16,12 +16,15 @@
INT32 index3;
INT32 index4;
INT32 tickCount;
+ INT32 orientation;
INT32 regionCount;
INT32 gridLineCount;
INT32 lineSegmentCount;
double xx;
double yy;
+ double uu;
+ double vv;
double value;
MgCoordinateSystemFactory factory;
@@ -40,9 +43,6 @@
MgCoordinateSystemGridTick* pGridTick;
MgCoordinateSystemGridTickCollection* pGridTicks;
- MgCoordinate* southWestXY = new MgCoordinateXY (600000.0,3900000.0);
- MgCoordinate* northEastXY = new MgCoordinateXY (900000.0,4100000.0);
-
pGridSpecification = factory.GridSpecification ();
pGridSpecification->SetGridBase (0.0,0.0);
pGridSpecification->SetGridIncrement (1.0,1.0);
@@ -50,12 +50,17 @@
pGridSpecification->SetUnits (MgCoordinateSystemUnitCode::Degree,MgCoordinateSystemUnitType::Angular);
pGridSpecification->SetCurvePrecision (1.0E-05);
- pGenericGrid = factory.GenericGrid (L"LL84",L"UTM83-13",true);
+ pGenericGrid = factory.GenericGrid (L"LL84",L"CA83-IIF",true);
+
+ MgCoordinate* southWestXY = new MgCoordinateXY (6.49E+06,1.99E+06);
+ MgCoordinate* northEastXY = new MgCoordinateXY (6.61E+06,2.11E+06);
pGridBoundary = factory.GridBoundary (southWestXY,northEastXY);
southWestXY->Release ();
northEastXY->Release ();
pGenericGrid->SetBoundary (pGridBoundary);
+ pGridBoundary->Release ();
+
pGridLines = pGenericGrid->GetGridLines (pGridSpecification);
gridLineCount = pGridLines->GetCount ();
for (index1 = 0;index1 < gridLineCount;index1 += 1)
@@ -86,6 +91,16 @@
for (index4 = 0;index4 < tickCount;index4 += 1)
{
pGridTick = pGridTicks->GetItem (index4);
+ value = pGridTick->GetValue ();
+ orientation = pGridTick->GetTickOrientation ();
+ pCoordinate = pGridTick->GetPosition ();
+ xx = pCoordinate->GetX ();
+ yy = pCoordinate->GetY ();
+ pCoordinate->Release ();
+ pCoordinate = pGridTick->GetDirectionVector ();
+ uu = pCoordinate->GetX ();
+ vv = pCoordinate->GetY ();
+ pCoordinate->Release ();
pGridTick->Release ();
}
pGridTicks->Release ();
@@ -95,8 +110,24 @@
pGridSpecification = factory.GridSpecification (MgCoordinateSystemGridSpecializationType::MGRS,
MgCoordinateSystemMgrsGridLevel::Mgrs1Km);
- pMgrs = factory.MgrsGrid (L"UTM84-13N",false,MgCoordinateSystemMgrsLetteringScheme::Normal,true);
+
+ pGridSpecification = factory.GridSpecification ();
+ pGridSpecification->SetGridBase (0.0,0.0);
+ pGridSpecification->SetGridIncrement (100.0,100.0);
+ pGridSpecification->SetTickIncrements (10.0,10.0);
+ pGridSpecification->SetUnits (MgCoordinateSystemUnitCode::Kilometer,MgCoordinateSystemUnitType::Linear);
+ pGridSpecification->SetCurvePrecision (0.5);
+
+ southWestXY = new MgCoordinateXY (6.49E+06,1.99E+06);
+ northEastXY = new MgCoordinateXY (6.61E+06,2.11E+06);
+ pGridBoundary = factory.GridBoundary (southWestXY,northEastXY);
+ southWestXY->Release ();
+ northEastXY->Release ();
+
+ pMgrs = factory.MgrsGrid (L"CA83-IIF",false,MgCoordinateSystemMgrsLetteringScheme::Normal,true);
pMgrs->SetBoundary (pGridBoundary);
+ pGridBoundary->Release ();
+
pGridLines = pMgrs->GetGridLines (pGridSpecification);
gridLineCount = pGridLines->GetCount ();
for (index1 = 0;index1 < gridLineCount;index1 += 1)
@@ -136,13 +167,22 @@
for (index4 = 0;index4 < tickCount;index4 += 1)
{
pGridTick = pGridTicks->GetItem (index4);
+ value = pGridTick->GetValue ();
+ orientation = pGridTick->GetTickOrientation ();
+ pCoordinate = pGridTick->GetPosition ();
+ xx = pCoordinate->GetX ();
+ yy = pCoordinate->GetY ();
+ pCoordinate->Release ();
+ pCoordinate = pGridTick->GetDirectionVector ();
+ uu = pCoordinate->GetX ();
+ vv = pCoordinate->GetY ();
+ pCoordinate->Release ();
pGridTick->Release ();
}
pGridTicks->Release ();
pMgrs->Release ();
- pGridBoundary->Release ();
pGridSpecification->Release ();
return 0;
Modified: trunk/MgDev/Common/Geometry/Spatial/MathUtility.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/MathUtility.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/Spatial/MathUtility.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -211,3 +211,42 @@
return interpolated;
}
+
+bool MgMathUtility::DblCmp (double first,double second)
+{
+ int exp1, exp2;
+ int deltaExp;
+ double mant1,mant2;
+
+ mant1 = frexp (first ,&exp1);
+ mant2 = frexp (second,&exp2);
+ deltaExp = exp1 - exp2;
+ if (abs (deltaExp) >= 2) return false;
+
+ // Need to deal with the case where the difference between the exponents
+ // is +/-1. This is necessary as the two values may be infinitesimally
+ // greater and less than an even true binary value like 0.5. In this
+ // case, they would be equal, but the exponents would not be the same.
+ if (deltaExp == 1)
+ {
+ // exp of first is bigger than exp of second. Adjust exp2 and mant2
+ // so that they still represent the same value, but exp2 is now the
+ // same as exp1. Note, this de-normalizes the numbers, but that
+ // does not affect the comparison result in any way.
+ exp2 += 1;
+ mant2 *= 0.5;
+ }
+ else if (deltaExp == -1)
+ {
+ exp1 += 1;
+ mant1 *= 0.5;
+ }
+
+ // Now, if the exponents are not equal, obviously the original values
+ // are not equal; not even close.
+ if (exp1 != exp2) return false;
+
+ // Since the exponents are equal, then we can simply compare the mantissas.
+ // We ignore any difference in the last few bits.
+ return (fabs (mant1 - mant2) < 5.0E-13);
+}
Modified: trunk/MgDev/Common/Geometry/Spatial/MathUtility.h
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/MathUtility.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/Spatial/MathUtility.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -91,6 +91,24 @@
/// It is allowable to pass NaN for any parameter, in which case the return
/// value is also a (quiet) NaN.
static double LinearInterpolate(double start, double end, double proportion);
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Reliably compares two doubles, providing that neither of the two values
+ /// is a hard zero, ignoring differences in the least significant bits of
+ /// the mantissa which are unreliable if either of the values being
+ /// compared are the result of some serious calculations.
+ /// </summary>
+ /// <param name="first">
+ /// The first of two doubles to be compared. Must not be a hard zero.
+ /// </param>
+ /// <param name="second">
+ /// The second of two doubles to be compared. Must not be a hard zero.
+ /// </param>
+ /// <returns>
+ /// Returns <c>true</c> for "essentially equal".
+ /// </returns>
+ static bool DblCmp (double first,double second);
};
/// \endcond
Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp 2009-09-08 22:16:31 UTC (rev 4212)
@@ -514,3 +514,375 @@
return retGeomComp.Detach();
}
+
+//////////////////////////////////////////////
+///<summary>
+/// Calculates the two dimensional intersection of two line segments.
+///
+///</summary>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+INT32 MgSpatialUtility::SegmentIntersection (MgCoordinate* result,MgCoordinate* seg1From,
+ MgCoordinate* seg1To,
+ MgCoordinate* seg2From,
+ MgCoordinate* seg2To)
+{
+ INT32 status (-7); // until we know different.
+
+ double delX1, delY1;
+ double delX2, delY2;
+ double denom1, denom2;
+ double num, denom; // numerator and denominator
+
+ CHECKNULL(result, L"MgSpatialUtility.SegmentIntersection")
+ CHECKNULL(seg1From, L"MgSpatialUtility.SegmentIntersection")
+ CHECKNULL(seg1To, L"MgSpatialUtility.SegmentIntersection")
+ CHECKNULL(seg2From, L"MgSpatialUtility.SegmentIntersection")
+ CHECKNULL(seg2To, L"MgSpatialUtility.SegmentIntersection")
+
+ // Compute the denominator which also tells us if the lines are collinear.
+ delX1 = seg1To->GetX () - seg1From->GetX ();
+ delY1 = seg1To->GetY () - seg1From->GetY ();
+ delX2 = seg2To->GetX () - seg2From->GetX ();
+ delY2 = seg2To->GetY () - seg2From->GetY ();
+ denom1 = delX2 * delY1;
+ denom2 = delX1 * delY2;
+ if (MgMathUtility::DblCmp (denom1,denom2))
+ {
+ // Collinear or parallel, there is no intersection.
+ status = -1;
+ }
+ else
+ {
+ // OK, we have a stable geometry and an intersection of some sort should exist.
+ // Compute the intersection point.
+ status = 0;
+ denom = denom1 - denom2;
+ num = delX1 * delX2 * (seg2From->GetY() - seg1From->GetY()) +
+ delX2 * delY1 * seg1From->GetX() -
+ delX1 * delY2 * seg2From->GetX();
+ result->SetX (num / denom);
+
+ num = delY1 * delY2 * (seg2From->GetX() - seg1From->GetX()) +
+ delY2 * delX1 * seg1From->GetY() -
+ delY1 * delX2 * seg2From->GetY();
+ result->SetY (num / -denom);
+
+ // Now to compute the location of the intersection point relative to the
+ // line segments involved. This is often very important.
+ if (fabs (delX1) > fabs (delY1))
+ {
+ // Segment one is more horizontal than vertical. We will use the X
+ // value to test if the resulting point is on the segment. Notice
+ // that an interscetion point which resides (relatively) precisely
+ // on the 'to' point is not considered to be on the segment.
+ if (delX1 >= 0.0)
+ {
+ // X increases from the 'from' point to the 'to' point.
+ if (result->GetX() > seg1From->GetX() && result->GetX() <= seg1To->GetX())
+ {
+ status |= 1;
+ }
+ }
+ else
+ {
+ // X decreases from the 'from' point to the 'to' point.
+ if (result->GetX() < seg1From->GetX() && result->GetX() >= seg1To->GetX())
+ {
+ status |= 1;
+ }
+ }
+ }
+ else
+ {
+ // First segment is more verical than horizontal. We will use the y
+ // value to test if the resulting point is on the segment.
+ if (delY1 >= 0.0)
+ {
+ // Y increases from the 'from' point to the 'to' point.
+ if (result->GetY() > seg1From->GetY() && result->GetY() <= seg1To->GetY())
+ {
+ status |= 1;
+ }
+ }
+ else
+ {
+ // Y increases from the 'from' point to the 'to' point.
+ if (result->GetY() < seg1From->GetY() && result->GetY() >= seg1To->GetY())
+ {
+ status |= 1;
+ }
+ }
+ }
+
+ // Same stuff with the second segment, sans comments.
+ if (fabs (delX2) > fabs (delY2))
+ {
+ if (delX2 >= 0.0)
+ {
+ if (result->GetX() > seg2From->GetX() && result->GetX() <= seg2To->GetX())
+ {
+ status |= 2;
+ }
+ }
+ else
+ {
+ if (result->GetX() < seg2From->GetX() && result->GetX() >= seg2To->GetX())
+ {
+ status |= 2;
+ }
+ }
+ }
+ else
+ {
+ if (delY2 >= 0.0)
+ {
+ if (result->GetY() > seg2From->GetY() && result->GetY() <= seg2To->GetY())
+ {
+ status |= 2;
+ }
+ }
+ else
+ {
+ if (result->GetY() < seg2From->GetY() && result->GetY() >= seg2To->GetY())
+ {
+ status |= 2;
+ }
+ }
+ }
+ }
+ return status;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// Returns a list of coordinates with all of the intersection points of the
+/// provided segment with the polygon provided by the first argument. Note
+/// that the first argument is a CoordinateIterator; so it doesn't have to be
+/// an MgPolygon. However, this function ASSUMES that the iterator does indeed
+/// point to a closed ring.
+/// </summary>
+MgCoordinateCollection* MgSpatialUtility::PolySegIntersection (MgCoordinateIterator* polyItr,MgCoordinate* segFrom,
+ MgCoordinate* segTo)
+{
+ int status;
+ Ptr<MgCoordinateCollection> coordinateCollection;
+ Ptr<MgCoordinate> intersection;
+ Ptr<MgCoordinate> polyFrom;
+ Ptr<MgCoordinate> polyTo;
+
+ CHECKNULL(polyItr, L"MgSpatialUtility.PolySegIntersection")
+ CHECKNULL(segFrom, L"MgSpatialUtility.PolySegIntersection")
+ CHECKNULL(segTo, L"MgSpatialUtility.PolySegIntersection")
+
+ // Create the return object. Quite often it gets returned empty, but we
+ // will always return a "new" object (i.e. refCount == 1). Create a work
+ // point we can use.
+ coordinateCollection = new MgCoordinateCollection ();
+ intersection = new MgCoordinateXY ();
+
+ // Reset the iterator so we know for sure what its state is.
+ polyItr->Reset ();
+ polyItr->MoveNext ();
+
+ // Loop through each segment in the polygon. If its an exterior ring,
+ // as is usually the case, it should be in counterclockwise order.
+ polyTo = polyItr->GetCurrent ();
+ while (polyItr->MoveNext ())
+ {
+ polyFrom = polyTo;
+ polyTo = polyItr->GetCurrent ();
+ status = SegmentIntersection (intersection,polyFrom,polyTo,segFrom,segTo);
+ if (status == 3)
+ {
+ // We have an intersection of interest to us. We need to add a
+ // point which will still be on the heap when we are done, so we
+ // definitely do not want to add the intersection point.
+ Ptr<MgCoordinate> newPoint = new MgCoordinateXY (intersection->GetX(),intersection->GetY());
+ coordinateCollection->Add(newPoint);
+
+ // The line segment can, and often does, have more than one
+ // intersection point with the polygon. SO we keep trucking.
+ }
+ }
+
+ // We return the generated collection, which will often be empty.
+ return coordinateCollection.Detach ();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// Returns true if the provided query point is inside of, or on, the closed
+/// ring provided by the polyItr argument.
+/// </summary>
+bool MgSpatialUtility::PointIsInPolygon (MgCoordinateIterator* polyItr,MgCoordinate* queryPoint)
+{
+ bool isInside;
+
+ INT32 count;
+
+ double minX, maxX;
+ double minY, maxY;
+ double outX, outY;
+
+ Ptr<MgCoordinate> tmpCoord;
+ Ptr<MgCoordinate> outPoint;
+ Ptr<MgCoordinateCollection> coordinateCollection;
+
+ // Accunulate min/max;
+ polyItr->Reset ();
+ minX = minY = +9.9E+100;
+ maxX = maxY = -9.9E+100;
+ while (polyItr->MoveNext ())
+ {
+ tmpCoord = polyItr->GetCurrent ();
+ if (tmpCoord->GetX() < minX) minX = tmpCoord->GetX ();
+ if (tmpCoord->GetY() < minY) minY = tmpCoord->GetY ();
+ if (tmpCoord->GetX() > maxX) maxX = tmpCoord->GetX ();
+ if (tmpCoord->GetY() > maxY) maxY = tmpCoord->GetY ();
+ }
+
+ // Create a from point known to be outside of the polygon.
+ outX = (minX >= 0.0) ? -minX : minX * 2.0;
+ outY = (minY >= 0.0) ? -minY : minY * 2.0;
+ outPoint = new MgCoordinateXY (outX,outY);
+
+ // Get all the intersections between the "outPoint" amd the query Point.
+ coordinateCollection = PolySegIntersection (polyItr,outPoint,queryPoint);
+ count = coordinateCollection->GetCount ();
+
+ // If the number of intersections is odd, the query point is inside.
+ // Otherwise it is outside. (Zero is an even number, isn't it?)
+ isInside = ((count & 1) != 0);
+
+ return isInside;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// <summary>
+/// Returns a collection of line strings which represents those portions of the
+/// provided line string which are inside of the provided closed ring.
+/// </summary>
+MgLineStringCollection* MgSpatialUtility::ClipStringToPolygon (MgCoordinateIterator* polyItr,
+ MgCoordinateIterator* lineItr)
+{
+ bool inside;
+
+ INT32 index;
+
+ Ptr<MgCoordinate> lineFrom;
+ Ptr<MgCoordinate> lineTo;
+ Ptr<MgCoordinateCollection> curCollection;
+ Ptr<MgLineString> newLineString;
+ Ptr<MgLineStringCollection> lineCollection;
+
+ // Need to create an empty collections, the factory doesn't do this.
+ curCollection = new MgCoordinateCollection ();
+ lineCollection = new MgLineStringCollection ();
+
+ // Set up the line string iterator. It is the primary control loop
+ // for this operation.
+ lineItr->Reset ();
+ lineItr->MoveNext ();
+ lineTo = lineItr->GetCurrent ();
+
+ // We need to know in what state we are starting in. lineTo currently
+ // has the coordinates of the first point, which will become the
+ // lineFrom point once the main loop gets started.
+ inside = PointIsInPolygon (polyItr,lineTo);
+
+ // If we are starting inside the polgon, we push the first point
+ // onto the current point collection.
+ if (inside)
+ {
+ curCollection->Add (lineTo);
+ }
+
+ while (lineItr->MoveNext ())
+ {
+ lineFrom = lineTo; // TODO: does this work without screwing up the reference counts.
+ lineTo = lineItr->GetCurrent ();
+
+ // Intersect this segment with the polygon.
+ Ptr<MgCoordinateCollection> segCollection;
+ segCollection = PolySegIntersection (polyItr,lineFrom,lineTo);
+ INT32 segCount = segCollection->GetCount ();
+
+ // If the segment count is zero, there were no intersections. If we were
+ // inside, we're still inside.
+ if (segCount == 0)
+ {
+ if (inside)
+ {
+ curCollection->Add (lineTo);
+ }
+ }
+ else
+ {
+ // There is at least one intersection, so there will some state changing going on here.
+ for (index = 0;index < segCount;index += 1)
+ {
+ Ptr<MgCoordinate> newPoint = segCollection->GetItem (index);
+
+ // Terminate the current state, and initate the new state.
+ // At this point, the state switches for each point in the
+ // intersection list.
+ if (inside)
+ {
+ // We're inside. Switch to outside state. sewPoint is the
+ // location where we left the inside of the polygon.
+ curCollection->Add (newPoint);
+
+ // Make a line string out of the current point collection,
+ // and add it to the line string collection which contains
+ // the clipped segments.
+ newLineString = new MgLineString (curCollection);
+ lineCollection->Add (newLineString);
+
+ // Clear curCollection inpreparation for the nex segment if
+ // there is one.
+ curCollection->Clear ();
+
+ // We're outside of the polygon now.
+ inside = false;
+ }
+ else
+ {
+ // We were outside the polgon. The intersection point
+ // is the point at which we reenterd the polygon.
+ curCollection->Add (newPoint);
+
+ // We're back inside now.
+ inside = true;
+ }
+ }
+ // At this point, if we end up inside, there will be a point in
+ // curCollection which will be the point at which we re-entered
+ // the last time. Since we are inside, we need to add the
+ // lineTo point to the collection.
+ if (inside)
+ {
+ curCollection->Add (lineTo);
+ }
+
+ // Now we do something which might appear strange: we leave the
+ // curCollection object alone. In this manner, we should eliminate
+ // a lot of contiguous line strings in the line string collection.
+ // Hope it works out that way. It should, as if we are inside now,
+ // the first point of the segment from the line string should also
+ // be inside.
+ }
+ }
+
+ // If we ended this mess in the inside state, curCollection should _NOT_ be
+ // empty. In this case, we need to add this final point collection as the
+ // final line stting in the line string collection.
+ if (inside)
+ {
+ lineCollection->Add (newLineString);
+ }
+
+ // Looks pretty simple, maybe that means it will work good; often does.
+ return lineCollection.Detach ();
+}
Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h 2009-09-08 21:26:17 UTC (rev 4211)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h 2009-09-08 22:16:31 UTC (rev 4212)
@@ -109,6 +109,137 @@
static MgLinearRing* CurveRingToLinearRing(MgCurveRing* curveRing, double maxSpacing, double maxOffset);
static MgLinearSegment* ArcSegmentToLinearSegment(MgArcSegment* segment, double maxSpacing, double maxOffset);
+ ///////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Computes the intersection of two 2D line segments. Intersection point,
+ /// if any, is returned in the provided result coordinate which (of course)
+ /// must already exist.
+ /// </summary>
+ /// <param name="result">
+ /// The calculated intersection point is returned in this variable which,
+ /// of course, must exist.
+ /// <param name="seg1From">
+ /// The initial point of the first line segment.
+ /// <param name="seg1To">
+ /// The end point of the first line segment.
+ /// <param name="seg2From">
+ /// The initial point of the second line segment.
+ /// <param name="seg2To">
+ /// The end point of the second line segment.
+ /// <returns>
+ /// Return status:
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Status</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ /// <item>
+ /// <term>-1</term>
+ /// <description>no intersection, segments are parallel or collinear or
+ /// a segemnt is of zero length; result remains unchanged
+ /// </description>
+ /// </item>
+ /// <item><term> 0</term><desription>intersection exists, intersection point is not on either line</description></item>
+ /// <item><term> 1</term><desription>intersection exists, intersection point is on segment 1 only</description></item>
+ /// <item><term> 2</term><desription>intersection exists, intersection point is on segment 2 only</description></item>
+ /// <item><term> 3</term><desription>intersection exists, intersection point is on both segments</description></item>
+ /// </list>
+ /// <remarks>
+ /// In determining if the intersection point resides on a line, an intersection
+ /// point identical to the 'to' point is considered on the line, but an
+ /// intersection point identical to the 'from' point is _NOT_ considered to be
+ /// on the line. Such a convention is necessary to avoid the appearance
+ /// of two intersections when indeed there is only one when processing a
+ /// a line string, for example.
+ /// </remarks>
+ /// <exception cref="MgNullReferenceException">
+ /// Thrown if any argument is null
+ /// </exception>
+ static INT32 SegmentIntersection (MgCoordinate* result,MgCoordinate* seg1From,
+ MgCoordinate* seg1To,
+ MgCoordinate* seg2From,
+ MgCoordinate* seg2To);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Returns a collection of coordinates with all of the intersection points of
+ /// the provided segment with the polygon provided by the first argument.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator of the closed ring to which the provided segment is
+ /// intersected.
+ /// </param>
+ /// <param name="segFrom">
+ /// The initial point of the line segment to be intersected with the provided
+ /// closed ring.
+ /// </param>
+ /// <param name="segTo">
+ /// The ending point of the line segment to be intersected with the provided
+ /// closed ring.
+ /// </param>
+ /// <returns>
+ /// A 2D coordinate collection of all intersection points; can and often is
+ /// an empty collection.
+ /// </returns>
+ /// <remarks>
+ /// This is a 2D function only, Z and M coordinates are ignored; the returned
+ /// point collection is a collection of <c>MgCoordinateXY</c> objects.<para>
+ /// Note that the first argument is a CoordinateIterator; so it doesn't have to be
+ /// an <c>MgPolygon</c>. However, this function assumes that the iterator does indeed
+ /// point to a closed ring.
+ /// </remarks>
+ static MgCoordinateCollection* PolySegIntersection (MgCoordinateIterator* polyItr,
+ MgCoordinate* segFrom,
+ MgCoordinate* segTo);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Determines if the provided point is inside (or actually on) the closed
+ /// ring provided bythe polyItr argument.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator of the closed ring which is the subject polygon.
+ /// </param>
+ /// <param name="queryPoint">
+ /// The 2D point whose status is to be determined.
+ /// </param>
+ /// <returns>
+ /// Returns true if the query point is inside or on the provided closed
+ /// ring.
+ /// </returns>
+ /// <remarks>
+ /// Currently, this function calculates the envelope of the provided closed
+ /// ring in order to determine a point which is known to be outside of the
+ /// closed ring. An overloaded function which accepts a point known to be
+ /// outside the closed ring would be a lot faster.
+ /// </remarks>
+ static bool PointIsInPolygon (MgCoordinateIterator* polyItr,MgCoordinate* queryPoint);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// <summary>
+ /// Clips a line string to an arbitrary polygon returning a collection of line
+ /// strings which represent the portions of the the provided line string which
+ /// are inside the provided closed ring.
+ /// </summary>
+ /// <param name="polyItr">
+ /// An iterator to the closed ring to which the provided line string is to be
+ /// clipped.
+ /// </param>
+ /// <param name="lineItr">
+ /// An iterator for the line string which is to be clipped.
+ /// </param>
+ /// <returns>
+ /// A collection of line string objects which represents the portions of the
+ /// provided line string which are inside of the provided closed ring. This
+ /// collection may be empty.
+ /// </returns>
+ /// <remarks>
+ /// This is a pure 2D function. The line strings generated will contain
+ /// collections of <c>MgCoordinateXY</c> objects.
+ /// </remarks>
+ static MgLineStringCollection* ClipStringToPolygon (MgCoordinateIterator* polyItr,
+ MgCoordinateIterator* lineItr);
+
protected:
MgSpatialUtility() {};
More information about the mapguide-commits
mailing list