[mapguide-commits] r4298 - in trunk/MgDev/Common: CoordinateSystem Geometry/CoordinateSystem Geometry/Spatial

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu Oct 15 18:24:22 EDT 2009


Author: NormOlsen
Date: 2009-10-15 18:24:21 -0400 (Thu, 15 Oct 2009)
New Revision: 4298

Modified:
   trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
   trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h
   trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp
   trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
   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/CoordinateSystemGrids.h
   trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
Log:
This submission corrects several flaws uncovered during testing of the API created to implement RFC 76.  This work includes the correction of several bugs, memory leaks, crashes, functionality flaws, and exception handling misques.  With this submission, the API is capable of producing good results, although a few known defects remain to be addressed; namely in the areas of tick mark generation and handling of the polar regions.

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -166,7 +166,8 @@
     codeOk = GetUnitInfo(unitCode,&lclUnitType,NULL);
     if (!codeOk || unitType != lclUnitType)
     {
-        throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.SetUnits", __LINE__, __WFILE__, NULL, L"", NULL);
+        throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.SetUnits",
+                                                          __LINE__, __WFILE__, NULL, L"", NULL);
     }
 
     m_UnitCode = unitCode;
@@ -176,196 +177,50 @@
 {
     m_CurvePrecision = curvePrecision;
 }
-
 // 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)
+// exception that the values returned are always converted to the units requested
+// by the resultUnitCode argument.
+double CCoordinateSystemGridSpecification::GetEastingBase (INT32 resultUnitCode)
 {
-    INT32 gridUnitType;
-    INT32 gridCrsUnitCode;
-    double unitConversion;
+    double eastingBase;
 
-    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);
-    }
-
-    // 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_EastingBase * unitConversion);
+    eastingBase = ConvertUnitsOfValue (m_EastingBase,resultUnitCode);
+    return eastingBase;
 }
-double CCoordinateSystemGridSpecification::GetNorthingBase (MgCoordinateSystem* gridCS)
+double CCoordinateSystemGridSpecification::GetNorthingBase (INT32 resultUnitCode)
 {
-    INT32 gridUnitType;
-    INT32 gridCrsUnitCode;
-    double unitConversion;
+    double northingBase;
 
-    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.GetNorthingBase", __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_NorthingBase * unitConversion);
+    northingBase = ConvertUnitsOfValue (m_NorthingBase,resultUnitCode);
+    return northingBase;
 }
-double CCoordinateSystemGridSpecification::GetEastingIncrement(MgCoordinateSystem* gridCS)
+double CCoordinateSystemGridSpecification::GetEastingIncrement (INT32 resultUnitCode)
 {
-    INT32 gridUnitType;
-    INT32 gridCrsUnitCode;
-    double unitConversion;
+    double eastingIncrement;
 
-    Ptr<MgCoordinateSystemCatalog> catalogPtr = gridCS->GetCatalog ();
-    Ptr<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.GetEastingIncrement", __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_EastingIncrement * unitConversion);
+    eastingIncrement = ConvertUnitsOfValue (m_EastingIncrement,resultUnitCode);
+    return eastingIncrement;
 }
-double CCoordinateSystemGridSpecification::GetNorthingIncrement(MgCoordinateSystem* gridCS)
+double CCoordinateSystemGridSpecification::GetNorthingIncrement(INT32 resultUnitCode)
 {
-    INT32 gridUnitType;
-    INT32 gridCrsUnitCode;
-    double unitConversion;
+    double northingIncrement;
 
-    Ptr<MgCoordinateSystemCatalog> catalogPtr = gridCS->GetCatalog ();
-    Ptr<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.GetNorthingIncrement", __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_NorthingIncrement * unitConversion);
+    northingIncrement = ConvertUnitsOfValue (m_NorthingIncrement,resultUnitCode);
+    return northingIncrement;
 }
-double CCoordinateSystemGridSpecification::GetTickEastingIncrement(MgCoordinateSystem* gridCS)
+double CCoordinateSystemGridSpecification::GetTickEastingIncrement(INT32 resultUnitCode)
 {
-    INT32 gridUnitType;
-    INT32 gridCrsUnitCode;
-    double unitConversion;
+    double tickEastingIncrement;
 
-    Ptr<MgCoordinateSystemCatalog> catalogPtr = gridCS->GetCatalog ();
-    Ptr<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);
+    tickEastingIncrement = ConvertUnitsOfValue (m_TickEastingIncrement,resultUnitCode);
+    return tickEastingIncrement;
 }
-double CCoordinateSystemGridSpecification::GetTickNorthingIncrement(MgCoordinateSystem* gridCS)
+double CCoordinateSystemGridSpecification::GetTickNorthingIncrement(INT32 resultUnitCode)
 {
-    INT32 gridUnitType;
-    INT32 gridCrsUnitCode;
-    double unitConversion;
+    double tickNorthingIncrement;
 
-    Ptr<MgCoordinateSystemCatalog> catalogPtr = gridCS->GetCatalog ();
-    Ptr<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);
+    tickNorthingIncrement = ConvertUnitsOfValue (m_TickNorthingIncrement,resultUnitCode);
+    return tickNorthingIncrement;
 }
 double CCoordinateSystemGridSpecification::GetCurvePrecision (MgCoordinateSystem* gridCS)
 {
@@ -382,7 +237,7 @@
     // will convert meters to coordinate system units by multiplication.
     double csUnitConversion = 1.0 / gridCS->GetUnitScale ();
 
-    // If the curve precision has not been set by the user, this gets very easy.
+    // If the curve precision has not been set by the user, this is easy.
     if (m_CurvePrecision < 1.0E-24)     // i.e. == 0.0
     {
         precisionInMeters = m_DefaultPrecision;
@@ -401,13 +256,81 @@
         precisionInMeters = m_CurvePrecision * toMeters;
     }
     precisionInCsUnits = precisionInMeters * csUnitConversion;
-    return (precisionInCsUnits);
+    return precisionInCsUnits;
 }
+bool CCoordinateSystemGridSpecification::IsConsistent ()
+{
+    bool ok (false);
+    INT32 unitType (MgCoordinateSystemUnitType::Unknown);
+    MgCoordinateSystemFactory csFactory;
+    Ptr<MgCoordinateSystemCatalog> catalogPtr = csFactory.GetCatalog ();
+    Ptr<MgCoordinateSystemUnitInformation> unitInfoPtr = catalogPtr->GetUnitInformation ();
+
+    // Check that m_UnitCode is consistent with m_UnitType.
+    unitType = unitInfoPtr->GetUnitType (m_UnitCode);
+    ok = (unitType != MgCoordinateSystemUnitType::Unknown && m_UnitType == unitType);
+
+    // Currently, unitScale is not used.  It could very well be used in the
+    // future as part of a scheme to filter out bogus parameter values.  That
+    // was my intent when writing this code, but doing so implies that I
+    // make some assumtions about what is "normal" and what is not.
+    //if (ok)
+    //{
+    //    double unitScale (1.0);
+    //
+    //    // The following should never throw in this case as we have
+    //    // already validated the consistency of the m_UnitCode and
+    //    // m__UnitType members.
+    //    unitScale = unitInfoPtr->GetScale (m_UnitCode,m_UnitType);
+    //}
+
+    // Verify that the 6 basic parameters are all positive numbers, and
+    // non-zero as appropriate.
+    if (ok)
+    {
+        ok = (m_EastingBase >= 0.0) && (m_NorthingBase >= 0.0) &&
+             (m_EastingIncrement > 0.0) && (m_NorthingIncrement > 0.0) &&
+             (m_TickEastingIncrement > 0.0) && (m_TickNorthingIncrement > 0.0) &&
+             (m_CurvePrecision >= 0.0);
+    }
+
+    return ok;
+}
 void CCoordinateSystemGridSpecification::Dispose ()
 {
     delete this;
 }
+double CCoordinateSystemGridSpecification::ConvertUnitsOfValue (double value,INT32 trgUnitCode)
+{
+    INT32 trgUnitType;
+    double unitConversion;
 
+    MgCoordinateSystemFactory csFactory;
+    Ptr<MgCoordinateSystemCatalog> catalogPtr = csFactory.GetCatalog ();
+    Ptr<MgCoordinateSystemUnitInformation> unitInfoPtr = catalogPtr->GetUnitInformation ();
+    
+    // Verify that the unit type of the specification match the unit type
+    // to which we are to convert.
+    GetUnitInfo(trgUnitCode,&trgUnitType,NULL);
+    if (trgUnitType != m_UnitType)
+    {
+        throw new MgInvalidCoordinateSystemUnitsException(L"MgCoordinateSystemGridSpecification.ConvertUnitsOfValue", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
+    // Calculate the appropriate units conversion factor.  Since the unit types
+    // are the same, this should succeed without error.
+    if (m_UnitType == MgCoordinateSystemUnitType::Linear)
+    {
+        unitConversion = unitInfoPtr->GetLinearUnitScale (m_UnitCode) /
+                         unitInfoPtr->GetLinearUnitScale (trgUnitCode);
+    }
+    else
+    {
+        unitConversion = unitInfoPtr->GetAngularUnitScale (m_UnitCode) /
+                         unitInfoPtr->GetAngularUnitScale (trgUnitCode);
+    }
+    return (value * unitConversion);
+}
 ///////////////////////////////////////////////////////////////////////////////
 ///<summary>
 /// The boundary of the grid or graticule.  In the case of geographic
@@ -482,14 +405,13 @@
         collection->Add (nwPnt);
         collection->Add (clPnt);
 
-        MgLinearRing* ring = factory.CreateLinearRing (collection);
+        Ptr<MgLinearRing> ring = factory.CreateLinearRing (collection);
         if (ring == 0)
         {
             throw new MgOutOfMemoryException(L"MgCoordinateSystemGridBoundary.SetBoundaryExtents",
                                              __LINE__, __WFILE__, NULL, L"", NULL);
         }
         m_GridBoundary = factory.CreatePolygon (ring,NULL);
-        ring->Release ();
     MG_CATCH_AND_THROW(L"MgCoordinateSystemGridBoundary.SetBoundaryExtents")
 }
 void CCoordinateSystemGridBoundary::SetBoundaryExtents (MgPolygon* boundary)

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h	2009-10-15 22:24:21 UTC (rev 4298)
@@ -51,18 +51,27 @@
     void SetCurvePrecision (double curvePrecision);
 
     // The following function identically to the published version, with the
-    // exception that the value returned are always converted to the units of
-    // the provided coordinate system.
-    double GetEastingBase (MgCoordinateSystem* gridCS);
-    double GetNorthingBase (MgCoordinateSystem* gridCS);
-    double GetEastingIncrement(MgCoordinateSystem* gridCS);
-    double GetNorthingIncrement(MgCoordinateSystem* gridCS);
-    double GetTickEastingIncrement(MgCoordinateSystem* gridCS);
-    double GetTickNorthingIncrement(MgCoordinateSystem* gridCS);
+    // exception that the value returned is always converted to the units
+    // specified by the provided units code.
+    double GetEastingBase (INT32 resultUnitCode);
+    double GetNorthingBase (INT32 resultUnitCode);
+    double GetEastingIncrement (INT32 resultUnitCode);
+    double GetNorthingIncrement (INT32 resultUnitCode);
+    double GetTickEastingIncrement (INT32 resultUnitCode);
+    double GetTickNorthingIncrement (INT32 resultUnitCode);
+
+    // This ufnction will generate a suitable value if the host application
+    // left the curve precision unspecified.
     double GetCurvePrecision(MgCoordinateSystem* gridCS);
 
+    // The following is used by the CoordinateSystemFactory object to verify
+    // that all of the information provided to it is consistent with the
+    // requirements of the object.
+    bool IsConsistent (void);
+
 protected:
     void Dispose (void);
+    double ConvertUnitsOfValue (double value,INT32 trgUnitCode);
 
 private:
     double m_EastingBase;

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -261,10 +261,10 @@
                 return NULL;
             }
         }
-		else
-		{
-			return pLonLat;
-		}
+        else
+        {
+            return pLonLat;
+        }
     }
 
     //if exception mode is on and excetion is thrown internally we exit anyway
@@ -337,7 +337,7 @@
         {
             // Parameter error
         }
-    MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::GetGridLines")
+    MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::InitMgrsSpecification")
 }
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 INT32 CCoordinateSystemMgrs::GetSpecializationType ()
@@ -358,6 +358,8 @@
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 MgCoordinateSystemGridBoundary* CCoordinateSystemMgrs::GetBoundary(void)
 {
+    // The following code should return NULL if the boundary has not been set.
+    // That is the desired result.
     return SAFE_ADDREF (m_GridBoundary.p);
 }
 
@@ -373,6 +375,13 @@
     Ptr<MgCoordinateSystemGridLineCollection> aGridLineCollection;
     Ptr<CCoordinateSystemGridLineCollection> theGridLineCollection;
 
+    if (m_GridBoundary == 0)
+    {
+        // Proceeding without a grid boundary will cause a crash.
+        throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemMgrs.GetGridLines",
+                                                                   __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
     MG_TRY ()
         theGridLineCollection = new CCoordinateSystemGridLineCollection ();
         unitType = specification->GetUnitType();
@@ -418,6 +427,13 @@
     Ptr<CCoordinateSystemMgrsZone> mgrsZoneGrid;
     Ptr<CCoordinateSystemGridRegionCollection> theGridRegionCollection;
 
+    if (m_GridBoundary == 0)
+    {
+        // Proceeding without a grid boundary will cause a crash.
+        throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemMgrs.GetGridRegions",
+                                                                   __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
     MG_TRY ()
         theGridRegionCollection = new CCoordinateSystemGridRegionCollection ();
         zoneCount = m_ZoneCollection->GetCount ();
@@ -443,6 +459,13 @@
     Ptr<MgCoordinateSystemGridTickCollection> aGridTickCollection;
     Ptr<CCoordinateSystemGridTickCollection> theGridTickCollection;
 
+    if (m_GridBoundary == 0)
+    {
+        // Proceeding without a grid boundary will cause a crash.
+        throw new MgCoordinateSystemInitializationFailedException(L"MgCoordinateSystemMgrs.GetGridRegions",
+                                                                   __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
     MG_TRY ()
         theGridTickCollection = new CCoordinateSystemGridTickCollection ();
         unitType = specification->GetUnitType();
@@ -464,12 +487,12 @@
                 aGridTickCollection = m_GraticuleUtm->GetBoundaryTicks (specification);
                 theGridTickCollection->AddCollection (aGridTickCollection);
             }
-            else if (m_GraticuleUtm)
+            if (m_GraticuleUpsNorth)
             {
                 aGridTickCollection = m_GraticuleUpsNorth->GetBoundaryTicks (specification);
                 theGridTickCollection->AddCollection (aGridTickCollection);
             }
-            else if (m_GraticuleUtm)
+            if (m_GraticuleUpsSouth)
             {
                 aGridTickCollection = m_GraticuleUpsSouth->GetBoundaryTicks (specification);
                 theGridTickCollection->AddCollection (aGridTickCollection);
@@ -478,7 +501,7 @@
         // 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")
+    MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::GetGridTicks")
     return static_cast<MgCoordinateSystemGridTickCollection*>(theGridTickCollection.Detach());
 }
 
@@ -706,12 +729,34 @@
     Ptr<CCoordinateSystemMgrsZoneCollection> zoneCollection;
     STRING utmCsCode;
 
+    // Maintenance Note: reducedFrameBoundary has the following properties:
+    // 1> It is in frame (i.e. viewport) coordinates.
+    // 2> It starts out as a boundary which defines the entire UTM zone
+    //    (polar or otherwise) which is being created.
+    // 3> It is reduced, by "Intersection" with, to the extents of the
+    //    frame (i.e. viewport).
+    // You could also describe this as object as "That portion of the
+    // viewport which is included in the specific UTM zone we are
+    // constructing an object for".
+    
+    // Maintenance Note: In extreme cases, the use of rectangular viewports
+    // to model a spherical world can lead to the consideration of a zone which
+    // does not intersect the viewport.  In such cases, the Intersection polygon
+    // will be empty.  By MapGuide conventions, that means the pPolygonIntersection
+    // pointer will be null.  In this case, we must not add the zone to the zone
+    // collection.
+
     MG_TRY ()
         Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory ();
         zoneCollection = new CCoordinateSystemMgrsZoneCollection ();
         pSouthwest = new MgCoordinateXY ();
         pNortheast = new MgCoordinateXY ();
 
+        // Release any graticule objects which may already exist.
+        m_GraticuleUtm = 0;
+        m_GraticuleUpsNorth = 0;
+        m_GraticuleUpsSouth = 0;
+
         // Convert the polygon portion of the Grid Boundary object to long/lat
         // coordinates and extract the min/max from the resulting polygon.
         llCRS = csFactory->CreateFromCode (useFrameDatum ? L"LL" : L"LL84");
@@ -734,12 +779,15 @@
             pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
             Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
             pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
-            reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
-            mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
-            zoneCollection->Add (mgrsZoneGrid);
+            if (pPolygonIntersection != 0)
+            {
+                reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
+                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);
+                // Construct the m_GraticuleUpsSouth member, it may be needed.
+                m_GraticuleUpsSouth = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
+            }
         }
         if (northMax > 84.0)
         {
@@ -753,12 +801,15 @@
             pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
             Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
             pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
-            reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
-            mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
-            zoneCollection->Add (mgrsZoneGrid);
+            if (pPolygonIntersection != 0)
+            {
+                reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
+                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);
+                // Construct the m_GraticuleUpsNorth member, it may be needed.
+                m_GraticuleUpsNorth = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
+            }
         }
         if (northMax > -80.0 && northMin < 84.0)
         {
@@ -796,7 +847,7 @@
                     // 2> Apply the extents of the provided frame boundary.
                     if (westLimit < eastMin) westLimit = eastMin;
                     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);
@@ -804,14 +855,16 @@
 
                     // 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 (toFrameTransform,1.0);
                     Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
                     pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
-                    reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
-                    mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
-                    zoneCollection->Add (mgrsZoneGrid);
+                    if (pPolygonIntersection != 0)
+                    {
+                        reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
+                        mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
+                        zoneCollection->Add (mgrsZoneGrid);
+                    }
                  }
             }
             if (northMin < 0.0)
@@ -834,9 +887,12 @@
                     pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
                     Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
                     pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
-                    reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
-                    mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
-                    zoneCollection->Add (mgrsZoneGrid);
+                    if (pPolygonIntersection != 0)
+                    {
+                        reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
+                        mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
+                        zoneCollection->Add (mgrsZoneGrid);
+                    }
                 }
             }
 
@@ -848,10 +904,15 @@
             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);
+            Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
+            pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
+            if (pPolygonIntersection != 0)
+            {
+                reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
+                m_GraticuleUtm = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
+            }
         }
-    MG_CATCH_AND_THROW(L"MgCoordinateSystemOneGrid::GetGridLines")
+    MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::FrameBoundaryToZones")
     return zoneCollection.Detach ();
 }
 STRING CCoordinateSystemMgrs::GridSquareDesignation (INT32 utmZoneNbr,double easting,
@@ -912,11 +973,11 @@
 
     if (zoneNbr == 61)
     {
-        utmCode = L"UPS-N";
+        utmCode = L"WGS84.UPSNorth";
     }
     else if (zoneNbr == -61)
     {
-        utmCode = L"UPS-S";
+        utmCode = L"WGS84.UPSSouth";
     }
     else if (zoneNbr > 0 &&zoneNbr < 61)
     {

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -20,6 +20,7 @@
 #include "CoordSysUtil.h"       //for Convert_Wide_To_Ascii
 #include "CriticalSection.h"    //for SmartCriticalClass
 
+#include "Spatial/MathUtility.h"
 #include "CoordSysGrids.h"
 #include "CoordSysOneGrid.h"
 #include "CoordSysMgrsZone.h"
@@ -68,10 +69,31 @@
                                                        MgCoordinateSystemGridSpecification* specification)
 {
     double curvePrecision;
+    double eastingIncrement;
+    double northingIncrement;
 
     curvePrecision = specification->GetCurvePrecision ();
-    BuildMajorRegions (frameBoundary,curvePrecision);
-    BuildMinorRegions (frameBoundary,curvePrecision);
+
+    if (specification->GetUnitType () == MgCoordinateSystemUnitType::Angular)
+    {
+        eastingIncrement = specification->GetEastingIncrement (MgCoordinateSystemUnitCode::Degree);
+        northingIncrement = specification->GetNorthingIncrement (MgCoordinateSystemUnitCode::Degree);
+        if (MgMathUtility::DblCmp (eastingIncrement,6.0) &&
+            MgMathUtility::DblCmp (northingIncrement,8.0))
+        {
+            BuildMajorRegions (frameBoundary,curvePrecision);
+        }
+    }
+    else if (specification->GetUnitType () == MgCoordinateSystemUnitType::Linear)
+    {
+        eastingIncrement = specification->GetEastingIncrement (MgCoordinateSystemUnitCode::Meter);
+        northingIncrement = specification->GetNorthingIncrement (MgCoordinateSystemUnitCode::Meter);
+        if (MgMathUtility::DblCmp (eastingIncrement,100000.0) &&
+            MgMathUtility::DblCmp (northingIncrement,100000.0))
+        {
+            BuildMinorRegions (frameBoundary,curvePrecision);
+        }
+    }
 }
 void CCoordinateSystemMgrsZone::BuildMajorRegions (MgCoordinateSystemGridBoundary* frameBoundary,double curvePrecision)
 {
@@ -109,16 +131,22 @@
         toFrameTransform = csFactory.GetTransform(llCRS,frameCRS);
 
         // Major regions are solely a function of the extents of the grid in
-        // terms of geographic coordinates.  So, we extract the extents of the
+        // terms of geographic coordinates.  So, we extract the extents of this
         // grid in geographic coordinate form, and work from there.
         GetGeographicExtents (lngMin,lngMax,latMin,latMax);
 
         if ((m_UtmZone) != 0 && (abs (m_UtmZone) <= 60))
         {
-            utmZoneNbr = abs (m_UtmZone);
+            // Here for a normal (i.e. non-polar) UTM zone.  Use some asserts
+            // to verify the assumption here that the boundary for this zone
+            // does not extend into the polar regions.
+            assert (latMin >= -80.0);
+            assert (latMax <=  84.0);
+
             // The grid boundary may have been shrunk to the limits of the frame
             // boundary, so we'll recompute the appropriate minLng and maxLng from
             // the utmZoneNbr data member.
+            utmZoneNbr = abs (m_UtmZone);
             centralMeridian = static_cast<double>(-183 + (utmZoneNbr * 6));
             lngMin = centralMeridian - 3.0;
             lngMax = centralMeridian + 3.0;
@@ -131,11 +159,18 @@
             delta = fabs (fmod (latMax,8.0));
             lastLat = static_cast<INT32>(latMax + ((latMax >= 0.0) ? (8.0 - delta) : -delta));
 
-            for (latIdx = firstLat;latIdx < lastLat;latIdx += 8)
+            // While the normal UTM zones extend up to 84 degrees
+            // north latitude, the northernmost band (Band X) is
+            // 12 degrees high (72 to 84 degrees latitude).  So there
+            // is no band beginning at 80.
+            if (lastLat > 72)
             {
-                // TODO: Need to adjust the region boundaries to account for
-                // the screwy stuff which happens in southern Norway and the
-                // Svaldberg Islands.
+                lastLat = 72;
+            }
+
+            for (latIdx = firstLat;latIdx <= lastLat;latIdx += 8)
+            {
+                // Calculate the envelope of the normal UTM zone.
                 latMin = static_cast<double>(latIdx);
                 latMax = latMin + 8.0;
                 southwest->SetX (lngMin);
@@ -143,6 +178,66 @@
                 northeast->SetX (lngMax);
                 northeast->SetY (latMax);
 
+                // Band X (72 thru 84 north latitude includes 12 degrees of
+                // latitude.  Also, in this band, zones 32, 34, and 36 do not exist.
+                // and zones 31, 33, 35, and 37 have non-standard widths.  We
+                // adjust for all that now.
+                if (latIdx == 72)
+                {
+                    if (m_UtmZone == 32 || m_UtmZone == 34 || m_UtmZone == 36)
+                    {
+                        // These are regions which do not exist.
+                        continue;
+                    }
+
+                    // For all other regions in this band, the "height" is
+                    // 12 degrees.
+                    latMin = static_cast<double>(latIdx);
+                    latMax = latMin + 12.0;
+
+                    // There are two zones which are 9 degrees wide, and two that are
+                    // 12 degrees wide in this band.
+                    if (m_UtmZone == 31)
+                    {
+                        lngMin = centralMeridian - 3.0;
+                        lngMax = centralMeridian + 6.0;
+                    }
+                    else if (m_UtmZone == 33 || m_UtmZone == 35)
+                    {
+                        lngMin = centralMeridian - 6.0;
+                        lngMax = centralMeridian + 6.0;
+                    }
+                    else if (m_UtmZone == 37)
+                    {
+                        lngMin = centralMeridian - 6.0;
+                        lngMax = centralMeridian + 3.0;
+                    }
+                    southwest->SetX (lngMin);
+                    southwest->SetY (latMin);
+                    northeast->SetX (lngMax);
+                    northeast->SetY (latMax);
+                }
+
+                // One more kludge.  The following is necessary for a specific
+                // region south east of Norway.
+                if ((latIdx == 56) && (m_UtmZone == 31 || m_UtmZone == 32))
+                {
+                    if (m_UtmZone == 31)
+                    {
+                        lngMin = centralMeridian - 3.0;
+                        lngMax = centralMeridian;
+                    }
+                    else if (m_UtmZone == 32)
+                    {
+                        lngMin = centralMeridian - 6.0;
+                        lngMax = centralMeridian + 3.0;
+                    }
+                    southwest->SetX (lngMin);
+                    southwest->SetY (latMin);
+                    northeast->SetX (lngMax);
+                    northeast->SetY (latMax);
+                }
+
                 // We have the polygon, we need the designation.
                 gridZoneIndex = CCoordinateSystemMgrs::GridZoneDesignationIndex (latMin + 1.0,centralMeridian);
                 gridZoneLetter = CCoordinateSystemMgrs::GridZoneDesignationLetter (gridZoneIndex);

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -116,7 +116,8 @@
 }
 MgCoordinateSystemGridLineCollection* CCoordinateSystemOneGrid::GetGridLines (MgCoordinateSystemGridSpecification* specs)
 {
-    INT32 lineStringCount;
+    INT32 gridCrsUnitCode;
+
     double value;
     double delta;
     double increment;
@@ -134,6 +135,8 @@
     Ptr<CCoordinateSystemGridLineCollection> gridLineCollection = new CCoordinateSystemGridLineCollection ();
 
     MG_TRY()
+        gridCrsUnitCode = m_GridCRS->GetUnitCode ();
+
         CCoordinateSystemGridSpecification* mySpecPtr = dynamic_cast<CCoordinateSystemGridSpecification*>(specs);
         coordinate = new MgCoordinateXY ();
         fromPnt    = new MgCoordinateXY ();
@@ -158,13 +161,13 @@
         // 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);
+        increment = mySpecPtr->GetEastingIncrement(gridCrsUnitCode);
         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 = mySpecPtr->GetNorthingIncrement(m_GridCRS);
+        increment = mySpecPtr->GetNorthingIncrement(gridCrsUnitCode);
         delta = fabs(fmod (northMin,increment));
         northMin -= (northMin >= 0.0) ? delta : (increment - delta);
         delta = fabs(fmod (northMax,increment));
@@ -173,15 +176,15 @@
         // Adjust for the base.  Again, we always enlarge, never shrink.
         if (mySpecPtr->GetEastingBase () > 0.0)
         {
-            increment = mySpecPtr->GetEastingIncrement (m_GridCRS);
-            delta = fmod (mySpecPtr->GetEastingBase(m_GridCRS),increment);
+            increment = mySpecPtr->GetEastingIncrement (gridCrsUnitCode);
+            delta = fmod (mySpecPtr->GetEastingBase(gridCrsUnitCode),increment);
             eastMin  += delta - increment;
             eastMax  += delta + increment;
         }
         if (mySpecPtr->GetNorthingBase () > 0.0)
         {
-            increment = mySpecPtr->GetNorthingIncrement (m_GridCRS);
-            delta = fmod (mySpecPtr->GetNorthingBase(m_GridCRS),increment);
+            increment = mySpecPtr->GetNorthingIncrement (gridCrsUnitCode);
+            delta = fmod (mySpecPtr->GetNorthingBase(gridCrsUnitCode),increment);
             northMin  += delta - increment;
             northMax  += delta + increment;
         }
@@ -189,7 +192,7 @@
         // Given the specification, we double loop, generating lines.
         // Forst loop, generatinf west/east lines starting at the southern edge
         // proceeding to the north.
-        increment = mySpecPtr->GetNorthingIncrement (m_GridCRS);
+        increment = mySpecPtr->GetNorthingIncrement (gridCrsUnitCode);
         for (value = northMin;value <= northMax;value += increment)
         {
             fromPnt->SetX (eastMin);
@@ -197,13 +200,12 @@
             toPnt->SetX (eastMax);
             toPnt->SetY (value);
             lineString = m_ToFrameXform->GridLine (fromPnt,toPnt,precision,m_MaxCurvePoints);
-            
+
             // Clip the line to the frame boundary.  The grid line may
             // actually leave, and then reenter, the grid boundary, so the
             // result can be a multi-line sting.
             lineStringCollection = m_FrameBoundary->ClipLineString (lineString);
-            lineStringCount = lineStringCollection->GetCount ();
-            if (lineStringCount > 0)
+            if (lineStringCollection)
             {
                 // Construct the Grid Line object and add it to the grid
                 // line collection object.
@@ -215,7 +217,7 @@
 
         // Second loop, the south/north lines, starting at the western edge
         // proceeding to the east.
-        increment = mySpecPtr->GetEastingIncrement (m_GridCRS);
+        increment = mySpecPtr->GetEastingIncrement (gridCrsUnitCode);
         for (value = eastMin;value <= eastMax;value += increment)
         {
             fromPnt->SetX (value);
@@ -228,8 +230,7 @@
             // actually leave, and then re-enter, the grid boundary, so the
             // result can be a multi-line string.
             lineStringCollection = m_FrameBoundary->ClipLineString (lineString);
-            lineStringCount = lineStringCollection->GetCount ();
-            if (lineStringCount > 0)
+            if (lineStringCollection)
             {
                 // Construct the Grid Line object and add it to the grid
                 // line collection object.
@@ -248,6 +249,7 @@
 
     INT32 status;
     INT32 orientation;
+    INT32 gridCrsUnitCode;
 
     double tmpDbl;
     double delta;
@@ -269,7 +271,9 @@
     MgGeometryFactory mgFactory;
 
     MG_TRY ()
-    
+
+        gridCrsUnitCode = m_GridCRS->GetUnitCode ();
+
         CCoordinateSystemGridSpecification* mySpecPtr = dynamic_cast<CCoordinateSystemGridSpecification*>(specs);
         tickCollection = new CCoordinateSystemGridTickCollection ();
 
@@ -279,13 +283,13 @@
 
         // Expand the extents to become the lowest and highest tick values
         // for each of the ordinates.
-        increment = mySpecPtr->GetTickEastingIncrement(m_GridCRS);
+        increment = mySpecPtr->GetTickEastingIncrement(gridCrsUnitCode);
         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 = mySpecPtr->GetTickNorthingIncrement(m_GridCRS);
+        increment = mySpecPtr->GetTickNorthingIncrement(gridCrsUnitCode);
         delta = fabs(fmod (northMin,increment));
         northMin -= (northMin >= 0.0) ? delta : (increment - delta);
         delta = fabs(fmod (northMax,increment));
@@ -294,15 +298,15 @@
         // Adjust for the base.  Again, we always enlarge, never shrink.
         if (mySpecPtr->GetEastingBase () > 0.0)
         {
-            increment = mySpecPtr->GetEastingIncrement (m_GridCRS);
-            delta = fmod (mySpecPtr->GetEastingBase(m_GridCRS),increment);
+            increment = mySpecPtr->GetEastingIncrement (gridCrsUnitCode);
+            delta = fmod (mySpecPtr->GetEastingBase(gridCrsUnitCode),increment);
             eastMin  += delta - increment;
             eastMax  += delta + increment;
         }
         if (mySpecPtr->GetNorthingBase () > 0.0)
         {
-            increment = mySpecPtr->GetNorthingIncrement (m_GridCRS);
-            delta = fmod (mySpecPtr->GetNorthingBase(m_GridCRS),increment);
+            increment = mySpecPtr->GetNorthingIncrement (gridCrsUnitCode);
+            delta = fmod (mySpecPtr->GetNorthingBase(gridCrsUnitCode),increment);
             northMin  += delta - increment;
             northMax  += delta + increment;
         }
@@ -323,7 +327,7 @@
 
             // Do the easting ticks; that is tickmarks whose value is an
             // easting ordinate value.
-            increment = mySpecPtr->GetTickEastingIncrement (m_GridCRS);
+            increment = mySpecPtr->GetTickEastingIncrement (gridCrsUnitCode);
             orientation = MgCoordinateSystemGridOrientation::EastWest;
             for (ordinateValue = eastMin;ordinateValue <= eastMax;ordinateValue += increment)
             {
@@ -355,7 +359,7 @@
 
             // Do the northing ticks; that is tickmarks whose value is an
             // northing ordinate value.
-            increment = mySpecPtr->GetTickNorthingIncrement (m_GridCRS);
+            increment = mySpecPtr->GetTickNorthingIncrement (gridCrsUnitCode);
             orientation = MgCoordinateSystemGridOrientation::NorthSouth;
             for (ordinateValue = northMin;ordinateValue <= northMax;ordinateValue += increment)
             {
@@ -462,50 +466,3 @@
 {
     delete this;
 }
-#pragma message ("Remove this code before code complete.")
-//=============================================================================
-// This object was invented to carry multiple MGRS grids, but is no longer used
-// as there is now a CCoordinateSystemMgrsZone object and a related collection
-// object.  When we're ready for code complete and we don't seem to need this
-// for anything, we should delete it. 
-CCoordinateSystemGridCollection::CCoordinateSystemGridCollection (void)
-                                        :
-                                     MgGuardDisposable   (),
-                                     m_OneGridCollection ()
-{
-    m_OneGridCollection = new MgDisposableCollection();
-}
-CCoordinateSystemGridCollection::~CCoordinateSystemGridCollection (void)
-{
-    m_OneGridCollection->Clear ();
-}
-INT32 CCoordinateSystemGridCollection::GetCount () const
-{
-    INT32 itemCount = m_OneGridCollection->GetCount ();
-    return itemCount;
-}
-CCoordinateSystemOneGrid* CCoordinateSystemGridCollection::GetItem (INT32 index) const
-{
-    CCoordinateSystemOneGrid *itemPtr = static_cast<CCoordinateSystemOneGrid*>(m_OneGridCollection->GetItem (index));
-    return itemPtr;
-}
-void CCoordinateSystemGridCollection::RemoveAt (INT32 index)
-{
-    m_OneGridCollection->RemoveAt (index);
-}
-void CCoordinateSystemGridCollection::Clear()
-{
-    m_OneGridCollection->Clear ();
-}
-void CCoordinateSystemGridCollection::SetItem (INT32 index, CCoordinateSystemOneGrid* value)
-{
-    m_OneGridCollection->SetItem (index,value);
-}
-void CCoordinateSystemGridCollection::Add (CCoordinateSystemOneGrid* value)
-{
-    m_OneGridCollection->Add (value);
-}
-void CCoordinateSystemGridCollection::Dispose (void)
-{
-    delete this;
-}

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.h	2009-10-15 22:24:21 UTC (rev 4298)
@@ -83,7 +83,7 @@
     Ptr<MgCoordinateSystem> m_FrameCRS;                  // The frame coordinate system
     Ptr<MgCoordinateSystemTransform> m_ToFrameXform;     // Converts grid coordinates to frame coordinates
     Ptr<MgCoordinateSystemTransform> m_ToGridXform;      // Converts frame coordinates to grid coordinates
-    double m_BoundaryPrecision;                          // Precision at which the boundary conversion was perfromed
+    double m_BoundaryPrecision;                          // Precision at which the boundary conversion was performed
     Ptr<MgCoordinateSystemGridBoundary> m_FrameBoundary; // Grid boundary in frame coordinates
     Ptr<MgCoordinateSystemGridBoundary> m_GridBoundary;  // Grid boundary in grid coordinates
 
@@ -93,36 +93,6 @@
     CCoordinateSystemOneGrid& operator= (const CCoordinateSystemOneGrid& rhs);
 };
 
-//=============================================================================
-// This object was invented to carry multiple MGRS grids, but is no longer used
-// as there is now a CCoordinateSystemMgrsZone object and a related collection
-// object.  WHen we're ready for code complete and we don't seem to need this
-// for anything, we should delete it. 
-class CCoordinateSystemGridCollection : public MgGuardDisposable
-{
-public:
-    CCoordinateSystemGridCollection (void);
-    ~CCoordinateSystemGridCollection (void);
-
-    INT32 GetCount () const;
-    CCoordinateSystemOneGrid* GetItem (INT32 index) const;
-    void RemoveAt (INT32 index);
-    void Clear();
-    void SetItem (INT32 index, CCoordinateSystemOneGrid* value);
-    void Add (CCoordinateSystemOneGrid* value);
-
-protected:
-    void Dispose (void);
-
-private:
-    // Data Members
-    Ptr<MgDisposableCollection> m_OneGridCollection;
-
-    // Member functions not implemented.
-    CCoordinateSystemGridCollection  (const CCoordinateSystemGridCollection & source);
-    CCoordinateSystemGridCollection& operator= (const CCoordinateSystemGridCollection & rhs);
-};
-
 }   /* namespace CSLibrary */
 
 #endif /* _CCOORDINATESYSTEMGRIDBASE_H_ */

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -1046,7 +1046,7 @@
 
     Ptr<MgCoordinateCollection> coordinateCollection;
     Ptr<MgLineString> lineString;
-    
+
     struct rx_Linseg_
     {
         struct rx_Linseg_ *next;
@@ -1070,126 +1070,127 @@
     double midSrcX, midSrcY;
     double midTrgX, midTrgY;
 
-//TODO: This algorithm calls Transform, which can and does throw.  There are no provisions for this in this algorithm.
+    MG_TRY()
 
-    chord2 = curvePrecision * curvePrecision;
+        chord2 = curvePrecision * curvePrecision;
 
-    // Allocate and populate the first point in the segment list.
-    segList = new rx_Linseg_;
-    segList->next = NULL;
+        // Allocate and populate the first point in the segment list.
+        segList = new rx_Linseg_;
+        segList->next = NULL;
 
-    wrkPntX = segList->srcX = segList->trgX = fromPnt->GetX ();
-    wrkPntY = segList->srcY = segList->trgY = fromPnt->GetY ();
-    Transform (&segList->trgX,&segList->trgY);
+        wrkPntX = segList->srcX = segList->trgX = fromPnt->GetX ();
+        wrkPntY = segList->srcY = segList->trgY = fromPnt->GetY ();
+        Transform (&segList->trgX,&segList->trgY);
 
-    // Allocate and populate the last point in the segment list.
-    curPtr = new rx_Linseg_;
-    curPtr->next = NULL;
-    segList->next = curPtr;
+        // Allocate and populate the last point in the segment list.
+        curPtr = new rx_Linseg_;
+        curPtr->next = NULL;
+        segList->next = curPtr;
 
-    wrkPntX = curPtr->srcX = curPtr->trgX = toPnt->GetX ();
-    wrkPntY = curPtr->srcY = curPtr->trgY = toPnt->GetY ();
-    Transform (&curPtr->trgX,&curPtr->trgY);
+        wrkPntX = curPtr->srcX = curPtr->trgX = toPnt->GetX ();
+        wrkPntY = curPtr->srcY = curPtr->trgY = toPnt->GetY ();
+        Transform (&curPtr->trgX,&curPtr->trgY);
 
-    // We now have the two end points of the line in the segment list.  Start a
-    // loop which will examine the segment list and add points where necessary
-    // to make sure the chord distance from the real point to the segment point
-    // is less than that required.
-    segCnt = 2;
-    do
-    {
-        // Loop through the list and bisect each segment as appropriate.
-        curPtr = segList;
-        maxChord = 0.0;
+        // We now have the two end points of the line in the segment list.  Start a
+        // loop which will examine the segment list and add points where necessary
+        // to make sure the chord distance from the real point to the segment point
+        // is less than that required.
+        segCnt = 2;
         do
         {
-            // Compute the midpoint of the segment in lin coordinates.
-            delX = curPtr->next->srcX - curPtr->srcX;
-            delY = curPtr->next->srcY - curPtr->srcY;
-            midTrgX = midSrcX = curPtr->srcX + delX * 0.5;
-            midTrgY = midSrcY = curPtr->srcY + delY * 0.5;
-            Transform (&midTrgX,&midTrgY);
+            // Loop through the list and bisect each segment as appropriate.
+            curPtr = segList;
+            maxChord = 0.0;
+            do
+            {
+                // Compute the midpoint of the segment in lin coordinates.
+                delX = curPtr->next->srcX - curPtr->srcX;
+                delY = curPtr->next->srcY - curPtr->srcY;
+                midTrgX = midSrcX = curPtr->srcX + delX * 0.5;
+                midTrgY = midSrcY = curPtr->srcY + delY * 0.5;
+                Transform (&midTrgX,&midTrgY);
 
-            // Compute the distance from the converted point to the line, doing all
-            // of this in dwg coordinates.  The result is the chord distance.
-            // The following algorithm was derived from taking the intersection of a
-            // line from the converted point perdendicular to the existing line.
-            delX = curPtr->next->trgX - curPtr->trgX;
-            delY = curPtr->next->trgY - curPtr->trgY;
-            delX2 = delX * delX;
-            delY2 = delY * delY;
-            denom = delX2 + delY2;
+                // Compute the distance from the converted point to the line, doing all
+                // of this in dwg coordinates.  The result is the chord distance.
+                // The following algorithm was derived from taking the intersection of a
+                // line from the converted point perdendicular to the existing line.
+                delX = curPtr->next->trgX - curPtr->trgX;
+                delY = curPtr->next->trgY - curPtr->trgY;
+                delX2 = delX * delX;
+                delY2 = delY * delY;
+                denom = delX2 + delY2;
 
-            // Make sure we don't divide by zero.  denom is the sum of two
-            // squares, so it can't be negative.
-            if (denom > 0.0)
-            {
-                num = (delX2 * midTrgX) + (delY2 * curPtr->trgX) +
-                      (midTrgY - curPtr->trgY) * delX * delY;
-                newX = num / denom;
-                num = (delY2 * midTrgY) + (delX2 * curPtr->trgY) +
-                      (midTrgX - curPtr->trgX) * delX * delY;
-                newY = num / denom;
-                delX = newX - midTrgX;
-                delY = newY - midTrgY;
-                dist2 = delX * delX + delY * delY;
-            }
-            else
-            {
-                // This is overkill unless the drawing units are lat/longs or something
-                // else that is very weird.
-                delX = curPtr->trgX - midTrgX;
-                delY = curPtr->trgY - midTrgY;
-                dist2 = delX * delX + delY * delY;
-            }
+                // Make sure we don't divide by zero.  denom is the sum of two
+                // squares, so it can't be negative.
+                if (denom > 0.0)
+                {
+                    num = (delX2 * midTrgX) + (delY2 * curPtr->trgX) +
+                          (midTrgY - curPtr->trgY) * delX * delY;
+                    newX = num / denom;
+                    num = (delY2 * midTrgY) + (delX2 * curPtr->trgY) +
+                          (midTrgX - curPtr->trgX) * delX * delY;
+                    newY = num / denom;
+                    delX = newX - midTrgX;
+                    delY = newY - midTrgY;
+                    dist2 = delX * delX + delY * delY;
+                }
+                else
+                {
+                    // This is overkill unless the drawing units are lat/longs or something
+                    // else that is very weird.
+                    delX = curPtr->trgX - midTrgX;
+                    delY = curPtr->trgY - midTrgY;
+                    dist2 = delX * delX + delY * delY;
+                }
 
-            // Accumulate the maximum chord distance so that we know when we are done.
-            if (dist2 > maxChord) maxChord = dist2;
+                // Accumulate the maximum chord distance so that we know when we are done.
+                if (dist2 > maxChord) maxChord = dist2;
 
-            // If the chord distance (it's not really a chord, but I don't know what
-            // the real name of this thing is) is greater than the requested maximum,
-            // we bisect this line segment.
-            if (dist2 > chord2)
-            {
-                // Allocate a new segment structure.
-                nxtPtr = new rx_Linseg_;
-                nxtPtr->next = NULL;
+                // If the chord distance (it's not really a chord, but I don't know what
+                // the real name of this thing is) is greater than the requested maximum,
+                // we bisect this line segment.
+                if (dist2 > chord2)
+                {
+                    // Allocate a new segment structure.
+                    nxtPtr = new rx_Linseg_;
+                    nxtPtr->next = NULL;
 
-                // Insert the computed mid point.  We have both the dwg and lin values
-                // available.
-                nxtPtr->trgX = midTrgX;
-                nxtPtr->trgY = midTrgY;
-                nxtPtr->srcX = midSrcX;
-                nxtPtr->srcY = midSrcY;
+                    // Insert the computed mid point.  We have both the dwg and lin values
+                    // available.
+                    nxtPtr->trgX = midTrgX;
+                    nxtPtr->trgY = midTrgY;
+                    nxtPtr->srcX = midSrcX;
+                    nxtPtr->srcY = midSrcY;
 
-                // Count this point.
-                segCnt += 1;
+                    // Count this point.
+                    segCnt += 1;
 
-                // Link this point into the list.
-                nxtPtr->next = curPtr->next;
-                curPtr->next = nxtPtr;
+                    // Link this point into the list.
+                    nxtPtr->next = curPtr->next;
+                    curPtr->next = nxtPtr;
 
-                // Move on to the next segment.
-                curPtr = nxtPtr->next;
-            }
-            else
-            {
-                // Move on to the next segment.
-                curPtr = curPtr->next;
-            }
-        } while (curPtr->next != NULL);
-    } while (maxChord > chord2 && segCnt < maxPoints);
+                    // Move on to the next segment.
+                    curPtr = nxtPtr->next;
+                }
+                else
+                {
+                    // Move on to the next segment.
+                    curPtr = curPtr->next;
+                }
+            } while (curPtr->next != NULL);
+        } while (maxChord > chord2 && segCnt < maxPoints);
 
-    // Add all of our dwg points to the provided point array.
-    coordinateCollection = new MgCoordinateCollection ();
-    for (curPtr = segList;curPtr != NULL;curPtr = curPtr->next)
-    {
-        MgCoordinate* pntPtr = factory.CreateCoordinateXY (curPtr->trgX,curPtr->trgY);
-        coordinateCollection->Add (pntPtr);
-        pntPtr->Release ();
-    }
-    lineString = factory.CreateLineString (coordinateCollection);
+        // Add all of our dwg points to the provided point array.
+        coordinateCollection = new MgCoordinateCollection ();
+        for (curPtr = segList;curPtr != NULL;curPtr = curPtr->next)
+        {
+            Ptr<MgCoordinate> pntPtr = factory.CreateCoordinateXY (curPtr->trgX,curPtr->trgY);
+            coordinateCollection->Add (pntPtr);
+        }
+        lineString = factory.CreateLineString (coordinateCollection);
 
+    MG_CATCH (L"MgCoordinateSystemTransform.GridLine")
+
     // Release all resources.
     curPtr = segList;
     while (curPtr != NULL)
@@ -1198,6 +1199,9 @@
         delete curPtr;
         curPtr = nxtPtr;
     }
+    
+    MG_THROW ()
+
     return lineString.Detach ();
 }
 // Returns integer status, two values currently supported.  Zero return
@@ -1239,7 +1243,9 @@
         }
         else
         {
-            // TODO: Parameter error.
+            // Invalid argument value.
+            throw new MgInvalidArgumentException(L"MgCoordinateSystemTransform.PositionOfValue",
+                                                 __LINE__, __WFILE__, NULL, L"", NULL);
         }
         if (minValue > maxValue)
         {
@@ -1265,6 +1271,7 @@
         {
             deltaX = gridTo->GetX () - gridFrom->GetX ();
             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) ||
@@ -1277,13 +1284,14 @@
                 xx = gridFrom->GetX () + deltaX * ratio;
                 yy = gridFrom->GetY () + deltaY * ratio;
 
-                // This object does not, currently, support this inverse
-                // function.  It does, however, have all the information
-                // necessary to support one.  So, next on the TODO list is
-                // to write a private TransformInverse function.
+                // This member function was added as a private member as part
+                // of the RFC #76 development effort.  All the information to
+                // perform this functyion is present in this object.  It was
+                // made private as to do otherwise would change the public API,
+                // a change which was not approved as part of the RFC.
                 TransformInverse (xx,yy);
 
-                // Frame temp is now an approximation (usually a pretty good
+                // xx and yy are now an approximation (usually a pretty good
                 // one) of the position of the provided ordinate value on the
                 // provided line in frame corodinates.  We _could_ tighten this
                 // up a little but here; but for know we'll just go with this
@@ -1458,6 +1466,10 @@
         throw new MgCoordinateSystemConversionFailedException(L"MgCoordinateSystemTransform.TransformPointInternal", __LINE__, __WFILE__, NULL, L"MgCoordinateSystemConversionExtentException", NULL);
     }
 }
+
+// Essentially the inverse of the Transform (double& xx,double& yy) function.
+// This is a private function used to greatly enhance the performance of the
+// PositionOfValue function defined above.
 int CCoordinateSystemTransform::TransformInverse (double& xx,double& yy)
 {
     int st;

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysTransform.h	2009-10-15 22:24:21 UTC (rev 4298)
@@ -293,6 +293,8 @@
 
     inline void TransformPointInternal(double& x, double& y, double *pdZ, bool isGeographic,
         double lonMin, double lonMax, double latMin, double latMax);
+
+    // Private function required to support the PositionOfValue function.
     int TransformInverse (double& xx,double& yy);
 };
 

Modified: trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemFactory.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -581,13 +581,17 @@
         gridSpecification = new CCoordinateSystemGridSpecification ();
         if (gridSpecification != NULL)
         {
-            // TODO:  modify CCoordinateSystemGridSpecification to check
-            // all the parameters added and throw an exception if an error.
             gridSpecification->SetGridBase (0.0,0.0);
             gridSpecification->SetGridIncrement (increment,increment);
             gridSpecification->SetGridIncrement (tickIncrement,tickIncrement);
             gridSpecification->SetUnits (unitCode,MgCoordinateSystemUnitType::Linear);
             gridSpecification->SetCurvePrecision (curvePrecision);
+
+            // Check the consistency of all these parameters.
+            if (!gridSpecification->IsConsistent ())
+            {
+                throw new MgInvalidArgumentException(L"MgCoordinateSystemFactory.GridSpecification", __LINE__, __WFILE__, NULL, L"", NULL);
+            }
         }
     MG_CATCH_AND_THROW(L"MgCoordinateSystemFactory.GridSpecification")
     return gridSpecification.Detach ();

Modified: trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h
===================================================================
--- trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/Geometry/CoordinateSystem/CoordinateSystemGrids.h	2009-10-15 22:24:21 UTC (rev 4298)
@@ -520,81 +520,148 @@
     ///
     virtual void SetCurvePrecision (double curvePrecision) = 0;
 
+    ///////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Checks the internal contents of the object for consistency.
+    ///
+    /// <!-- Syntax in .Net, Java, and PHP -->
+    /// \htmlinclude DotNetSyntaxTop.html
+    /// virtual bool IsConsistent ();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude JavaSyntaxTop.html
+    /// virtual bool IsConsistent ();
+    /// \htmlinclude SyntaxBottom.html
+    /// \htmlinclude PHPSyntaxTop.html
+    /// virtual bool IsConsistent ();
+    /// \htmlinclude SyntaxBottom.html
+    ///
+    /// \return
+    /// returns true if the values set are consistent with a valid
+    /// specification block.
+    ///
+    /// \remarks
+    /// Will not throw.
+    virtual bool IsConsistent (void) = 0;
+
 INTERNAL_API:
     ///////////////////////////////////////////////////////////////////////////
     /// \brief
     /// Returns the easting base value after conversion from the units
-    /// of this specification object to the units of the provided coordinate
-    /// system.
+    /// of this specification object to the units requested by the argument.
     ///
-    /// \param gridCRS
-    /// The return value is converted to the units of this coordinate system.
+    /// \param resultUnitCode
+    /// The return value is converted to the units indicated by this unit
+    /// code.
     ///
     /// \return
-    /// Easting base value in units of the provided coordinate system.
+    /// Easting base value in units indicated by the resultUnitCode
+    /// parameter.
     ///
     /// \exception
     /// Will throw if the unit types of this specification and the provided
-    /// coordinate system are not the same.
+    /// argument are not the same.
     ///
-    virtual double GetEastingBase (MgCoordinateSystem* gridCRS)=0;
+    virtual double GetEastingBase (INT32 resultUnitCode)=0;
 
     ///////////////////////////////////////////////////////////////////////////
     /// \brief
     /// Returns the northing base value after conversion from the units
-    /// of this specification object to the units of the provided coordinate
-    /// system.
+    /// of this specification object to the units requested by the argument.
     ///
-    /// \param gridCRS
-    /// The return value is converted to the units of this coordinate system.
+    /// \param resultUnitCode
+    /// The return value is converted to the units indicated by this unit
+    /// code.
     ///
     /// \return
-    /// Northing base value in units of the provided coordinate system.
+    /// Northing base value in units indicated by the resultUnitCode
+    /// parameter.
     ///
     /// \exception
     /// Will throw if the unit types of this specification and the provided
-    /// coordinate system are not the same.
+    /// argument are not the same.
     ///
-    virtual double GetNorthingBase (MgCoordinateSystem* gridCRS)=0;
+    virtual double GetNorthingBase (INT32 resultUnitCode)=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.
+    /// Returns the easting increment value after conversion from the units
+    /// of this specification object to the units requested by the argument.
     ///
-    /// \param gridCRS
-    /// The return value is converted to the units of this coordinate system.
+    /// \param resultUnitCode
+    /// The return value is converted to the units indicated by this unit
+    /// code.
     ///
     /// \return
-    /// Easting grid increment value in units of the provided coordinate system.
+    /// Easting increment value in units indicated by the resultUnitCode
+    /// parameter.
     ///
     /// \exception
     /// Will throw if the unit types of this specification and the provided
-    /// coordinate system are not the same.
+    /// argument are not the same.
     ///
-    virtual double GetEastingIncrement (MgCoordinateSystem* gridCRS)=0;
+    virtual double GetEastingIncrement (INT32 resultUnitCode)=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.
+    /// Returns the northing increment value after conversion from the units
+    /// of this specification object to the units requested by the argument.
     ///
-    /// \param gridCRS
-    /// The return value is converted to the units of this coordinate system.
+    /// \param resultUnitCode
+    /// The return value is converted to the units indicated by this unit
+    /// code.
     ///
     /// \return
-    /// Northing grid increment value in units of the provided coordinate system.
+    /// Northing increment value in units indicated by the resultUnitCode
+    /// parameter.
     ///
     /// \exception
     /// Will throw if the unit types of this specification and the provided
-    /// coordinate system are not the same.
+    /// argument are not the same.
     ///
-    virtual double GetNorthingIncrement (MgCoordinateSystem* gridCRS)=0;
+    virtual double GetNorthingIncrement (INT32 resultUnitCode)=0;
 
     ///////////////////////////////////////////////////////////////////////////
     /// \brief
+    /// Returns the tick easting increment value after conversion from the
+    /// units of this specification object to the units requested by the
+    /// argument.
+    ///
+    /// \param resultUnitCode
+    /// The return value is converted to the units indicated by this unit
+    /// code.
+    ///
+    /// \return
+    /// Tick easting increment value in units indicated by the
+    /// resultUnitCode parameter.
+    ///
+    /// \exception
+    /// Will throw if the unit types of this specification and the provided
+    /// argument are not the same.
+    ///
+    virtual double GetTickEastingIncrement (INT32 resultUnitCode)=0;
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// \brief
+    /// Returns the tick northing increment value after conversion from the
+    /// units of this specification object to the units requested by the
+    /// argument.
+    ///
+    /// \param resultUnitCode
+    /// The return value is converted to the units indicated by this unit
+    /// code.
+    ///
+    /// \return
+    /// Tick northing increment value in units indicated by the
+    /// resultUnitCode parameter.
+    ///
+    /// \exception
+    /// Will throw if the unit types of this specification and the provided
+    /// argument are not the same.
+    ///
+    virtual double GetTickNorthingIncrement (INT32 resultUnitCode)=0;
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// \brief
     /// Returns the curve precision value after conversion from the units
     /// of this specification object to the units of the provided coordinate
     /// system.

Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp	2009-10-15 19:52:07 UTC (rev 4297)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp	2009-10-15 22:24:21 UTC (rev 4298)
@@ -762,7 +762,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 /// <summary>
 /// Returns a collection of line strings which represents those portions of the
-/// provided line string which are inside of the provided closed ring.
+/// provided line string which are inside of the provided closed ring.  The null
+/// pointer is returned rather than an empty line string.
 /// </summary>
 MgLineStringCollection* MgSpatialUtility::ClipStringToPolygon (MgCoordinateIterator* polyItr,
                                                                MgCoordinateIterator* lineItr)
@@ -774,7 +775,6 @@
     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.
@@ -801,7 +801,7 @@
 
     while (lineItr->MoveNext ())
     {
-        lineFrom = lineTo;              // TODO: does this work without screwing up the reference counts.
+        lineFrom = lineTo;
         lineTo = lineItr->GetCurrent ();
         
         // Intersect this segment with the polygon.
@@ -837,7 +837,7 @@
                     // 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);
+                    Ptr<MgLineString> newLineString = new MgLineString (curCollection);
                     lineCollection->Add (newLineString);
 
                     // Clear curCollection inpreparation for the nex segment if
@@ -857,6 +857,7 @@
                     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
@@ -874,15 +875,22 @@
             // 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.
+    // final line string in the line string collection.
     if (inside)
     {
+        Ptr<MgLineString> newLineString = new MgLineString (curCollection);
         lineCollection->Add (newLineString);
     }
-    
+
+    // Release the LineStringCollection object if it is empty.
+    if (lineCollection->GetCount () == 0)
+    {
+        lineCollection = 0;
+    }
+
     // Looks pretty simple, maybe that means it will work good; often does.
     return lineCollection.Detach ();
 }



More information about the mapguide-commits mailing list