LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mssqlspatial - ogrmssqlgeometrywriter.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 345 0.0 %
Date: 2024-05-04 12:52:34 Functions: 0 16 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MSSQL Spatial driver
       4             :  * Purpose:  Implements OGRMSSQLGeometryWriter class to write native
       5             :  *SqlGeometries. Author:   Tamas Szekeres, szekerest at gmail.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2016, Tamas Szekeres
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_conv.h"
      30             : #include "ogr_mssqlspatial.h"
      31             : 
      32             : /*   SqlGeometry/SqlGeography serialization format
      33             : 
      34             : Simple Point (SerializationProps & IsSinglePoint)
      35             :   [SRID][0x01][SerializationProps][Point][z][m]
      36             : 
      37             : Simple Line Segment (SerializationProps & IsSingleLineSegment)
      38             :   [SRID][0x01][SerializationProps][Point1][Point2][z1][z2][m1][m2]
      39             : 
      40             : Complex Geometries
      41             :   [SRID][VersionAttribute][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN]
      42             :   [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape]
      43             : 
      44             : Complex Geometries (FigureAttribute == Curve)
      45             :   [SRID][VersionAttribute][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN]
      46             :   [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape][NumSegments][SegmentType]..[SegmentType]
      47             : 
      48             : VersionAttribute (1 byte)
      49             :   0x01 = Katmai (MSSQL2008+)
      50             :   0x02 = Denali (MSSQL2012+)
      51             : 
      52             : SRID
      53             :   Spatial Reference Id (4 bytes)
      54             : 
      55             : SerializationProps (bitmask) 1 byte
      56             :   0x01 = HasZValues
      57             :   0x02 = HasMValues
      58             :   0x04 = IsValid
      59             :   0x08 = IsSinglePoint
      60             :   0x10 = IsSingleLineSegment
      61             :   0x20 = IsLargerThanAHemisphere
      62             : 
      63             : Point (2-4)x8 bytes, size depends on SerializationProps & HasZValues &
      64             : HasMValues [x][y]                  - SqlGeometry [latitude][longitude]   -
      65             : SqlGeography
      66             : 
      67             : Figure
      68             :   [FigureAttribute][PointOffset]
      69             : 
      70             : FigureAttribute - Katmai (1 byte)
      71             :   0x00 = Interior Ring
      72             :   0x01 = Stroke
      73             :   0x02 = Exterior Ring
      74             : 
      75             : FigureAttribute - Denali (1 byte)
      76             :   0x00 = None
      77             :   0x01 = Line
      78             :   0x02 = Arc
      79             :   0x03 = Curve
      80             : 
      81             : Shape
      82             :   [ParentFigureOffset][FigureOffset][ShapeType]
      83             : 
      84             : ShapeType (1 byte)
      85             :   0x00 = Unknown
      86             :   0x01 = Point
      87             :   0x02 = LineString
      88             :   0x03 = Polygon
      89             :   0x04 = MultiPoint
      90             :   0x05 = MultiLineString
      91             :   0x06 = MultiPolygon
      92             :   0x07 = GeometryCollection
      93             :   -- Denali
      94             :   0x08 = CircularString
      95             :   0x09 = CompoundCurve
      96             :   0x0A = CurvePolygon
      97             :   0x0B = FullGlobe
      98             : 
      99             : SegmentType (1 byte)
     100             :   0x00 = Line
     101             :   0x01 = Arc
     102             :   0x02 = FirstLine
     103             :   0x03 = FirstArc
     104             : 
     105             : */
     106             : 
     107             : /************************************************************************/
     108             : /*                         Geometry writer macros                       */
     109             : /************************************************************************/
     110             : 
     111             : #define WriteInt32(nPos, value) (*((unsigned int *)(pszData + (nPos))) = value)
     112             : 
     113             : #define WriteByte(nPos, value) (pszData[nPos] = value)
     114             : 
     115             : #define WriteDouble(nPos, value) (*((double *)(pszData + (nPos))) = value)
     116             : 
     117             : #define ParentOffset(iShape) (nShapePos + (iShape)*9)
     118             : #define FigureOffset(iShape) (nShapePos + (iShape)*9 + 4)
     119             : #define ShapeType(iShape) (nShapePos + (iShape)*9 + 8)
     120             : #define SegmentType(iSegment) (nSegmentPos + (iSegment))
     121             : 
     122             : #define FigureAttribute(iFigure) (nFigurePos + (iFigure)*5)
     123             : #define PointOffset(iFigure) (nFigurePos + (iFigure)*5 + 1)
     124             : 
     125             : #define WriteX(iPoint, value) (WriteDouble(nPointPos + 16 * (iPoint), value))
     126             : #define WriteY(iPoint, value)                                                  \
     127             :     (WriteDouble(nPointPos + 16 * (iPoint) + 8, value))
     128             : #define WriteZ(iPoint, value)                                                  \
     129             :     (WriteDouble(nPointPos + 16 * nNumPoints + 8 * (iPoint), value))
     130             : #define WriteM(iPoint, value)                                                  \
     131             :     (WriteDouble(nPointPos + 24 * nNumPoints + 8 * (iPoint), value))
     132             : 
     133             : /************************************************************************/
     134             : /*                   OGRMSSQLGeometryWriter()                           */
     135             : /************************************************************************/
     136             : 
     137           0 : OGRMSSQLGeometryWriter::OGRMSSQLGeometryWriter(OGRGeometry *poGeometry,
     138           0 :                                                int nGeomColumnType, int nSRS)
     139             : {
     140           0 :     nColType = nGeomColumnType;
     141           0 :     nSRSId = nSRS;
     142           0 :     poGeom2 = poGeometry;
     143             : 
     144           0 :     chProps = 0;
     145             : 
     146             :     /* calculate required buffer length and the attributes */
     147           0 :     nPointSize = 16;
     148           0 :     if (poGeom2->getCoordinateDimension() == 3)
     149             :     {
     150           0 :         chProps |= SP_HASZVALUES;
     151           0 :         nPointSize += 8;
     152             :     }
     153             : 
     154           0 :     if (poGeom2->IsMeasured())
     155             :     {
     156           0 :         chProps |= SP_HASMVALUES;
     157           0 :         nPointSize += 8;
     158             :     }
     159             : 
     160           0 :     iPoint = 0;
     161           0 :     nNumPoints = 0;
     162           0 :     iFigure = 0;
     163           0 :     nNumFigures = 0;
     164           0 :     iShape = 0;
     165           0 :     nNumShapes = 0;
     166           0 :     iSegment = 0;
     167           0 :     nNumSegments = 0;
     168             : 
     169             :     /* calculate points figures, shapes and segments*/
     170           0 :     chVersion = VA_KATMAI;
     171           0 :     TrackGeometry(poGeom2);
     172           0 :     ++nNumShapes;
     173             : 
     174           0 :     OGRwkbGeometryType geomType = wkbFlatten(poGeom2->getGeometryType());
     175             : 
     176           0 :     if (nNumPoints == 1 && geomType == wkbPoint)
     177             :     {
     178             :         /* writing a single point */
     179           0 :         chProps |= SP_ISSINGLEPOINT | SP_ISVALID;
     180           0 :         nPointPos = 6;
     181           0 :         nLen = nPointPos + nPointSize;
     182             :     }
     183           0 :     else if (nNumPoints == 2 && geomType == wkbLineString)
     184             :     {
     185             :         /* writing a single line */
     186           0 :         chProps |= SP_ISSINGLELINESEGMENT | SP_ISVALID;
     187           0 :         nPointPos = 6;
     188           0 :         nLen = nPointPos + nPointSize * 2;
     189             :     }
     190             :     else
     191             :     {
     192             :         /* complex geometry */
     193           0 :         nPointPos = 10;
     194           0 :         nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
     195           0 :         nShapePos = nFigurePos + 5 * nNumFigures + 4;
     196           0 :         nSegmentPos = nShapePos + 9 * nNumShapes + 4;
     197           0 :         if (nNumSegments > 0)
     198           0 :             nLen = nSegmentPos + nNumSegments;
     199             :         else
     200           0 :             nLen = nShapePos + 9 * nNumShapes;
     201             :     }
     202           0 : }
     203             : 
     204             : /************************************************************************/
     205             : /*                         WritePoint()                                 */
     206             : /************************************************************************/
     207             : 
     208           0 : void OGRMSSQLGeometryWriter::WritePoint(OGRPoint *poGeom)
     209             : {
     210           0 :     if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     211           0 :         WritePoint(poGeom->getX(), poGeom->getY(), poGeom->getZ(),
     212             :                    poGeom->getM());
     213           0 :     else if (chProps & SP_HASZVALUES)
     214           0 :         WritePoint(poGeom->getX(), poGeom->getY(), poGeom->getZ());
     215           0 :     else if (chProps & SP_HASMVALUES)
     216           0 :         WritePoint(poGeom->getX(), poGeom->getY(), poGeom->getM());
     217             :     else
     218           0 :         WritePoint(poGeom->getX(), poGeom->getY());
     219           0 : }
     220             : 
     221           0 : void OGRMSSQLGeometryWriter::WritePoint(double x, double y)
     222             : {
     223           0 :     if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     224             :     {
     225           0 :         WriteY(iPoint, x);
     226           0 :         WriteX(iPoint, y);
     227             :     }
     228             :     else
     229             :     {
     230           0 :         WriteX(iPoint, x);
     231           0 :         WriteY(iPoint, y);
     232             :     }
     233           0 :     ++iPoint;
     234           0 : }
     235             : 
     236           0 : void OGRMSSQLGeometryWriter::WritePoint(double x, double y, double z)
     237             : {
     238           0 :     WriteZ(iPoint, z);
     239           0 :     WritePoint(x, y);
     240           0 : }
     241             : 
     242           0 : void OGRMSSQLGeometryWriter::WritePoint(double x, double y, double z, double m)
     243             : {
     244           0 :     WriteZ(iPoint, z);
     245           0 :     WriteM(iPoint, m);
     246           0 :     WritePoint(x, y);
     247           0 : }
     248             : 
     249             : /************************************************************************/
     250             : /*                         WriteSimpleCurve()                           */
     251             : /************************************************************************/
     252             : 
     253           0 : void OGRMSSQLGeometryWriter::WriteSimpleCurve(OGRSimpleCurve *poGeom,
     254             :                                               int iStartIndex, int nCount,
     255             :                                               bool bReversePoints)
     256             : {
     257           0 :     if (bReversePoints && iStartIndex == 0)
     258             :     {
     259           0 :         poGeom->reversePoints();
     260             :     }
     261             : 
     262           0 :     if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     263             :     {
     264           0 :         for (int i = iStartIndex; i < iStartIndex + nCount; i++)
     265           0 :             WritePoint(poGeom->getX(i), poGeom->getY(i), poGeom->getZ(i),
     266           0 :                        poGeom->getM(i));
     267             :     }
     268           0 :     else if (chProps & SP_HASZVALUES)
     269             :     {
     270           0 :         for (int i = iStartIndex; i < iStartIndex + nCount; i++)
     271           0 :             WritePoint(poGeom->getX(i), poGeom->getY(i), poGeom->getZ(i));
     272             :     }
     273           0 :     else if (chProps & SP_HASMVALUES)
     274             :     {
     275           0 :         for (int i = iStartIndex; i < iStartIndex + nCount; i++)
     276           0 :             WritePoint(poGeom->getX(i), poGeom->getY(i), poGeom->getM(i));
     277             :     }
     278             :     else
     279             :     {
     280           0 :         for (int i = iStartIndex; i < iStartIndex + nCount; i++)
     281           0 :             WritePoint(poGeom->getX(i), poGeom->getY(i));
     282             :     }
     283           0 : }
     284             : 
     285           0 : void OGRMSSQLGeometryWriter::WriteSimpleCurve(OGRSimpleCurve *poGeom,
     286             :                                               int iStartIndex,
     287             :                                               bool bReversePoints)
     288             : {
     289           0 :     WriteSimpleCurve(poGeom, iStartIndex, poGeom->getNumPoints() - iStartIndex,
     290             :                      bReversePoints);
     291           0 : }
     292             : 
     293           0 : void OGRMSSQLGeometryWriter::WriteSimpleCurve(OGRSimpleCurve *poGeom,
     294             :                                               bool bReversePoints)
     295             : {
     296           0 :     WriteSimpleCurve(poGeom, 0, poGeom->getNumPoints(), bReversePoints);
     297           0 : }
     298             : 
     299             : /************************************************************************/
     300             : /*                         WriteCompoundCurve()                         */
     301             : /************************************************************************/
     302             : 
     303           0 : void OGRMSSQLGeometryWriter::WriteCompoundCurve(OGRCompoundCurve *poGeom)
     304             : {
     305             :     OGRSimpleCurve *poSubGeom;
     306           0 :     WriteByte(FigureAttribute(iFigure), FA_CURVE);
     307           0 :     WriteInt32(PointOffset(iFigure), iPoint);
     308           0 :     for (int i = 0; i < poGeom->getNumCurves(); i++)
     309             :     {
     310           0 :         poSubGeom = poGeom->getCurve(i)->toSimpleCurve();
     311           0 :         switch (wkbFlatten(poSubGeom->getGeometryType()))
     312             :         {
     313           0 :             case wkbLineString:
     314           0 :                 if (i == 0)
     315           0 :                     WriteSimpleCurve(poSubGeom, false);
     316             :                 else
     317           0 :                     WriteSimpleCurve(poSubGeom, 1, false);
     318           0 :                 for (int j = 1; j < poSubGeom->getNumPoints(); j++)
     319             :                 {
     320           0 :                     if (j == 1)
     321           0 :                         WriteByte(SegmentType(iSegment++), SMT_FIRSTLINE);
     322             :                     else
     323           0 :                         WriteByte(SegmentType(iSegment++), SMT_LINE);
     324             :                 }
     325           0 :                 break;
     326             : 
     327           0 :             case wkbCircularString:
     328           0 :                 if (i == 0)
     329           0 :                     WriteSimpleCurve(poSubGeom, false);
     330             :                 else
     331           0 :                     WriteSimpleCurve(poSubGeom, 1, false);
     332           0 :                 for (int j = 2; j < poSubGeom->getNumPoints(); j += 2)
     333             :                 {
     334           0 :                     if (j == 2)
     335           0 :                         WriteByte(SegmentType(iSegment++), SMT_FIRSTARC);
     336             :                     else
     337           0 :                         WriteByte(SegmentType(iSegment++), SMT_ARC);
     338             :                 }
     339           0 :                 break;
     340             : 
     341           0 :             default:
     342           0 :                 break;
     343             :         }
     344             :     }
     345           0 : }
     346             : 
     347             : /************************************************************************/
     348             : /*                         WriteCurve()                                 */
     349             : /************************************************************************/
     350             : 
     351           0 : void OGRMSSQLGeometryWriter::WriteCurve(OGRCurve *poGeom, bool bReversePoints)
     352             : {
     353           0 :     switch (wkbFlatten(poGeom->getGeometryType()))
     354             :     {
     355           0 :         case wkbLineString:
     356             :         case wkbLinearRing:
     357           0 :             WriteByte(FigureAttribute(iFigure), FA_LINE);
     358           0 :             WriteInt32(PointOffset(iFigure), iPoint);
     359           0 :             WriteSimpleCurve(poGeom->toSimpleCurve(), bReversePoints);
     360           0 :             ++iFigure;
     361           0 :             break;
     362             : 
     363           0 :         case wkbCircularString:
     364           0 :             WriteByte(FigureAttribute(iFigure), FA_ARC);
     365           0 :             WriteInt32(PointOffset(iFigure), iPoint);
     366           0 :             WriteSimpleCurve(poGeom->toSimpleCurve(), bReversePoints);
     367           0 :             ++iFigure;
     368           0 :             break;
     369             : 
     370           0 :         case wkbCompoundCurve:
     371           0 :             WriteCompoundCurve(poGeom->toCompoundCurve());
     372           0 :             ++iFigure;
     373           0 :             break;
     374             : 
     375           0 :         default:
     376           0 :             break;
     377             :     }
     378           0 : }
     379             : 
     380             : /************************************************************************/
     381             : /*                         WritePolygon()                               */
     382             : /************************************************************************/
     383             : 
     384           0 : void OGRMSSQLGeometryWriter::WritePolygon(OGRPolygon *poGeom)
     385             : {
     386             :     int r;
     387           0 :     OGRLinearRing *poRing = poGeom->getExteriorRing();
     388             : 
     389           0 :     if (poRing == nullptr)
     390           0 :         return;
     391             : 
     392           0 :     if (chVersion == VA_KATMAI)
     393           0 :         WriteByte(FigureAttribute(iFigure), FA_EXTERIORRING);
     394             :     else
     395           0 :         WriteByte(FigureAttribute(iFigure), FA_LINE);
     396             : 
     397           0 :     WriteInt32(PointOffset(iFigure), iPoint);
     398           0 :     WriteSimpleCurve(poRing, poRing->isClockwise() &&
     399           0 :                                  nColType == MSSQLCOLTYPE_GEOGRAPHY);
     400           0 :     ++iFigure;
     401           0 :     for (r = 0; r < poGeom->getNumInteriorRings(); r++)
     402             :     {
     403             :         /* write interior rings */
     404           0 :         poRing = poGeom->getInteriorRing(r);
     405           0 :         if (chVersion == VA_KATMAI)
     406           0 :             WriteByte(FigureAttribute(iFigure), FA_INTERIORRING);
     407             :         else
     408           0 :             WriteByte(FigureAttribute(iFigure), FA_LINE);
     409             : 
     410           0 :         WriteInt32(PointOffset(iFigure), iPoint);
     411           0 :         WriteSimpleCurve(poRing, !poRing->isClockwise() &&
     412           0 :                                      nColType == MSSQLCOLTYPE_GEOGRAPHY);
     413           0 :         ++iFigure;
     414             :     }
     415             : }
     416             : 
     417             : /************************************************************************/
     418             : /*                         WriteCurvePolygon()                          */
     419             : /************************************************************************/
     420             : 
     421           0 : void OGRMSSQLGeometryWriter::WriteCurvePolygon(OGRCurvePolygon *poGeom)
     422             : {
     423           0 :     if (poGeom->getExteriorRingCurve() == nullptr)
     424           0 :         return;
     425             : 
     426           0 :     WriteCurve(poGeom->getExteriorRingCurve(),
     427           0 :                poGeom->getExteriorRingCurve()->isClockwise() &&
     428           0 :                    nColType == MSSQLCOLTYPE_GEOGRAPHY);
     429           0 :     for (int r = 0; r < poGeom->getNumInteriorRings(); r++)
     430             :     {
     431             :         /* write interior rings */
     432           0 :         WriteCurve(poGeom->getInteriorRingCurve(r),
     433           0 :                    !poGeom->getInteriorRingCurve(r)->isClockwise() &&
     434           0 :                        nColType == MSSQLCOLTYPE_GEOGRAPHY);
     435             :     }
     436             : }
     437             : 
     438             : /************************************************************************/
     439             : /*                         WriteGeometryCollection()                    */
     440             : /************************************************************************/
     441             : 
     442           0 : void OGRMSSQLGeometryWriter::WriteGeometryCollection(
     443             :     OGRGeometryCollection *poGeom, int iParent)
     444             : {
     445           0 :     for (int i = 0; i < poGeom->getNumGeometries(); i++)
     446           0 :         WriteGeometry(poGeom->getGeometryRef(i), iParent);
     447           0 : }
     448             : 
     449             : /************************************************************************/
     450             : /*                         WriteGeometry()                              */
     451             : /************************************************************************/
     452             : 
     453           0 : void OGRMSSQLGeometryWriter::WriteGeometry(OGRGeometry *poGeom, int iParent)
     454             : {
     455             :     /* write shape */
     456           0 :     int iCurrentFigure = iFigure;
     457           0 :     int iCurrentShape = iShape;
     458           0 :     WriteInt32(ParentOffset(iShape), iParent);
     459             : 
     460           0 :     iParent = iShape;
     461             : 
     462           0 :     switch (wkbFlatten(poGeom->getGeometryType()))
     463             :     {
     464           0 :         case wkbPoint:
     465           0 :             WriteByte(ShapeType(iShape++), ST_POINT);
     466           0 :             if (!poGeom->IsEmpty())
     467             :             {
     468           0 :                 if (chVersion == VA_KATMAI)
     469           0 :                     WriteByte(FigureAttribute(iFigure), FA_STROKE);
     470             :                 else
     471           0 :                     WriteByte(FigureAttribute(iFigure), FA_LINE);
     472           0 :                 WriteInt32(PointOffset(iFigure), iPoint);
     473           0 :                 WritePoint(poGeom->toPoint());
     474           0 :                 ++iFigure;
     475             :             }
     476           0 :             break;
     477             : 
     478           0 :         case wkbLineString:
     479           0 :             WriteByte(ShapeType(iShape++), ST_LINESTRING);
     480           0 :             if (!poGeom->IsEmpty())
     481             :             {
     482           0 :                 if (chVersion == VA_KATMAI)
     483           0 :                     WriteByte(FigureAttribute(iFigure), FA_STROKE);
     484             :                 else
     485           0 :                     WriteByte(FigureAttribute(iFigure), FA_LINE);
     486           0 :                 WriteInt32(PointOffset(iFigure), iPoint);
     487           0 :                 WriteSimpleCurve(poGeom->toSimpleCurve(), false);
     488           0 :                 ++iFigure;
     489             :             }
     490           0 :             break;
     491             : 
     492           0 :         case wkbCircularString:
     493           0 :             WriteByte(ShapeType(iShape++), ST_CIRCULARSTRING);
     494           0 :             if (!poGeom->IsEmpty())
     495             :             {
     496           0 :                 if (chVersion == VA_KATMAI)
     497           0 :                     WriteByte(FigureAttribute(iFigure), FA_STROKE);
     498             :                 else
     499           0 :                     WriteByte(FigureAttribute(iFigure), FA_ARC);
     500           0 :                 WriteInt32(PointOffset(iFigure), iPoint);
     501           0 :                 WriteSimpleCurve(poGeom->toSimpleCurve(), false);
     502           0 :                 ++iFigure;
     503             :             }
     504           0 :             break;
     505             : 
     506           0 :         case wkbCompoundCurve:
     507           0 :             WriteByte(ShapeType(iShape++), ST_COMPOUNDCURVE);
     508           0 :             if (!poGeom->IsEmpty())
     509             :             {
     510           0 :                 WriteCompoundCurve(poGeom->toCompoundCurve());
     511           0 :                 ++iFigure;
     512             :             }
     513           0 :             break;
     514             : 
     515           0 :         case wkbPolygon:
     516           0 :             WriteByte(ShapeType(iShape++), ST_POLYGON);
     517           0 :             WritePolygon(poGeom->toPolygon());
     518           0 :             break;
     519             : 
     520           0 :         case wkbCurvePolygon:
     521           0 :             WriteByte(ShapeType(iShape++), ST_CURVEPOLYGON);
     522           0 :             WriteCurvePolygon(poGeom->toCurvePolygon());
     523           0 :             break;
     524             : 
     525           0 :         case wkbMultiPoint:
     526           0 :             WriteByte(ShapeType(iShape++), ST_MULTIPOINT);
     527           0 :             WriteGeometryCollection(poGeom->toGeometryCollection(), iParent);
     528           0 :             break;
     529             : 
     530           0 :         case wkbMultiLineString:
     531           0 :             WriteByte(ShapeType(iShape++), ST_MULTILINESTRING);
     532           0 :             WriteGeometryCollection(poGeom->toGeometryCollection(), iParent);
     533           0 :             break;
     534             : 
     535           0 :         case wkbMultiPolygon:
     536           0 :             WriteByte(ShapeType(iShape++), ST_MULTIPOLYGON);
     537           0 :             WriteGeometryCollection(poGeom->toGeometryCollection(), iParent);
     538           0 :             break;
     539             : 
     540           0 :         case wkbGeometryCollection:
     541           0 :             WriteByte(ShapeType(iShape++), ST_GEOMETRYCOLLECTION);
     542           0 :             WriteGeometryCollection(poGeom->toGeometryCollection(), iParent);
     543           0 :             break;
     544             : 
     545           0 :         default:
     546           0 :             return;
     547             :     }
     548             :     // check if new figures have been added to shape
     549           0 :     WriteInt32(FigureOffset(iCurrentShape),
     550             :                iFigure == iCurrentFigure ? 0xFFFFFFFF : iCurrentFigure);
     551             : }
     552             : 
     553             : /************************************************************************/
     554             : /*                         TrackGeometry()                              */
     555             : /************************************************************************/
     556             : 
     557           0 : void OGRMSSQLGeometryWriter::TrackGeometry(OGRGeometry *poGeom)
     558             : {
     559           0 :     switch (wkbFlatten(poGeom->getGeometryType()))
     560             :     {
     561           0 :         case wkbPoint:
     562           0 :             if (!poGeom->IsEmpty())
     563             :             {
     564           0 :                 ++nNumFigures;
     565           0 :                 ++nNumPoints;
     566             :             }
     567           0 :             break;
     568             : 
     569           0 :         case wkbLineString:
     570           0 :             if (!poGeom->IsEmpty())
     571             :             {
     572           0 :                 ++nNumFigures;
     573           0 :                 nNumPoints += poGeom->toLineString()->getNumPoints();
     574             :             }
     575           0 :             break;
     576             : 
     577           0 :         case wkbCircularString:
     578           0 :             chVersion = VA_DENALI;
     579           0 :             if (!poGeom->IsEmpty())
     580             :             {
     581           0 :                 ++nNumFigures;
     582           0 :                 nNumPoints += poGeom->toCircularString()->getNumPoints();
     583             :             }
     584           0 :             break;
     585             : 
     586           0 :         case wkbCompoundCurve:
     587             :         {
     588             :             int c;
     589           0 :             chVersion = VA_DENALI;
     590           0 :             if (!poGeom->IsEmpty())
     591             :             {
     592           0 :                 OGRCompoundCurve *g = poGeom->toCompoundCurve();
     593             :                 OGRCurve *poSubGeom;
     594           0 :                 ++nNumFigures;
     595           0 :                 for (int i = 0; i < g->getNumCurves(); i++)
     596             :                 {
     597           0 :                     poSubGeom = g->getCurve(i);
     598           0 :                     switch (wkbFlatten(poSubGeom->getGeometryType()))
     599             :                     {
     600           0 :                         case wkbLineString:
     601           0 :                             c = poSubGeom->toLineString()->getNumPoints();
     602           0 :                             if (c > 1)
     603             :                             {
     604           0 :                                 if (i == 0)
     605           0 :                                     nNumPoints += c;
     606             :                                 else
     607           0 :                                     nNumPoints += c - 1;
     608           0 :                                 nNumSegments += c - 1;
     609             :                             }
     610           0 :                             break;
     611             : 
     612           0 :                         case wkbCircularString:
     613           0 :                             c = poSubGeom->toCircularString()->getNumPoints();
     614           0 :                             if (c > 2)
     615             :                             {
     616           0 :                                 if (i == 0)
     617           0 :                                     nNumPoints += c;
     618             :                                 else
     619           0 :                                     nNumPoints += c - 1;
     620           0 :                                 nNumSegments += (int)((c - 1) / 2);
     621             :                             }
     622           0 :                             break;
     623             : 
     624           0 :                         default:
     625           0 :                             break;
     626             :                     }
     627             :                 }
     628             :             }
     629             :         }
     630           0 :         break;
     631             : 
     632           0 :         case wkbPolygon:
     633             :         {
     634           0 :             OGRPolygon *g = poGeom->toPolygon();
     635           0 :             for (auto &&poIter : *g)
     636           0 :                 TrackGeometry(poIter);
     637             :         }
     638           0 :         break;
     639             : 
     640           0 :         case wkbCurvePolygon:
     641             :         {
     642           0 :             chVersion = VA_DENALI;
     643           0 :             OGRCurvePolygon *g = poGeom->toCurvePolygon();
     644           0 :             for (auto &&poIter : *g)
     645           0 :                 TrackGeometry(poIter);
     646             :         }
     647           0 :         break;
     648             : 
     649           0 :         case wkbMultiPoint:
     650             :         case wkbMultiLineString:
     651             :         case wkbMultiPolygon:
     652             :         case wkbGeometryCollection:
     653             :         {
     654           0 :             OGRGeometryCollection *g = poGeom->toGeometryCollection();
     655           0 :             for (auto &&poMember : *g)
     656             :             {
     657           0 :                 TrackGeometry(poMember);
     658           0 :                 ++nNumShapes;
     659             :             }
     660             :         }
     661           0 :         break;
     662             : 
     663           0 :         default:
     664           0 :             break;
     665             :     }
     666           0 : }
     667             : 
     668             : /************************************************************************/
     669             : /*                         WriteSqlGeometry()                           */
     670             : /************************************************************************/
     671             : 
     672           0 : OGRErr OGRMSSQLGeometryWriter::WriteSqlGeometry(unsigned char *pszBuffer,
     673             :                                                 int nBufLen)
     674             : {
     675           0 :     pszData = pszBuffer;
     676             : 
     677           0 :     if (nBufLen < nLen)
     678           0 :         return OGRERR_FAILURE;
     679             : 
     680           0 :     OGRwkbGeometryType geomType = wkbFlatten(poGeom2->getGeometryType());
     681             : 
     682           0 :     if (nNumPoints == 1 && geomType == wkbPoint)
     683             :     {
     684             :         /* writing a single point */
     685           0 :         OGRPoint *g = poGeom2->toPoint();
     686           0 :         WriteInt32(0, nSRSId);
     687           0 :         WriteByte(4, VA_KATMAI);
     688           0 :         WriteByte(5, chProps);
     689           0 :         WritePoint(g);
     690             :     }
     691           0 :     else if (nNumPoints == 2 && geomType == wkbLineString)
     692             :     {
     693             :         /* writing a single line */
     694           0 :         OGRLineString *g = poGeom2->toLineString();
     695           0 :         WriteInt32(0, nSRSId);
     696           0 :         WriteByte(4, VA_KATMAI);
     697           0 :         WriteByte(5, chProps);
     698             : 
     699           0 :         if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     700             :         {
     701           0 :             WritePoint(g->getX(0), g->getY(0), g->getZ(0), g->getM(0));
     702           0 :             WritePoint(g->getX(1), g->getY(1), g->getZ(1), g->getM(1));
     703             :         }
     704           0 :         else if (chProps & SP_HASZVALUES)
     705             :         {
     706           0 :             WritePoint(g->getX(0), g->getY(0), g->getZ(0));
     707           0 :             WritePoint(g->getX(1), g->getY(1), g->getZ(1));
     708             :         }
     709           0 :         else if (chProps & SP_HASMVALUES)
     710             :         {
     711           0 :             WritePoint(g->getX(0), g->getY(0), g->getM(0));
     712           0 :             WritePoint(g->getX(1), g->getY(1), g->getM(1));
     713             :         }
     714             :         else
     715             :         {
     716           0 :             WritePoint(g->getX(0), g->getY(0));
     717           0 :             WritePoint(g->getX(1), g->getY(1));
     718           0 :         }
     719             :     }
     720             :     else
     721             :     {
     722             :         /* complex geometry */
     723           0 :         if (poGeom2->IsValid())
     724           0 :             chProps |= SP_ISVALID;
     725             : 
     726           0 :         WriteInt32(0, nSRSId);
     727           0 :         WriteByte(4, chVersion);
     728           0 :         WriteByte(5, chProps);
     729           0 :         WriteInt32(nPointPos - 4, nNumPoints);
     730           0 :         WriteInt32(nFigurePos - 4, nNumFigures);
     731           0 :         WriteInt32(nShapePos - 4, nNumShapes);
     732           0 :         if (nNumSegments > 0)
     733           0 :             WriteInt32(nSegmentPos - 4, nNumSegments);
     734             : 
     735           0 :         WriteGeometry(poGeom2, 0xFFFFFFFF);
     736             :     }
     737           0 :     return OGRERR_NONE;
     738             : }
     739             : 
     740             : #undef ParentOffset
     741             : #undef FigureOffset
     742             : #undef ShapeType
     743             : #undef SegmentType
     744             : 
     745             : #undef FigureAttribute
     746             : #undef PointOffset
     747             : #undef NextPointOffset

Generated by: LCOV version 1.14