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

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Nov 20 12:56:29 EST 2009


Author: NormOlsen
Date: 2009-11-20 12:56:28 -0500 (Fri, 20 Nov 2009)
New Revision: 4351

Added:
   trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.cpp
   trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.h
Modified:
   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/Geometry/Geometry.vcproj
   trunk/MgDev/Common/Geometry/Makefile.am
   trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
Log:
Major changes required to correct MapGuide Trac ticket number is 1156.  This all pertaining to RFC 76, Grids & Graticules and represents a major step closer to the actual completion of the implementation of the RFC.

Rigorous testing has shown that there were several erroneous grid line conditions in the generation of grid lines for the polar regions. These were caused by:

1> The original design of the Grid/Graticule sub-system did not properly recognize the spherical nature of coordinates at or near either pole.

2> The MGRS graticule boundary generator failed to recognize that the X Band of MGRS is 12 degrees of latitude high (unlike all others which are 8 degrees high).

3> The boundaries generated for the polar regions produced exceptional conditions which the line string/polygon clipper could not handle correctly.

4> The clipper would produce unexpected result in the case where a line would intersect the clipping polygon __exactly__ at a vertex point on the polygon.

These issues are addressed in this submission.  Note that this submission creates two new source code modules.

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.h	2009-11-20 17:56:28 UTC (rev 4351)
@@ -60,7 +60,7 @@
     double GetTickEastingIncrement (INT32 resultUnitCode);
     double GetTickNorthingIncrement (INT32 resultUnitCode);
 
-    // This ufnction will generate a suitable value if the host application
+    // This function will generate a suitable value if the host application
     // left the curve precision unspecified.
     double GetCurvePrecision(MgCoordinateSystem* gridCS);
 
@@ -174,9 +174,9 @@
     /// the new coordinate system.
     MgPolygon* GetBoundary (void) const;
 
-     ////////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////////
     /// \brief
-    /// Sets a limit on thenumber of points generated by the complex curve
+    /// Sets a limit on the number of points generated by the complex curve
     /// approximation algorithm.
     /// \param maxPoints
     /// The complex curve approximation algorithm cleanly terminates after this
@@ -189,7 +189,7 @@
     /// probability of a runaway calculation.
     void SetMaxCurvePoints (INT32 maxPoints);
 
-   ////////////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////////////
     /// \brief
     /// Returns the extents of the grid boundary.
     /// \param eastMin
@@ -205,10 +205,10 @@
     /// 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
+    /// after the boundary has been converted using the provided coordinate
     /// system transform.
     /// \param transform
     /// The transformation used to convert the grid boundary.
@@ -240,8 +240,8 @@
     /// 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.
+    /// concave polygons, but this has not been tested.  Interior rings in the
+    /// internal polygon object are ignored.
     MgLineStringCollection* ClipLineString (MgLineString* lineString) const;
 
 protected:

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.cpp	2009-11-20 17:56:28 UTC (rev 4351)
@@ -375,6 +375,8 @@
     Ptr<MgCoordinateSystemGridLineCollection> aGridLineCollection;
     Ptr<CCoordinateSystemGridLineCollection> theGridLineCollection;
 
+    MgCoordinateSystemFactory factory;
+
     if (m_GridBoundary == 0)
     {
         // Proceeding without a grid boundary will cause a crash.
@@ -384,37 +386,43 @@
 
     MG_TRY ()
         theGridLineCollection = new CCoordinateSystemGridLineCollection ();
+
+        // Determine the grid type.
         unitType = specification->GetUnitType();
         specIsGrid = (unitType ==  MgCoordinateSystemUnitType::Linear);
-        if (specIsGrid)
+        
+        // Process each zone in our zone collection.  Originally, we thought
+        // we could just call the GetGridLines function of the OneGrid
+        // base class, but there are just too many special cases to deal with.
+        // So, rather than kludge a bunch of special stuff into OneGrid and
+        // compromise its generality, we have our own functions in this MGRS
+        // specific object which duplicates much of the functionality of the
+        // OneGrid objoect.
+        zoneCount = m_ZoneCollection->GetCount ();
+        for (index = 0;index < zoneCount;index += 1)
         {
-            // The specification calls for a grid.
-            zoneCount = m_ZoneCollection->GetCount ();
-            for (index = 0;index < zoneCount;index += 1)
+            mgrsZoneGrid = m_ZoneCollection->GetItem (index);
+            if (specIsGrid)
             {
-                mgrsZoneGrid = m_ZoneCollection->GetItem (index);
-                aGridLineCollection = mgrsZoneGrid->GetGridLines (specification);
-                theGridLineCollection->AddCollection (aGridLineCollection);
+                // The specification calls for a grid.  The following function
+                // is smart enough to deal with the special nature of zones
+                // 31 through 37 at the higher northern latitudes.
+                aGridLineCollection = mgrsZoneGrid->GetGridLines (m_GridBoundary,specification);
             }
-        }
-        else
-        {
-            // The specification calls for a graticule.
-            if (m_GraticuleUtm)
+            else
             {
-                aGridLineCollection = m_GraticuleUtm->GetGridLines (specification);
-                theGridLineCollection->AddCollection (aGridLineCollection);
+                // The specification calls for a graticule  This object is
+                // smart enough to deal with band X (which is 12 degrees high)
+                // and the special nature of zones 31 through 37 at the higher
+                // northern latitudes.
+                aGridLineCollection = mgrsZoneGrid->GetGraticuleLines (m_GridBoundary,specification);
             }
-            if (m_GraticuleUpsNorth)
+            if (aGridLineCollection != 0)
             {
-                aGridLineCollection = m_GraticuleUpsNorth->GetGridLines (specification);
+                // Add whatever we got to the collection we are accumulating.
                 theGridLineCollection->AddCollection (aGridLineCollection);
+                aGridLineCollection = 0;
             }
-            if (m_GraticuleUpsSouth)
-            {
-                aGridLineCollection = m_GraticuleUpsSouth->GetGridLines (specification);
-                theGridLineCollection->AddCollection (aGridLineCollection);
-            }
         }
     MG_CATCH_AND_THROW(L"MgCoordinateSystemMgrs::GetGridLines")
     return static_cast<MgCoordinateSystemGridLineCollection*>(theGridLineCollection.Detach());
@@ -706,6 +714,9 @@
                                                                                   MgCoordinateSystem* frameCRS,
                                                                                   bool useFrameDatum)
 {
+    bool northPole (false);
+    bool southPole (false);
+
     INT32 zoneNbr;
     INT32 zoneMin;
     INT32 zoneMax;
@@ -713,8 +724,10 @@
 
     double cm;                      // central meridian
     double eastLimit, westLimit;    // limits of a UTM zone
-    double eastMin, eastMax;        // frame boundary extrema in 'LL84' (or 'LL')
-    double northMin, northMax;      // frame boundary extrema in 'LL84' (or 'LL')
+    double lngMin, lngMax;          // frame boundary extrema in 'LL84' (or 'LL')
+    double latMin, latMax;          // frame boundary extrema in 'LL84' (or 'LL')
+    double eastMin, eastMax;        // frame boundary extrema in frame CRS
+    double northMin, northMax;      // frame boundary extrema in frame CRS
 
     Ptr<MgPolygon> pPolygon;
     Ptr<MgPolygon> pPolygonIntersection;
@@ -758,71 +771,158 @@
         m_GraticuleUpsNorth = 0;
         m_GraticuleUpsSouth = 0;
 
+        // Get the min/max of the frame in frame coordinates.
+        frameBoundary->GetBoundaryExtents (eastMin,eastMax,northMin,northMax);
+
         // 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");
         toLlTransform = csFactory->GetTransform(frameCRS,llCRS);
+        toLlTransform->IgnoreDatumShiftWarning (true);
+        toLlTransform->IgnoreOutsideDomainWarning (true);
         toFrameTransform = csFactory->GetTransform(llCRS,frameCRS);
+        toFrameTransform->IgnoreDatumShiftWarning (true);
+        toFrameTransform->IgnoreOutsideDomainWarning (true);
         pPolygon = frameBoundary->GetBoundary (toLlTransform,1.0E-05);
         llBoundary = csFactory->GridBoundary (pPolygon);
-        llBoundary->GetBoundaryExtents (eastMin,eastMax,northMin,northMax);
+        llBoundary->GetBoundaryExtents (lngMin,lngMax,latMin,latMax);
 
+        // The llBoundary object has been created using rectangular techniques.
+        // Since the earth is spherical, in certain rare cases the resulting
+        // extents can exclude either (or both, presumably) pole when inclusion
+        // is appropriate.  We try to deal with that issue here.  We use this
+        // technique only for projections which we believe can properly
+        // represent a pole for defensive purposes.
+
+        if (CanDoPoles (frameCRS))
+        {
+            // Use the toFrameXform object to convert the north pole to the frame
+            // coordinate system.  If the conversion is successful, and the result
+            // resides within the original cartesian frame boundary, we add the
+            // north pole to the extents generated by the GetBoundaryExtents
+            // function call.
+            if (latMax > 0.0)
+            {
+                Ptr<MgCoordinate> poleTest = new MgCoordinateXY (0.0,90.0);
+                poleTest = toFrameTransform->Transform (poleTest);
+                if (poleTest->GetX () >= eastMin  && poleTest->GetX () <= eastMax &&
+                    poleTest->GetY () >= northMin && poleTest->GetY () <= northMax)
+                {
+                    northPole = true;
+                }
+            }
+            if (latMin < 0.0)
+            {
+                Ptr<MgCoordinate> poleTest = new MgCoordinateXY (0.0,-90.0);
+                poleTest = toFrameTransform->Transform (poleTest);
+                if (poleTest->GetX () >= eastMin  && poleTest->GetX () <= eastMax &&
+                    poleTest->GetY () >= northMin && poleTest->GetY () <= northMax)
+                {
+                    southPole = true;
+                }
+            }
+        }
+
         // Use the latitude min/max to extract the UTM/UPS zones as necessary.
-        if (northMin < -80.0)
+        if (latMin < -80.0 || southPole)
         {
             // There is a portion of the frame boundary in the south polar region.
             zoneNbr = -61;
-            pSouthwest->SetX (eastMin);
-            pSouthwest->SetY (northMin);
-            pNortheast->SetX (eastMax);
-            pNortheast->SetY (-80.0);
-            llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
-            pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
-            Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
-            pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
-            if (pPolygonIntersection != 0)
+
+            pPolygon = 0;
+            if (southPole)
             {
-                reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
-                mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
-                zoneCollection->Add (mgrsZoneGrid);
+                // The south pole is included within the provided frame boundary.
+                // In this case, the rectangular technique used above would
+                // produce a closed polygon which will look like a circular pie
+                // with an infitessiammly smal slice in it.  This slice drives
+                // the clipper crazy.  So, we need to develop a simple
+                // circular closed boundary around, but not including the
+                // pole.
 
-                // Construct the m_GraticuleUpsSouth member, it may be needed.
-                m_GraticuleUpsSouth = new CCoordinateSystemOneGrid (reducedFrameBoundary,llCRS,frameCRS);
+                // Since we need to do the same thing for the northern pole as
+                // well, we have a function that will do that for us.  THis
+                // function will fail if the underlying frame CRS is not
+                // suitable for polar aspects.
+                pPolygon = ParallelPolygon (toFrameTransform,-80.0,720);
             }
+            if (!pPolygon)
+            {
+                // The south pole is not within the frame boundary, the
+                // generation of a circular boundary representing a parallel
+                // failed, or the frame CRS is incapabale of representing
+                // the pole.  Therefore, we have to use the standard rectangular
+                // boundary technique and hope for the best.  This should work
+                // fine if the region does not actually include the pole, and
+                // the results should be decent in other cases.
+                pSouthwest->SetX (lngMin);
+                pSouthwest->SetY (latMin);
+                pNortheast->SetX (lngMax);
+                pNortheast->SetY (-80.0);
+                llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
+                pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+            }
+            if (pPolygon)
+            {
+                Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
+                pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
+                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);
+                }
+            }
         }
-        if (northMax > 84.0)
+        if (latMax > 84.0 || northPole)
         {
             // There is a portion of the frame boundary in the north polar region.
             zoneNbr = 61;
-            pSouthwest->SetX (eastMin);
-            pSouthwest->SetY (84.0);
-            pNortheast->SetX (eastMax);
-            pNortheast->SetY (northMax);
-            llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
-            pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
-            Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
-            pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
-            if (pPolygonIntersection != 0)
+
+            // Same as for the south pole, sans the laborious comments.
+            pPolygon = 0;
+            if (northPole)
             {
-                reducedFrameBoundary = csFactory->GridBoundary (pPolygonIntersection);
-                mgrsZoneGrid = new CCoordinateSystemMgrsZone (reducedFrameBoundary,zoneNbr,useFrameDatum,frameCRS,m_nLetteringScheme);
-                zoneCollection->Add (mgrsZoneGrid);
+                pPolygon = ParallelPolygon (toFrameTransform,84.0,720);
+            }
+            if (pPolygon == 0)
+            {
+                pSouthwest->SetX (lngMin);
+                pSouthwest->SetY (84.0);
+                pNortheast->SetX (lngMax);
+                pNortheast->SetY (latMax);
+                llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
+                pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
+            }
+            if (pPolygon != 0)
+            {
+                Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
+                pPolygonIntersection = dynamic_cast<MgPolygon*>(pPolygon->Intersection (pPolygonTemp));
+                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)
+        if (latMax > -80.0 && latMin < 84.0)
         {
             // 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.
-            tmpInt32 = static_cast <INT32>(floor (eastMin));
+            tmpInt32 = static_cast <INT32>(floor (lngMin));
             zoneMin = ((tmpInt32 + 180) / 6) + 1;
-            tmpInt32 = static_cast <INT32>(ceil (eastMax));
+            tmpInt32 = static_cast <INT32>(ceil (lngMax));
             zoneMax = ((tmpInt32 + 180) / 6) + 1;
 
-            if (northMax > 0.0)
+            if (latMax > 0.0)
             {
                 // There are some northern zones.
 
@@ -831,8 +931,8 @@
                 // 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);
+                pSouthwest->SetY ((latMin <  0.0) ?  0.0 : latMin);
+                pNortheast->SetY ((latMax > 84.0) ? 84.0 : latMax);
 
                 // OK, generate a CCoordinateSystemMgrsZone object for each
                 // UTM zone which intersects the frame boundary provided.
@@ -848,8 +948,8 @@
                     eastLimit = cm + 3.0;
 
                     // 2> Apply the extents of the provided frame boundary.
-                    if (westLimit < eastMin) westLimit = eastMin;
-                    if (eastLimit > eastMax) eastLimit = eastMax;
+                    if (westLimit < lngMin) westLimit = lngMin;
+                    if (eastLimit > lngMax) eastLimit = lngMax;
 
                     // 3> Create, in terms of LL coordinates, the frame
                     //    boundary as is appropriate for this particular zone.
@@ -870,19 +970,19 @@
                     }
                  }
             }
-            if (northMin < 0.0)
+            if (latMin < 0.0)
             {
                 // 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);
+                pSouthwest->SetY ((latMin < -80.0) ? -80.0 : latMin);
+                pNortheast->SetY ((latMax >   0.0) ?   0.0 : latMax);
                 for (zoneNbr = zoneMin;zoneNbr <= zoneMax;zoneNbr += 1)
                 {
                     cm = static_cast<double>((zoneNbr * 6) - 183);
                     westLimit = cm - 3.0;
                     eastLimit = cm + 3.0;
-                    if (westLimit < eastMin) westLimit = eastMin;
-                    if (eastLimit > eastMax) eastLimit = eastMax;
+                    if (westLimit < lngMin) westLimit = lngMin;
+                    if (eastLimit > lngMax) eastLimit = lngMax;
                     pSouthwest->SetX (westLimit);
                     pNortheast->SetX (eastLimit);
 
@@ -901,10 +1001,10 @@
 
             // 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);
+            pSouthwest->SetX (lngMin);
+            pNortheast->SetX (lngMax);
+            pSouthwest->SetY ((latMin < -80.0) ? -80.0 : latMin);
+            pNortheast->SetY ((latMax >  84.0) ?  84.0 : latMax);
             llBoundary = csFactory->GridBoundary (pSouthwest,pNortheast);
             pPolygon = llBoundary->GetBoundary (toFrameTransform,1.0);
             Ptr<MgPolygon> pPolygonTemp = frameBoundary->GetBoundary ();
@@ -930,12 +1030,14 @@
     squareDesignation [0] = L'?';
     squareDesignation [1] = L'?';
     squareDesignation [2] = L'\0';
+    squareDesignation [3] = L'\0';
 
+    iEasting  = static_cast<INT32>(easting);
+    iNorthing = static_cast<INT32>(northing);
+
     // For now we assume there is no difference between the northern and southern hemisphere.
     if (utmZoneNbr != 0 && abs(utmZoneNbr) <= 60)
     {
-        iEasting  = static_cast<INT32>(easting);
-        iNorthing = static_cast<INT32>(northing);
         if (iEasting < 100000) iEasting = 100000;
         if (iEasting > 1000000) iEasting = 1000000;
         if (iNorthing < 0) iNorthing = 0;
@@ -946,7 +1048,6 @@
         northIndex = static_cast<INT32>(iNorthing) / 100000;
         if (eastIndex < 9 && northIndex < 21)
         {
-//          seriesIndex = abs (utmZoneNbr) % 6 - 1;                 //BOGUS:: This does not work!!!!!
             seriesIndex = (abs (utmZoneNbr) - 1) % 6;
             if (letteringScheme == MgCoordinateSystemMgrsLetteringScheme::Alternative)
             {
@@ -960,6 +1061,31 @@
             }
         }
     }
+    else if (utmZoneNbr == 61)
+    {
+        // North UPS region
+        eastIndex = (iEasting / 100000) - 13;
+        northIndex = (iNorthing / 100000) - 13;
+        if (eastIndex >= 0  && eastIndex  <= 13 &&
+            northIndex >= 0 && northIndex <= 13)
+        {
+            squareDesignation [0] = MgrsSeriesPolarNorth [0][eastIndex];
+            squareDesignation [1] = MgrsSeriesPolarNorth [1][northIndex];
+        }
+    }
+    else if (utmZoneNbr == -61)
+    {
+        // South UPS region
+        eastIndex = (iEasting / 100000) - 8;
+        northIndex = (iNorthing / 100000) - 8;
+        if (eastIndex >= 0  && eastIndex  <= 19 &&
+            northIndex >= 0 && northIndex <= 19)
+        {
+            squareDesignation [0] = MgrsSeriesPolarSouth [0][eastIndex];
+            squareDesignation [1] = MgrsSeriesPolarSouth [1][northIndex];
+        }
+    }
+
     STRING designation (squareDesignation);
     return designation;
 }
@@ -1034,4 +1160,114 @@
     }
     return designationLetter;
 }
+
+// TODO:  This function probably should be a member of some other object, as
+// its product is of value outside the realm of MGRS.
+MgPolygon* CCoordinateSystemMgrs::ParallelPolygon (MgCoordinateSystemTransform* transformation,double latitude,
+                                                                                               INT32 pointCount)
+{
+    bool ok (true);
+    INT32 index;
+    INT32 status;
+
+    double deltaLng;
+    double currentLng;
+
+    Ptr<MgCoordinate> llPoint;
+    Ptr<MgCoordinate> xyPoint;
+    Ptr<MgCoordinate> firstPoint;
+    Ptr<MgCoordinateCollection> xyCollection;
+    Ptr<MgLinearRing> linearRing;
+    Ptr<MgPolygon> polyPtr;
+    MgPolygon* result;
+
+    result = 0;
+    if (pointCount < 3 || pointCount > 2048)
+    {
+        pointCount = 720;
+    }
+    deltaLng = 360.0 / static_cast<double>(pointCount);
+
+    currentLng = -180.0;
+    xyCollection = new MgCoordinateCollection ();
+    llPoint = new MgCoordinateXY (currentLng,latitude);
+    for (index = 0;ok && (index < pointCount);index += 1)
+    {
+        llPoint->SetX (currentLng);
+        xyPoint = transformation->Transform (llPoint);
+        status = transformation->GetLastTransformStatus ();
+        ok = status == MgCoordinateSystemTransform::TransformOk;
+        if (ok)
+        {
+            xyCollection->Add (xyPoint);
+            if (index == 0)
+            {
+                firstPoint = SAFE_ADDREF (xyPoint.p);
+            }
+        }
+        currentLng += deltaLng;
+    }
+
+    if (ok)
+    {
+        // Close the linear ring for sure.
+        xyCollection->Add (firstPoint);
+
+        linearRing = new MgLinearRing (xyCollection);
+        polyPtr = new MgPolygon (linearRing,0);
+        result = polyPtr.Detach ();
+    }
+    return result;
+}
+bool CCoordinateSystemMgrs::CanDoPoles (MgCoordinateSystem* frameCRS)
+{
+	// MENTOR_MAINTENANCE --> a new projection may need to be added to this list.
+    static INT32 polarCapable [] =
+    {
+        MgCoordinateSystemProjectionCode::Tm,
+        MgCoordinateSystemProjectionCode::Trmrs,
+        MgCoordinateSystemProjectionCode::Trmeraf,
+        MgCoordinateSystemProjectionCode::Sotrm,
+        MgCoordinateSystemProjectionCode::Alber,
+        MgCoordinateSystemProjectionCode::Azede,
+        MgCoordinateSystemProjectionCode::Azmea,
+        MgCoordinateSystemProjectionCode::Azmed,
+        MgCoordinateSystemProjectionCode::Cassini,
+        MgCoordinateSystemProjectionCode::Edcnc,
+        MgCoordinateSystemProjectionCode::GaussK,
+        MgCoordinateSystemProjectionCode::Hom1uv,
+        MgCoordinateSystemProjectionCode::Hom2uv,
+        MgCoordinateSystemProjectionCode::Hom1xy,
+        MgCoordinateSystemProjectionCode::Hom2xy,
+        MgCoordinateSystemProjectionCode::Krovak,
+        MgCoordinateSystemProjectionCode::Rskew,
+        MgCoordinateSystemProjectionCode::Rskewc,
+        MgCoordinateSystemProjectionCode::Rskewo,
+        MgCoordinateSystemProjectionCode::Lm1sp,
+        MgCoordinateSystemProjectionCode::Lm2sp,
+        MgCoordinateSystemProjectionCode::Lmblg,
+        MgCoordinateSystemProjectionCode::Lmbrtaf,
+        MgCoordinateSystemProjectionCode::Lmtan,
+        MgCoordinateSystemProjectionCode::Mstero,
+        MgCoordinateSystemProjectionCode::Obqcyl,
+        MgCoordinateSystemProjectionCode::Plycn,
+        MgCoordinateSystemProjectionCode::Pstro,
+        MgCoordinateSystemProjectionCode::Pstrosl,
+        MgCoordinateSystemProjectionCode::Unknown
+    };
+
+    bool canDoPoles (false);
+    INT32 index;
+    
+    INT32 prjCode = frameCRS->GetProjectionCode ();
+    for (index = 0;polarCapable [index] != MgCoordinateSystemProjectionCode::Unknown;index += 1)
+    {
+        if (prjCode == polarCapable [index])
+        {
+            canDoPoles = true;
+            break;
+        }
+    }
+    return canDoPoles;
+}
 //End of file.

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrs.h	2009-11-20 17:56:28 UTC (rev 4351)
@@ -104,6 +104,9 @@
 
 private:
     short GetBesselFromLetteringScheme(INT8 nLetteringScheme);
+    MgPolygon* ParallelPolygon (MgCoordinateSystemTransform* transformation,double latitude,
+                                                                            INT32 pointCount);
+    bool CanDoPoles (MgCoordinateSystem* frameCRS);
 
 protected:
     INT8 m_nLetteringScheme;

Added: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.cpp	                        (rev 0)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.cpp	2009-11-20 17:56:28 UTC (rev 4351)
@@ -0,0 +1,307 @@
+//
+//  Copyright (C) 2004-2009 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "GeometryCommon.h"
+#include "CoordSysCommon.h"
+#include "CoordSysUtil.h"
+#include "CriticalSection.h"
+
+#include "CoordSys.h"
+#include "CoordSysGrids.h"
+#include "CoordSysOneGrid.h"
+#include "CoordSysMgrsZone.h"
+#include "CoordSysMgrs.h"
+#include "CoordSysMgrsMajorRegion.h"
+
+using namespace CSLibrary;
+
+//=============================================================================
+// CCoordinateSystemMgrsMajorRegion
+CCoordinateSystemMgrsMajorRegion::CCoordinateSystemMgrsMajorRegion (INT32 utmZoneNbr,INT32 bandIndex)
+                                                                        :
+                                                                    m_IsValid         (false),
+                                                                    m_Designation     (),
+                                                                    m_UtmZoneNbr      (utmZoneNbr),
+                                                                    m_MgrsBandIndex   (bandIndex),
+                                                                    m_CentralMeridian (),
+                                                                    m_WestLng         (),
+                                                                    m_SouthLat        (),
+                                                                    m_EastLng         (),
+                                                                    m_NorthLat        ()
+{
+    INT32 zoneNbr;
+    wchar_t gridZoneLetter;
+    wchar_t wcBufr [128];
+
+    // This constructor should not be used for the polar regions.
+    zoneNbr = abs (m_UtmZoneNbr);
+    if ((zoneNbr > 0) && (zoneNbr <= 60) && (bandIndex >= 2) && (bandIndex < 22))
+    {
+        m_IsValid = true;
+
+        // Do the normal thing which is all we need to do 90% of the time.
+        zoneNbr = abs (m_UtmZoneNbr);
+        m_CentralMeridian = static_cast<double>(-183 + (zoneNbr * 6));
+        m_WestLng = m_CentralMeridian - 3.0;
+        m_EastLng = m_CentralMeridian + 3.0;
+
+        gridZoneLetter = CCoordinateSystemMgrs::GridZoneDesignationLetter (bandIndex);
+        swprintf (wcBufr,128,L"%d%c",zoneNbr,gridZoneLetter);
+        STRING designation (wcBufr);
+        m_Designation = designation;
+
+        // -2 gets us past the 'A' and 'B' for the south polar region.
+        m_SouthLat = static_cast<double>(-80 + ((bandIndex - 2) * 8));
+        m_NorthLat = m_SouthLat + 8.0;
+
+        if (bandIndex == 21)
+        {
+            m_NorthLat = m_SouthLat + 12.0;
+            if (m_UtmZoneNbr == 32 || m_UtmZoneNbr == 34 || m_UtmZoneNbr == 36)
+            {
+                m_IsValid = false;
+            }
+            else
+            {
+                // There are two zones which are 9 degrees wide, and two that are
+                // 12 degrees wide in this band.
+                if (m_UtmZoneNbr == 31)
+                {
+                    m_WestLng = m_CentralMeridian - 3.0;
+                    m_EastLng = m_CentralMeridian + 6.0;
+                }
+                else if (m_UtmZoneNbr == 33 || m_UtmZoneNbr == 35)
+                {
+                    m_WestLng = m_CentralMeridian - 6.0;
+                    m_EastLng = m_CentralMeridian + 6.0;
+                }
+                else if (m_UtmZoneNbr == 37)
+                {
+                    m_WestLng = m_CentralMeridian - 6.0;
+                    m_EastLng = m_CentralMeridian + 3.0;
+                }
+            }
+        }
+        else if (bandIndex == 19)
+        {        
+            if (m_UtmZoneNbr == 31)
+            {
+                m_WestLng = m_CentralMeridian - 3.0;
+                m_EastLng = m_CentralMeridian;
+            }
+            else if (m_UtmZoneNbr == 32)
+            {
+                m_WestLng = m_CentralMeridian - 6.0;
+                m_EastLng = m_CentralMeridian + 3.0;
+            }
+        }
+    }
+}
+// The following constructor is for polar regions.
+//CCoordinateSystemMgrsMajorRegion (INT32 utmZoneNbr,double centralMeridian,INT32 latIndex);
+CCoordinateSystemMgrsMajorRegion::~CCoordinateSystemMgrsMajorRegion (void)
+{
+}
+bool CCoordinateSystemMgrsMajorRegion::IsValid (void)
+{
+    return m_IsValid;
+}
+STRING CCoordinateSystemMgrsMajorRegion::GetDesignation (void)
+{
+    return m_Designation;
+}
+INT32 CCoordinateSystemMgrsMajorRegion::GetUtmZoneNbr (void)
+{
+    return m_UtmZoneNbr;
+}
+INT32 CCoordinateSystemMgrsMajorRegion::GetMgrsBandINdex (void)
+{
+    return m_MgrsBandIndex;
+}
+double CCoordinateSystemMgrsMajorRegion::GetCentralMeridian (void)
+{
+    return m_CentralMeridian;
+}
+double CCoordinateSystemMgrsMajorRegion::GetWestEdgeLng (void)
+{
+    return m_WestLng;
+}
+double CCoordinateSystemMgrsMajorRegion::GetSouthEdgeLat (void)
+{
+    return m_SouthLat;
+}
+double CCoordinateSystemMgrsMajorRegion::GetEastEdgeLng (void)
+{
+    return m_EastLng;
+}
+double CCoordinateSystemMgrsMajorRegion::GetNorthEdgeLat (void)
+{
+    return m_NorthLat;
+}
+void CCoordinateSystemMgrsMajorRegion::Dispose (void)
+{
+    delete this;
+}
+///////////////////////////////////////////////////////////////////////////////
+CCoordinateSystemMgrsMajorRegionCollection::CCoordinateSystemMgrsMajorRegionCollection (void)
+                                                    :
+                                                 MgGuardDisposable       (),
+                                                 m_MajorRegionCollection ()
+{
+    m_MajorRegionCollection = new MgDisposableCollection();
+}
+CCoordinateSystemMgrsMajorRegionCollection::CCoordinateSystemMgrsMajorRegionCollection (INT32 utmZoneNbr,double minLat,double maxLat)
+                                                                                            :
+                                                                                        MgGuardDisposable       (),
+                                                                                        m_NorthPolar            (false),
+                                                                                        m_SouthPolar            (false),
+                                                                                        m_MajorRegionCollection ()
+{
+    INT32 bandIndex;
+    INT32 intMinLat;
+    INT32 intMaxLat;
+    INT32 southernBandIndex;
+    INT32 northernBandIndex;
+
+    double delta;
+
+    // NOTE:  This is a constructor.
+    m_MajorRegionCollection = new MgDisposableCollection();
+
+    // Determine the band index of the southernmost region in the latitude range.
+    if (minLat < -80.0)
+    {
+        // Southern limit includes the south UPS region.
+        m_SouthPolar = true;
+        intMinLat = -90;
+        southernBandIndex = 0;
+    }
+    else if (minLat >= -80.0 && minLat < 72.0)
+    {
+        // Southern limit is in the normal UTM zone area where regions are 8 degrees
+        // of latitude.
+        delta = fabs(fmod (minLat,8.0));
+        intMinLat = static_cast<INT32>(minLat - ((minLat >= 0.0) ? delta : (8.0 - delta)));
+        // +2 two here accounts for the A & B regions of the south pole.
+        southernBandIndex = ((intMinLat + 80) / 8) + 2;
+    }
+    else if (minLat >= 72.0 && minLat <= 84.0)
+    {
+        // The southern limit is in Band X which is the one zone which is 12 degrees
+        // of latitude high.
+        intMinLat = 72;
+        southernBandIndex = 21;
+    }
+    else if (minLat > 84.0)
+    {
+        // The southern limit is in the north UPS regions (i.e. YZ).
+        m_NorthPolar = true;   
+        intMinLat = 84;
+        southernBandIndex = 22;
+    }
+
+    // Determine the bandindex of the northernmost region in the latitude range.
+    if (maxLat < -80.0)
+    {
+        // Northern limit is in the southern UPS region.
+        m_SouthPolar = true;
+        intMaxLat = 80;
+        northernBandIndex = 1;
+    }
+    else if (maxLat >= -80.0 && maxLat <= 72.0)
+    {
+        // Northern limit is in area of normal UTM zones where regions are 8 degrees
+        // of latitude high.
+        delta = fabs(fmod (maxLat,8.0));
+        intMaxLat = static_cast<INT32>(maxLat + ((maxLat >= 0.0) ? (8.0 - delta) : delta));
+        northernBandIndex = ((intMaxLat + 80) / 8) + 2;
+    }
+    else if (maxLat > 72.0 && maxLat <= 84.0)
+    {
+        // Northern limit is in band X, the region which is 12 degrees high.
+        intMaxLat = 84;
+        northernBandIndex = 21;
+    }
+    else if (maxLat > 84.0)
+    {
+        m_NorthPolar = true;
+        intMaxLat = 90;
+        northernBandIndex = 22;
+    }
+
+    // This function does not return the polar regions, as it is likely that doing
+    // in this function which UTM zone specific will cause several duplicates.  So
+    // we filter the polar band out.
+    if (southernBandIndex <  2) southernBandIndex =  2;
+    if (northernBandIndex > 21) northernBandIndex = 21;
+
+    // OK, generate the regions which interect (even to the smallest degree) the
+    // the latitude limits we were provided.
+    if (southernBandIndex <= northernBandIndex)
+    {
+        for (bandIndex = southernBandIndex;bandIndex <= northernBandIndex;bandIndex += 1)
+        {
+            Ptr<CCoordinateSystemMgrsMajorRegion> rgnPtr = new CCoordinateSystemMgrsMajorRegion (utmZoneNbr,bandIndex);
+            if (rgnPtr->IsValid ())
+            {
+                m_MajorRegionCollection->Add (rgnPtr);
+            }
+        }
+    }
+}
+bool CCoordinateSystemMgrsMajorRegionCollection::IncludesSouthPolarRegion (void)
+{
+    return m_SouthPolar;
+}
+bool CCoordinateSystemMgrsMajorRegionCollection::IncludesNorthPolarRegion (void)
+{
+    return m_NorthPolar;
+}
+CCoordinateSystemMgrsMajorRegionCollection::~CCoordinateSystemMgrsMajorRegionCollection (void)
+{
+    m_MajorRegionCollection->Clear ();
+}
+INT32 CCoordinateSystemMgrsMajorRegionCollection::GetCount () const
+{
+    INT32 itemCount = m_MajorRegionCollection->GetCount ();
+    return itemCount;
+}
+CCoordinateSystemMgrsMajorRegion* CCoordinateSystemMgrsMajorRegionCollection::GetItem (INT32 index) const
+{
+    CCoordinateSystemMgrsMajorRegion *itemPtr = static_cast<CCoordinateSystemMgrsMajorRegion*>(m_MajorRegionCollection->GetItem (index));
+    return itemPtr;
+}
+void CCoordinateSystemMgrsMajorRegionCollection::RemoveAt (INT32 index)
+{
+    m_MajorRegionCollection->RemoveAt (index);
+}
+void CCoordinateSystemMgrsMajorRegionCollection::Clear()
+{
+    m_MajorRegionCollection->Clear ();
+}
+void CCoordinateSystemMgrsMajorRegionCollection::SetItem (INT32 index, CCoordinateSystemMgrsMajorRegion* value)
+{
+    m_MajorRegionCollection->SetItem (index,value);
+}
+void CCoordinateSystemMgrsMajorRegionCollection::Add (CCoordinateSystemMgrsMajorRegion* value)
+{
+    m_MajorRegionCollection->Add (value);
+}
+void CCoordinateSystemMgrsMajorRegionCollection::Dispose (void)
+{
+    delete this;
+}

Added: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.h	                        (rev 0)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsMajorRegion.h	2009-11-20 17:56:28 UTC (rev 4351)
@@ -0,0 +1,116 @@
+//
+//  Copyright (C) 2004-2009 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef _CCOORDINATESYSTEMMGRSMAJORTREGION_H_
+#define _CCOORDINATESYSTEMMGRSMAHJORREGION_H_
+
+namespace CSLibrary
+{
+
+// All region, major and minor, are rectangular in their native coordinates:
+// Lat/Long for the major regions and UTM coordinates for minor regions.  We
+// have this helper object for the major regions as there screwy things go on
+// at the northern extent.  Specifically, band X is actually 12 degrees
+// high, zones 31 thru 37 in band X are screwy, and in band V zones 31 and 32
+// are screwy.  We intend to use this object so that there is only one copy of
+// the code necessary to deal with all this screwy-ness.
+//
+// Essentially, given a grid boundary in terms of lat/long min/max, we generate
+// a collection of these objects which represents the regions which intersect
+// the geographic region provided.  Then, as need dictate, MGRS graticule lines
+// and/or Grid Regions are manufactured from the the resulting collection.
+//
+// A lot of busy work, but required to get this done right.
+
+class CCoordinateSystemMgrsMajorRegion : public MgGuardDisposable
+{
+public:
+    CCoordinateSystemMgrsMajorRegion (INT32 utmZoneNbr,INT32 bandIndex);
+
+    // This constructor is used for polar regions.  The central meridian
+    // paremeter is the central longitude of the view port as seen from the
+    // the equator and is used to determine what portion of the polar
+    // graticules are considered east/west/south/north lines.  This
+    // becomes very important for labeling purposes.
+    CCoordinateSystemMgrsMajorRegion (INT32 utmZoneNbr,double centralMeridian,INT32 latIndex);
+    ~CCoordinateSystemMgrsMajorRegion (void);
+
+    bool IsValid (void);
+    STRING GetDesignation (void);
+    INT32 GetUtmZoneNbr (void);
+    INT32 GetMgrsBandINdex (void);
+    double GetCentralMeridian (void);
+    double GetWestEdgeLng (void);
+    double GetSouthEdgeLat (void);
+    double GetEastEdgeLng (void);
+    double GetNorthEdgeLat (void);
+
+protected:
+    void Dispose (void);
+
+private:
+    bool m_IsValid;             // Set to false for non-existent regions
+    STRING m_Designation;       // MGRS major region designation.
+    INT32 m_UtmZoneNbr;         // positive is north, negative south, 61 polar, 0 == invalid.
+    INT32 m_MgrsBandIndex;      // 'A' thru 'Z', sans 'I' and 'O', zero based
+    double m_CentralMeridian;   // in degrees, east longitude positive.
+    double m_WestLng;           // longitude of western edge of the region, degrees positive east
+    double m_SouthLat;          // latitude of the southern edge of the region, degrees positive north
+    double m_EastLng;           // longitude of eastern edge of the region, degrees positive east
+    double m_NorthLat;          // latitude of the southern edge of the region, degrees positive north
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Not implemented
+    CCoordinateSystemMgrsMajorRegion (const CCoordinateSystemMgrsMajorRegion& source);
+    CCoordinateSystemMgrsMajorRegion& operator= (const CCoordinateSystemMgrsMajorRegion& rhs);
+};
+
+// The following is a collection of the above.  The magic here, of course,
+// is that the constructor of this object builds the entire collection.
+class CCoordinateSystemMgrsMajorRegionCollection : public MgGuardDisposable
+{
+public:
+    CCoordinateSystemMgrsMajorRegionCollection (void);
+    CCoordinateSystemMgrsMajorRegionCollection (INT32 utmZoneNbr,double minLat,double maxLat);
+    ~CCoordinateSystemMgrsMajorRegionCollection (void);
+
+    bool IncludesSouthPolarRegion (void);
+    bool IncludesNorthPolarRegion (void);
+    INT32 GetCount () const;
+    CCoordinateSystemMgrsMajorRegion* GetItem (INT32 index) const;
+    void RemoveAt (INT32 index);
+    void Clear();
+    void SetItem (INT32 index, CCoordinateSystemMgrsMajorRegion* value);
+    void Add (CCoordinateSystemMgrsMajorRegion* value);
+
+protected:
+    void Dispose (void);
+
+private:
+    // Data Members
+    bool m_SouthPolar;
+    bool m_NorthPolar;
+    Ptr<MgDisposableCollection> m_MajorRegionCollection;
+
+    // Member functions not implemented.
+    CCoordinateSystemMgrsMajorRegionCollection  (const CCoordinateSystemMgrsMajorRegionCollection & source);
+    CCoordinateSystemMgrsMajorRegionCollection& operator= (const CCoordinateSystemMgrsMajorRegionCollection & rhs);
+};
+
+}       // CSLibrary namespace
+
+#endif  // _CCOORDINATESYSTEMMGRSMAJORTREGION_H_

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2009-11-20 17:56:28 UTC (rev 4351)
@@ -24,7 +24,8 @@
 #include "CoordSysGrids.h"
 #include "CoordSysOneGrid.h"
 #include "CoordSysMgrsZone.h"
-#include "CoordSysMgrs.h"       //for CCoordinateSystemMgrs
+#include "CoordSysMgrs.h"
+#include "CoordSysMgrsMajorRegion.h"
 
 using namespace CSLibrary;
 
@@ -45,8 +46,8 @@
 
     STRING utmZoneCode = CCoordinateSystemMgrs::ZoneNbrToUtmCs (m_UtmZone);
     utmZoneCRS = csFactory.CreateFromCode (utmZoneCode);
+
     SetUp (frameBoundary,utmZoneCRS,frameCRS);
-    
     SetUserID (m_UtmZone);
 }
 CCoordinateSystemMgrsZone::~CCoordinateSystemMgrsZone (void)
@@ -58,6 +59,168 @@
     BuildRegionCollection (frameBoundary,specification);
     return SAFE_ADDREF(m_RegionCollection.p);
 }
+CCoordinateSystemGridLineCollection* CCoordinateSystemMgrsZone::GetGridLines (MgCoordinateSystemGridBoundary* frameBoundary,
+                                                                              MgCoordinateSystemGridSpecification* specification)
+{
+    // For now, we just call the generic OneGrid grid line function.
+    // Later on we might need to add some special logic for zones 31
+    // through 37 in the higher northern longitudes.
+    MgCoordinateSystemGridLineCollection* gridLines = CCoordinateSystemOneGrid::GetGridLines (specification);
+    return dynamic_cast<CCoordinateSystemGridLineCollection*>(gridLines);
+}
+CCoordinateSystemGridLineCollection* CCoordinateSystemMgrsZone::GetGraticuleLines (MgCoordinateSystemGridBoundary* frameBoundary,
+                                                                                   MgCoordinateSystemGridSpecification* specification)
+{
+    const INT32 maxPoints = 512;
+
+    INT32 index;
+    INT32 regionCount;
+    double value;
+    double precision;
+    double lngMin, lngMax;
+    double latMin,latMax;
+    STRING designation;
+   
+    Ptr<MgCoordinateXY> fromPoint;
+    Ptr<MgCoordinateXY> toPoint;
+    Ptr<MgCoordinateSystem> llCRS;
+    Ptr<MgCoordinateSystem> frameCRS;
+    Ptr<MgCoordinateSystemTransform> toFrameTransform;
+    Ptr<CCoordinateSystemMgrsMajorRegion> regionPtr;
+    Ptr<CCoordinateSystemMgrsMajorRegionCollection> regionCollection;
+    Ptr<MgLineStringCollection> lineStrCollectionPtr;
+    Ptr<CCoordinateSystemMgrsZoneCollection> mjrZoneCollection;
+    Ptr<MgLineString> lineString;
+    Ptr<MgLineStringCollection> lineStringCollection;
+    Ptr<CCoordinateSystemGridLine> gridLine;
+
+    MgCoordinateSystemFactory csFactory;
+
+    Ptr<CCoordinateSystemGridLineCollection> gridLineCollection = new CCoordinateSystemGridLineCollection ();
+
+    MG_TRY ()
+        fromPoint = new MgCoordinateXY ();
+        toPoint = new MgCoordinateXY ();
+        CCoordinateSystemGridSpecification* mySpecPtr = dynamic_cast<CCoordinateSystemGridSpecification*>(specification);
+        precision = mySpecPtr->GetCurvePrecision (m_GridCRS);
+ 
+        // To be are successful, we'll need a Transform which will convert
+        // 'LL' to the frame coordinate system.
+        llCRS = csFactory.CreateFromCode (L"LL");
+        frameCRS = GetFrameCRS ();
+        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 this
+        // grid in geographic coordinate form, and work from there.
+        GetGeographicExtents (lngMin,lngMax,latMin,latMax);
+        
+        regionCollection = new CCoordinateSystemMgrsMajorRegionCollection (m_UtmZone,latMin,latMax);
+        if (regionCollection != 0)
+        {
+            // Draw the east/west lines, i.e. the lines of constant latitude.
+            regionCount = regionCollection->GetCount ();
+            for (index = 0;index < regionCount;index += 1)
+            {
+                // We have a region.
+                regionPtr = regionCollection->GetItem (index);
+                value = regionPtr->GetSouthEdgeLat ();
+                fromPoint->SetX (regionPtr->GetWestEdgeLng ());
+                fromPoint->SetY (value);
+                toPoint->SetX (regionPtr->GetEastEdgeLng ());
+                toPoint->SetY (value);
+                lineString = toFrameTransform->GridLine (fromPoint,toPoint,precision,m_MaxCurvePoints);
+
+                // 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 string.
+                lineStringCollection = frameBoundary->ClipLineString (lineString);
+                if (lineStringCollection)
+                {
+                    // 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);
+                }
+                if (index == (regionCount - 1))
+                {
+                    value = regionPtr->GetNorthEdgeLat ();
+                    fromPoint->SetX (regionPtr->GetWestEdgeLng ());
+                    fromPoint->SetY (value);
+                    toPoint->SetX (regionPtr->GetEastEdgeLng ());
+                    toPoint->SetY (value);
+                    lineString = toFrameTransform->GridLine (fromPoint,toPoint,precision,m_MaxCurvePoints);
+
+                    // Clip the line to the frame boundary.
+                    lineStringCollection = frameBoundary->ClipLineString (lineString);
+                    if (lineStringCollection)
+                    {
+                        // 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);
+                    }
+                }
+            }
+
+            // Draw the western north/south lines, i.e. the lines of constant
+            // longitude.
+            regionCount = regionCollection->GetCount ();
+            for (index = 0;index < regionCount;index += 1)
+            {
+                // We have a region.
+                regionPtr = regionCollection->GetItem (index);
+                value = regionPtr->GetWestEdgeLng ();
+                fromPoint->SetX (value);
+                fromPoint->SetY (regionPtr->GetSouthEdgeLat ());
+                toPoint->SetX (value);
+                toPoint->SetY (regionPtr->GetNorthEdgeLat ());
+                lineString = toFrameTransform->GridLine (fromPoint,toPoint,precision,m_MaxCurvePoints);
+
+                // Clip the line to the frame boundary.
+                lineStringCollection = frameBoundary->ClipLineString (lineString);
+                if (lineStringCollection)
+                {
+                    // 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);
+                }
+            }
+
+            // Draw the north/south lines, i.e. the lines of constant longitude.
+            regionCount = regionCollection->GetCount ();
+            for (index = 0;index < regionCount;index += 1)
+            {
+                // We have a region.
+                regionPtr = regionCollection->GetItem (index);
+                value = regionPtr->GetEastEdgeLng ();
+                fromPoint->SetX (value);
+                fromPoint->SetY (regionPtr->GetSouthEdgeLat ());
+                toPoint->SetX (value);
+                toPoint->SetY (regionPtr->GetNorthEdgeLat ());
+                lineString = toFrameTransform->GridLine (fromPoint,toPoint,precision,m_MaxCurvePoints);
+
+                // 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 string.
+                lineStringCollection = frameBoundary->ClipLineString (lineString);
+                if (lineStringCollection)
+                {
+                    // 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"MgCoordinateSystemMgrsZone::GetGraticuleLines")
+   return gridLineCollection.Detach ();
+}
 INT32 CCoordinateSystemMgrsZone::GetUtmZoneNbr (void)
 {
     // m_UtmZoneNbr is positive for northern hemisphere, negative for the
@@ -99,17 +262,11 @@
 {
     const INT32 maxPoints = 512;
 
-    wchar_t gridZoneLetter;
-    INT32 utmZoneNbr;
-    INT32 gridZoneIndex;
-    INT32 latIdx, firstLat, lastLat;
-    double delta;
-    double centralMeridian;
+    INT32 index;
     double lngMin, lngMax;
     double latMin,latMax;
     STRING designation;
-    wchar_t wcBufr [128];
- 
+
     Ptr<MgCoordinate> southwest;
     Ptr<MgCoordinate> northeast;
     Ptr<MgCoordinateSystem> llCRS;
@@ -117,6 +274,8 @@
     Ptr<MgCoordinateSystemTransform> toFrameTransform;
     Ptr<CCoordinateSystemGridBoundary> rgnBoundary;
     Ptr<CCoordinateSystemGridRegion> pMjrRegion;
+    Ptr<CCoordinateSystemMgrsMajorRegion> regionPtr;
+    Ptr<CCoordinateSystemMgrsMajorRegionCollection> regionCollection;
 
     MgCoordinateSystemFactory csFactory;
 
@@ -134,127 +293,28 @@
         // 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))
+        
+        regionCollection = new CCoordinateSystemMgrsMajorRegionCollection (m_UtmZone,latMin,latMax);
+        if (regionCollection != 0)
         {
-            // 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;
-
-            // Need to account for the fact that the frame boundary may cross
-            // 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)));
-            delta = fabs (fmod (latMax,8.0));
-            lastLat = static_cast<INT32>(latMax + ((latMax >= 0.0) ? (8.0 - delta) : -delta));
-
-            // 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 > 80)
+            INT32 regionCount = regionCollection->GetCount ();
+            for (index = 0;index < regionCount;index += 1)
             {
-                lastLat = 80;
+                // We have a region.
+                regionPtr = regionCollection->GetItem (index);
+                southwest->SetX (regionPtr->GetWestEdgeLng ());
+                southwest->SetY (regionPtr->GetSouthEdgeLat ());
+                northeast->SetX (regionPtr->GetEastEdgeLng ());
+                northeast->SetY (regionPtr->GetNorthEdgeLat ());
+                designation = regionPtr->GetDesignation ();
+                pMjrRegion = new CCoordinateSystemGridRegion (designation,frameBoundary,
+                                                                          toFrameTransform,
+                                                                          southwest,
+                                                                          northeast,
+                                                                          curvePrecision,
+                                                                          maxPoints);
+                m_RegionCollection->Add (pMjrRegion);
             }
-
-            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);
-                southwest->SetY (latMin);
-                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);
-                swprintf (wcBufr,128,L"%d%c",utmZoneNbr,gridZoneLetter);
-                STRING designation (wcBufr);
-                if (!designation.empty ())
-                {
-                    // Construct the region object and add it to the region collection.
-                    pMjrRegion = new CCoordinateSystemGridRegion (designation,frameBoundary,
-                                                                              toFrameTransform,
-                                                                              southwest,
-                                                                              northeast,
-                                                                              curvePrecision,
-                                                                              maxPoints);
-                    m_RegionCollection->Add (pMjrRegion);
-                }
-            }
         }
         else if (m_UtmZone == 61)
         {

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.h	2009-11-20 17:56:28 UTC (rev 4351)
@@ -53,6 +53,10 @@
                                INT8 letteringScheme);
     ~CCoordinateSystemMgrsZone (void);
 
+    CCoordinateSystemGridLineCollection* GetGridLines (MgCoordinateSystemGridBoundary* frameBoundary,
+                                                       MgCoordinateSystemGridSpecification* specification);
+    CCoordinateSystemGridLineCollection* GetGraticuleLines (MgCoordinateSystemGridBoundary* frameBoundary,
+                                                            MgCoordinateSystemGridSpecification* specification);
     CCoordinateSystemGridRegionCollection* GetGridRegions (MgCoordinateSystemGridBoundary* frameBoundary,
                                                            MgCoordinateSystemGridSpecification* specification);
     INT32 GetUtmZoneNbr (void);
@@ -105,100 +109,3 @@
 } // End of namespace
 
 #endif //_CCOORDINATESYSTEMMGRSZONE_H_
-//
-//  Copyright (C) 2004-2009 by Autodesk, Inc.
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of version 2.1 of the GNU Lesser
-//  General Public License as published by the Free Software Foundation.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-#ifndef _CCOORDINATESYSTEMMGRSZONE_H_
-#define _CCOORDINATESYSTEMMGRSZONE_H_
-
-namespace CSLibrary
-{
-
-//=============================================================================
-// MGRS grids can cross UTM zone boundaries, which means that an MGRS grid may
-// consist of multiple generic grids.  Thus, we have an object named
-// CCoordinateSystemMgrsZone which represents a single zone of a multiple
-// zone MGRS grid.  The higher level CCoordinateSystemMgrs object carries a
-// collection of these objects.
-//
-// In this object:
-// * UtmZone is an integer value indicating the UTM zone where positive means
-//   northern hemisphere, negative means southern hemisphere, and 61 means
-//   a polr region (i.e. UPS).  Zero indicates not set yet or invalid.
-// * GridCsCode is the key name of the grid coordinate system which will be
-//   used to generate the grid.  This definition will be datum dependent.
-// * ZoneBoundary starts off being an envelope of the entire UTM zone, and
-//   is eventually reduced to be that portion of the Viewport boundary which
-//   is covered by this grid object.
-// * 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.
-class CCoordinateSystemMgrsZone : public CCoordinateSystemOneGrid
-{
-public:
-    //
-    CCoordinateSystemMgrsZone (MgCoordinateSystemGridBoundary* frameBoundary,
-                               INT32 utmZoneNbr,
-                               bool useFrameDatum,
-                               MgCoordinateSystem* frameCS,
-                               INT8 letteringScheme);
-    ~CCoordinateSystemMgrsZone (void);
-
-    CCoordinateSystemGridRegionCollection* GetGridRegions (MgCoordinateSystemGridSpecification* specification);
-protected:
-    void BuildRegionCollection (MgCoordinateSystemGridSpecification* specification);
-private:
-    void BuildMajorRegions (double boundaryPrecision);
-    void BuildMinorRegions (double boundaryPrecision);
-    // Data members
-    INT32 m_UtmZone;
-    INT8 m_LetteringScheme;
-    Ptr<CCoordinateSystemGridRegionCollection> m_RegionCollection;
-
-    // Not implemented
-    CCoordinateSystemMgrsZone (const CCoordinateSystemMgrsZone& source);
-    CCoordinateSystemMgrsZone& operator= (const CCoordinateSystemMgrsZone& rhs);
-};
-
-class CCoordinateSystemMgrsZoneCollection : public MgGuardDisposable
-{
-public:
-    CCoordinateSystemMgrsZoneCollection (void);
-    ~CCoordinateSystemMgrsZoneCollection (void);
-
-    INT32 GetCount () const;
-    CCoordinateSystemMgrsZone* GetItem (INT32 index) const;
-    void RemoveAt (INT32 index);
-    void Clear();
-    void SetItem (INT32 index, CCoordinateSystemMgrsZone* value);
-    void Add (CCoordinateSystemMgrsZone* value);
-
-protected:
-    void Dispose (void);
-
-private:
-    // Data Members
-    Ptr<MgDisposableCollection> m_OneGridCollection;
-
-    // Member functions not implemented.
-    CCoordinateSystemMgrsZoneCollection  (const CCoordinateSystemMgrsZoneCollection & source);
-    CCoordinateSystemMgrsZoneCollection& operator= (const CCoordinateSystemMgrsZoneCollection & rhs);
-};
-
-} // End of namespace
-
-#endif //_CCOORDINATESYSTEMMGRSZONE_H_

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp	2009-11-20 17:56:28 UTC (rev 4351)
@@ -79,7 +79,11 @@
     m_GridCRS = SAFE_ADDREF (gridCRS);
     m_FrameCRS = SAFE_ADDREF (frameCRS);
     m_ToFrameXform = csFactory.GetTransform (m_GridCRS,m_FrameCRS);
+    m_ToFrameXform->IgnoreDatumShiftWarning (true);
+    m_ToFrameXform->IgnoreOutsideDomainWarning (true);
     m_ToGridXform = csFactory.GetTransform (m_FrameCRS,m_GridCRS);
+    m_ToGridXform->IgnoreDatumShiftWarning (true);
+    m_ToGridXform->IgnoreOutsideDomainWarning (true);
 }
 bool CCoordinateSystemOneGrid::IsGeographic (void)
 {
@@ -146,7 +150,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 = mySpecPtr->GetCurvePrecision ();
+        precision = mySpecPtr->GetCurvePrecision (m_GridCRS);
         GenerateGridBoundary (precision);
 
         // Get the extents of the frame boundary, and then convert them to
@@ -202,8 +206,8 @@
             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.
+            // actually leave, and then re-enter, the grid boundary, so the
+            // result can be a multi-line string.
             lineStringCollection = m_FrameBoundary->ClipLineString (lineString);
             if (lineStringCollection)
             {
@@ -215,7 +219,7 @@
             }
         }
 
-        // Second loop, the south/north lines, starting at the western edge
+        // Second loop, the south/north lines, starting at the western edged
         // proceeding to the east.
         increment = mySpecPtr->GetEastingIncrement (gridCrsUnitCode);
         for (value = eastMin;value <= eastMax;value += increment)
@@ -442,6 +446,8 @@
     MG_TRY ()
         llCRS = csFactory.CreateFromCode (L"LL");
         llTransform = csFactory.GetTransform(m_FrameCRS,llCRS);
+        llTransform->IgnoreDatumShiftWarning (true);
+        llTransform->IgnoreOutsideDomainWarning (true);
         pPolygon = m_FrameBoundary->GetBoundary (llTransform,precision);
         llBoundary = csFactory.GridBoundary (pPolygon);
         llBoundary->GetBoundaryExtents (longMin,longMax,latMin,latMax);

Modified: trunk/MgDev/Common/Geometry/Geometry.vcproj
===================================================================
--- trunk/MgDev/Common/Geometry/Geometry.vcproj	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/Geometry/Geometry.vcproj	2009-11-20 17:56:28 UTC (rev 4351)
@@ -2929,10 +2929,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\CoordinateSystem\CoordSysMgrsGridScale.h"
-				>
-			</File>
-			<File
 				RelativePath="..\CoordinateSystem\CoordSysMgrsZone.cpp"
 				>
 			</File>
@@ -3462,6 +3458,14 @@
 			>
 		</File>
 		<File
+			RelativePath="..\CoordinateSystem\CoordSysMgrsMajorRegion.cpp"
+			>
+		</File>
+		<File
+			RelativePath="..\CoordinateSystem\CoordSysMgrsMajorRegion.h"
+			>
+		</File>
+		<File
 			RelativePath="..\CoordinateSystem\CoordSysWktFailureCache.cpp"
 			>
 		</File>

Modified: trunk/MgDev/Common/Geometry/Makefile.am
===================================================================
--- trunk/MgDev/Common/Geometry/Makefile.am	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/Geometry/Makefile.am	2009-11-20 17:56:28 UTC (rev 4351)
@@ -38,6 +38,7 @@
   ../CoordinateSystem/CoordSysGrids.cpp \
   ../CoordinateSystem/CoordSysMgrsZone.cpp \
   ../CoordinateSystem/CoordSysMgrs.cpp \
+  ../CoordinateSystem/CoordSysMgrsMajorRegion.cpp \
   ../CoordinateSystem/CoordSysOneGrid.cpp
 
 include_SOURCES = \
@@ -173,6 +174,7 @@
   ../CoordinateSystem/CoordSysGrids.cpp \
   ../CoordinateSystem/CoordSysMgrsZone.cpp \
   ../CoordinateSystem/CoordSysMgrs.cpp \
+  ../CoordinateSystem/CoordSysMgrsMajorRegion.cpp \
   ../CoordinateSystem/CoordSysOneGrid.cpp
 
 noinst_HEADERS = $(include_SOURCES) \
@@ -385,6 +387,7 @@
   ../CoordinateSystem/CoordSysGrids.h \
   ../CoordinateSystem/CoordSysMgrsZone.h \
   ../CoordinateSystem/CoordSysMgrs.h \
+  ../CoordinateSystem/CoordSysMgrsMajorRegion.h \
   ../CoordinateSystem/CoordSysOneGrid.h
 
 INCLUDES = \

Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp	2009-11-19 23:23:42 UTC (rev 4350)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp	2009-11-20 17:56:28 UTC (rev 4351)
@@ -528,7 +528,9 @@
                                                                   MgCoordinate* seg2From,
                                                                   MgCoordinate* seg2To)
 {
-    INT32 status (-7);          // until we know different.
+    bool preciseFrom;
+    bool preciseTo;
+    INT32 status (-1);          // until we know different.
 
     double delX1, delY1;
     double delX2, delY2;
@@ -574,13 +576,14 @@
         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.
+            // value to test if the resulting point is on the segment.
+            preciseFrom = MgMathUtility::DblCmp (result->GetX(),seg1From->GetX());
+            preciseTo = MgMathUtility::DblCmp (result->GetX(),seg1To->GetX());
             if (delX1 >= 0.0)
             {
                 // X increases from the 'from' point to the 'to' point.
-                if (result->GetX() > seg1From->GetX() && result->GetX() <= seg1To->GetX())
+                if ((result->GetX() >= seg1From->GetX() || preciseFrom) &&
+                    (result->GetX() <= seg1To->GetX()  || preciseTo))
                 {
                     status |= 1;
                 }
@@ -588,20 +591,32 @@
             else
             {
                 // X decreases from the 'from' point to the 'to' point.
-                if (result->GetX() < seg1From->GetX() && result->GetX() >= seg1To->GetX())
+                if ((result->GetX() <= seg1From->GetX() || preciseFrom) &&
+                    (result->GetX() >= seg1To->GetX()   || preciseTo)) 
                 {
                     status |= 1;
                 }
             }
+            if (preciseFrom)
+            {
+                status |= 4;
+            }
+            if (preciseTo)
+            {
+                status |= 8;
+            }
         }
         else
         {
-            // First segment is more verical than horizontal. We will use the y
+            // First segment is more vertical than horizontal. We will use the Y
             // value to test if the resulting point is on the segment.
+            preciseFrom = MgMathUtility::DblCmp (result->GetY(),seg1From->GetY());
+            preciseTo = MgMathUtility::DblCmp (result->GetY(),seg1To->GetY());
             if (delY1 >= 0.0)
             {
                 // Y increases from the 'from' point to the 'to' point.
-                if (result->GetY() > seg1From->GetY() && result->GetY() <= seg1To->GetY())
+                if ((result->GetY() >= seg1From->GetY() || preciseFrom) &&
+                    (result->GetY() <= seg1To->GetY()   || preciseTo))
                 {
                     status |= 1;
                 }
@@ -609,47 +624,80 @@
             else
             {
                 // Y increases from the 'from' point to the 'to' point.
-                if (result->GetY() < seg1From->GetY() && result->GetY() >= seg1To->GetY())
+                if ((result->GetY() <= seg1From->GetY() || preciseFrom) &&
+                    (result->GetY() >= seg1To->GetY()   || preciseTo))
                 {
                     status |= 1;
                 }
             }
+            if (preciseFrom)
+            {
+                status |= 4;
+            }
+            if (preciseTo)
+            {
+                status |= 8;
+            }
         }
 
         // Same stuff with the second segment, sans comments.
         if (fabs (delX2) > fabs (delY2))
         {
+            preciseFrom = MgMathUtility::DblCmp (result->GetX(),seg2From->GetX());
+            preciseTo = MgMathUtility::DblCmp (result->GetX(),seg2To->GetX());
             if (delX2 >= 0.0)
             {
-                if (result->GetX() > seg2From->GetX() && result->GetX() <= seg2To->GetX())
+                if ((result->GetX() >= seg2From->GetX() || preciseFrom) &&
+                    (result->GetX() <= seg2To->GetX()   || preciseTo))
                 {
                     status |= 2;
                 }
             }
             else
             {
-                if (result->GetX() < seg2From->GetX() && result->GetX() >= seg2To->GetX())
+                if ((result->GetX() <= seg2From->GetX() || preciseFrom) &&
+                    (result->GetX() >= seg2To->GetX()   || preciseTo))
                 {
                     status |= 2;
                 }
             }
+            if (preciseFrom)
+            {
+                status |= 16;
+            }
+            if (preciseTo)
+            {
+                status |= 32;
+            }
         }
         else
         {
+            preciseFrom = MgMathUtility::DblCmp (result->GetY(),seg2From->GetY());
+            preciseTo = MgMathUtility::DblCmp (result->GetY(),seg2To->GetY());
             if (delY2 >= 0.0)
             {
-                if (result->GetY() > seg2From->GetY() && result->GetY() <= seg2To->GetY())
+                if ((result->GetY() >= seg2From->GetY() || preciseFrom) &&
+                    (result->GetY() <= seg2To->GetY()   || preciseTo))
                 {
                     status |= 2;
                 }
             }
             else
             {
-                if (result->GetY() < seg2From->GetY() && result->GetY() >= seg2To->GetY())
+                if ((result->GetY() <= seg2From->GetY() || preciseFrom) &&
+                    (result->GetY() >= seg2To->GetY()   || preciseTo))
                 {
                     status |= 2;
                 }
             }
+            if (preciseFrom)
+            {
+                status |= 16;
+            }
+            if (preciseTo)
+            {
+                status |= 32;
+            }
         }
     }
     return status;
@@ -695,11 +743,21 @@
         polyFrom = polyTo;
         polyTo = polyItr->GetCurrent ();
         status = SegmentIntersection (intersection,polyFrom,polyTo,segFrom,segTo);
-        if (status == 3)
+        
+        // If the intersection is precisely on the 'From' point of the polygon segment,
+        // we're not interested.  It will show up again when that point becomes a
+        // 'To' point on the polygon.
+        if ((status & 4) == 4)
         {
-            // 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.
+            continue;
+        }
+        if ((status & 3) == 3)
+        {
+            // We have an intersection of interest to us.  That is, an intersection
+            // point which resides on both lines, but not presisely on the 'From"
+            // point of the polygon segment.  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());
             insertIndex = AddToCoordinateCollection (coordinateCollection,newPoint,segFrom);
             if (insertIndex != 0)



More information about the mapguide-commits mailing list