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

Generated by: LCOV version 1.14