Example #1
0
OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
                              OGRGeometry **ppoGeom,
                              int nBytes )

{
    *ppoGeom = NULL;

    if( nBytes < 16 )
        return OGRERR_FAILURE;

    if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
        return OGRERR_FAILURE;

    int nGeomType = pabyGeom[0];
    pabyGeom += 16;
    nBytes -= 16;

    if( nGeomType == GEOMEDIA_POINT ||
        nGeomType == GEOMEDIA_ORIENTED_POINT )
    {
        if (nBytes < 3 * 8)
            return OGRERR_FAILURE;

        double dfX, dfY, dfZ;
        memcpy(&dfX, pabyGeom, 8);
        CPL_LSBPTR64(&dfX);
        memcpy(&dfY, pabyGeom + 8, 8);
        CPL_LSBPTR64(&dfY);
        memcpy(&dfZ, pabyGeom + 16, 8);
        CPL_LSBPTR64(&dfZ);

        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );

         return OGRERR_NONE;
    }
    else if ( nGeomType == GEOMEDIA_POLYLINE )
    {
        if (nBytes < 4)
            return OGRERR_FAILURE;

        int nPoints;
        memcpy(&nPoints, pabyGeom, 4);
        CPL_LSBPTR32(&nPoints);

        pabyGeom += 4;
        nBytes -= 4;

        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
            return OGRERR_FAILURE;

        OGRLineString* poLS = new OGRLineString();
        poLS->setNumPoints(nPoints);
        int i;
        for(i=0;i<nPoints;i++)
        {
            double dfX, dfY, dfZ;
            memcpy(&dfX, pabyGeom, 8);
            CPL_LSBPTR64(&dfX);
            memcpy(&dfY, pabyGeom + 8, 8);
            CPL_LSBPTR64(&dfY);
            memcpy(&dfZ, pabyGeom + 16, 8);
            CPL_LSBPTR64(&dfZ);

            poLS->setPoint(i, dfX, dfY, dfZ);

            pabyGeom += 24;
        }

        *ppoGeom = poLS;

        return OGRERR_NONE;
    }
    else if ( nGeomType == GEOMEDIA_POLYGON )
    {
        if (nBytes < 4)
            return OGRERR_FAILURE;

        int nPoints;
        memcpy(&nPoints, pabyGeom, 4);
        CPL_LSBPTR32(&nPoints);

        pabyGeom += 4;
        nBytes -= 4;

        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
            return OGRERR_FAILURE;

        OGRLinearRing* poRing = new OGRLinearRing();
        poRing->setNumPoints(nPoints);
        int i;
        for(i=0;i<nPoints;i++)
        {
            double dfX, dfY, dfZ;
            memcpy(&dfX, pabyGeom, 8);
            CPL_LSBPTR64(&dfX);
            memcpy(&dfY, pabyGeom + 8, 8);
            CPL_LSBPTR64(&dfY);
            memcpy(&dfZ, pabyGeom + 16, 8);
            CPL_LSBPTR64(&dfZ);

            poRing->setPoint(i, dfX, dfY, dfZ);

            pabyGeom += 24;
        }

        OGRPolygon* poPoly = new OGRPolygon();
        poPoly->addRingDirectly(poRing);
        *ppoGeom = poPoly;

        return OGRERR_NONE;
    }
    else if ( nGeomType == GEOMEDIA_BOUNDARY )
    {
        if (nBytes < 4)
            return OGRERR_FAILURE;

        int nExteriorSize;
        memcpy(&nExteriorSize, pabyGeom, 4);
        CPL_LSBPTR32(&nExteriorSize);

        pabyGeom += 4;
        nBytes -= 4;

        if (nBytes < nExteriorSize)
            return OGRERR_FAILURE;

        OGRGeometry* poExteriorGeom = NULL;
        if (OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom, nExteriorSize ) != OGRERR_NONE)
            return OGRERR_FAILURE;

        if ( wkbFlatten( poExteriorGeom->getGeometryType() ) != wkbPolygon )
        {
            delete poExteriorGeom;
            return OGRERR_FAILURE;
        }

        pabyGeom += nExteriorSize;
        nBytes -= nExteriorSize;

        if (nBytes < 4)
        {
            delete poExteriorGeom;
            return OGRERR_FAILURE;
        }

        int nInteriorSize;
        memcpy(&nInteriorSize, pabyGeom, 4);
        CPL_LSBPTR32(&nInteriorSize);

        pabyGeom += 4;
        nBytes -= 4;

        if (nBytes < nInteriorSize)
        {
            delete poExteriorGeom;
            return OGRERR_FAILURE;
        }

        OGRGeometry* poInteriorGeom = NULL;
        if (OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom, nInteriorSize ) != OGRERR_NONE)
        {
            delete poExteriorGeom;
            return OGRERR_FAILURE;
        }

        OGRwkbGeometryType interiorGeomType = wkbFlatten( poInteriorGeom->getGeometryType() );
        if ( interiorGeomType == wkbPolygon )
        {
            ((OGRPolygon*)poExteriorGeom)->addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing());
        }
        else if ( interiorGeomType == wkbMultiPolygon )
        {
            int numGeom = ((OGRMultiPolygon*)poInteriorGeom)->getNumGeometries();
            for ( int i = 0; i < numGeom; ++i )
            {
                OGRPolygon* poInteriorPolygon = 
                    (OGRPolygon*)((OGRMultiPolygon*)poInteriorGeom)->getGeometryRef(i);
                ((OGRPolygon*)poExteriorGeom)->addRing( poInteriorPolygon->getExteriorRing() );
            }
        }
        else
        {
            delete poExteriorGeom;
            delete poInteriorGeom;
            return OGRERR_FAILURE;
        }

        delete poInteriorGeom;
        *ppoGeom = poExteriorGeom;

        return OGRERR_NONE;
    }
    else if ( nGeomType == GEOMEDIA_COLLECTION ||
              nGeomType == GEOMEDIA_MULTILINE ||
              nGeomType == GEOMEDIA_MULTIPOLYGON )
    {
        if (nBytes < 4)
            return OGRERR_FAILURE;

        int i;
        int nParts;
        memcpy(&nParts, pabyGeom, 4);
        CPL_LSBPTR32(&nParts);

        pabyGeom += 4;
        nBytes -= 4;

        if (nParts < 0 || nParts > INT_MAX / (4 + 16) || nBytes < nParts * (4 + 16))
            return OGRERR_FAILURE;

        /* Can this collection be considered as a multipolyline or multipolygon ? */
        if ( nGeomType == GEOMEDIA_COLLECTION )
        {
            GByte* pabyGeomBackup = pabyGeom;
            int nBytesBackup = nBytes;

            int bAllPolyline = TRUE;
            int bAllPolygon = TRUE;

            for(i=0;i<nParts;i++)
            {
                if (nBytes < 4)
                    return OGRERR_FAILURE;
                int nSubBytes;
                memcpy(&nSubBytes, pabyGeom, 4);
                CPL_LSBPTR32(&nSubBytes);

                if (nSubBytes < 0)
                {
                    return OGRERR_FAILURE;
                }

                pabyGeom += 4;
                nBytes -= 4;

                if (nBytes < nSubBytes)
                {
                    return OGRERR_FAILURE;
                }

                if( nSubBytes < 16 )
                    return OGRERR_FAILURE;

                if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
                    return OGRERR_FAILURE;

                int nSubGeomType = pabyGeom[0];
                if ( nSubGeomType != GEOMEDIA_POLYLINE )
                    bAllPolyline = FALSE;
                if ( nSubGeomType != GEOMEDIA_POLYGON )
                    bAllPolygon = FALSE;

                pabyGeom += nSubBytes;
                nBytes -= nSubBytes;
            }

            pabyGeom = pabyGeomBackup;
            nBytes = nBytesBackup;

            if (bAllPolyline)
                nGeomType = GEOMEDIA_MULTILINE;
            else if (bAllPolygon)
                nGeomType = GEOMEDIA_MULTIPOLYGON;
        }

        OGRGeometryCollection* poColl = (nGeomType == GEOMEDIA_MULTILINE) ? new OGRMultiLineString() :
                                        (nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() :
                                                              new OGRGeometryCollection();

        for(i=0;i<nParts;i++)
        {
            if (nBytes < 4)
                return OGRERR_FAILURE;
            int nSubBytes;
            memcpy(&nSubBytes, pabyGeom, 4);
            CPL_LSBPTR32(&nSubBytes);

            if (nSubBytes < 0)
            {
                delete poColl;
                return OGRERR_FAILURE;
            }

            pabyGeom += 4;
            nBytes -= 4;

            if (nBytes < nSubBytes)
            {
                delete poColl;
                return OGRERR_FAILURE;
            }

            OGRGeometry* poSubGeom = NULL;
            if (OGRCreateFromGeomedia( pabyGeom, &poSubGeom, nSubBytes ) == OGRERR_NONE)
            {
                if (wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon &&
                    wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString)
                {
                    OGRPolygon* poPoly = new OGRPolygon();
                    OGRLinearRing* poRing = new OGRLinearRing();
                    poRing->addSubLineString((OGRLineString*)poSubGeom);
                    poPoly->addRingDirectly(poRing);
                    delete poSubGeom;
                    poSubGeom = poPoly;
                }

                if (poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE)
                {
                    //printf("%d %d\n", poColl->getGeometryType() & ~wkb25DBit, poSubGeom->getGeometryType() & ~wkb25DBit);
                    delete poSubGeom;
                }
            }

            pabyGeom += nSubBytes;
            nBytes -= nSubBytes;
        }

        *ppoGeom = poColl;

        return OGRERR_NONE;
    }
    else
    {
        CPLDebug("GEOMEDIA", "Unhandled type %d", nGeomType);
    }

    return OGRERR_FAILURE;
}
Example #2
0
OGRFeature *OGRSOSILayer::GetNextFeature() {
    short nName, nNumLines;
    long  nNumCoo;
    unsigned short nInfo;

    /* iterate through the SOSI groups*/
    while (LC_NextBgr(poNextSerial,LC_FRAMGR)) {
        nName = LC_RxGr(&oNextSerial, LES_OPTIMALT, &nNumLines, &nNumCoo, &nInfo);

        S2S oHeaders;
        S2S::iterator iHeaders;
        /* extract reference strings from group header */
        CPLString osKey, osValue;
        for (short i=1; i<=nNumLines; i++) {
            char *pszLine = LC_GetGi(i);
            if (pszLine[0] == '!') continue;                 /* If we have a comment line, skip it. */
            if ((pszLine[0] == ':')||(pszLine[0] == '(')) {  /* if we have a continued REF line... */
                osValue.append(CPLString(pszLine));            /* append to previous line.           */
                oHeaders.insert(std::pair<CPLString,CPLString>(osKey,osValue));
                continue;
            }
            while (pszLine[0] == '.') pszLine++; /* skipping the dots at the beginning of a SOSI line */
            char *pszUTFLine = CPLRecode(pszLine, poParent->pszEncoding, CPL_ENC_UTF8); /* switch to UTF encoding here */
            char *pszPos = strstr(pszUTFLine, " ");
            if (pszPos != NULL) {
                osKey = CPLString(std::string(pszUTFLine,pszPos));
                osValue = CPLString(pszPos+1);
                oHeaders.insert(std::pair<CPLString,CPLString>(osKey,osValue));
            }
            CPLFree(pszUTFLine);
        }

        /* get Feature from fyba, according to feature definition */
        OGRGeometry *poGeom = NULL;
        OGRwkbGeometryType oGType = wkbUnknown;

        switch (nName) {
        case INGEN_GRUPPE: {  /* No group */
            CPLDebug( "[GetNextFeature]", "Could not load further groups - FYBA reported INGEN_GRUPPE.");
            break;
        }
        case L_FLATE: {  /* Area */
            oGType = wkbPolygon;
            OGRLinearRing *poOuter = new OGRLinearRing();  /* Initialize a new closed polygon */
            long nRefNr;
            unsigned char nRefStatus;
            long nRefCount;
            bool correct = true;
            LC_GRF_STATUS oGrfStat;

            // Iterate through all objects that constitute this area.
            LC_InitGetRefFlate(&oGrfStat);
            nRefCount = LC_GetRefFlate(&oGrfStat, GRF_YTRE, &nRefNr, &nRefStatus, 1);
            while (nRefCount > 0) {
                if (poParent->papoBuiltGeometries[nRefNr] == NULL) {
                    // This should not happen under normal operation.
                    CPLError( CE_Warning, CPLE_AppDefined, "Feature %li referenced by %li, but it was not initialized. Geometry may be broken.", nRefNr, oNextSerial.lNr);
                    correct = false;
                    //return NULL;
                    break;
                }
                OGRGeometry *geom = poParent->papoBuiltGeometries[nRefNr];
                if (geom->getGeometryType() == wkbLineString) {
                  OGRLineString *poCurve = (OGRLineString*)geom;
                  if (nRefStatus == LC_MED_DIG) {         /* clockwise */
                    poOuter->addSubLineString(poCurve);
                  } else if (nRefStatus == LC_MOT_DIG) {  /* counter-clockwise */
                      poOuter->addSubLineString(poCurve,poCurve->getNumPoints()-1,0);
                  } else {
                      CPLError( CE_Failure, CPLE_OpenFailed, "Internal error: GRF_*_OY encountered.");
                      return NULL;
                  }
                } else {
                    CPLError( CE_Warning, CPLE_AppDefined, "Element %li composed of non-linestrings (REF %li of type %i). Ignored.", oNextSerial.lNr, nRefNr, geom->getGeometryType());
                }
                nRefCount = LC_GetRefFlate(&oGrfStat, GRF_YTRE, &nRefNr, &nRefStatus, 1);
            }

            if (correct) {
              OGRPolygon *poLy = new OGRPolygon();
              poOuter->closeRings();
              poLy->addRingDirectly(poOuter);

              OGRLinearRing *poInner = 0;
              nRefCount = LC_GetRefFlate(&oGrfStat, GRF_INDRE, &nRefNr, &nRefStatus, 1);
              while (nRefCount > 0) {
                  if (nRefNr == -1) {
                    if (poInner && (poInner->getNumPoints()>2)) {   /* If this is not the first polygon, terminate and add the last */
                          poInner->closeRings();
                          poLy->addRingDirectly(poInner);
                    }
                    poInner = new OGRLinearRing();  /* Initialize a new closed polygon */
                  } else {
                    if (poParent->papoBuiltGeometries[nRefNr] == NULL) { /* this shouldn't happen under normal operation */
                        CPLError( CE_Fatal, CPLE_AppDefined, "Feature %li referenced by %li, but it was not initialized.", nRefNr, oNextSerial.lNr);
                        return NULL;
                    }
                    OGRGeometry *geom = poParent->papoBuiltGeometries[nRefNr];
                    if (geom->getGeometryType() == wkbLineString) {
                      OGRLineString *poCurve = (OGRLineString*)geom;
                      if (nRefStatus == LC_MED_DIG) {         /* clockwise */
                        poInner->addSubLineString(poCurve);
                      } else if (nRefStatus == LC_MOT_DIG) {  /* counter-clockwise */
                          poInner->addSubLineString(poCurve,poCurve->getNumPoints()-1,0);
                      } else {
                          CPLError( CE_Failure, CPLE_OpenFailed, "Internal error: GRF_*_OY encountered.");
                          return NULL;
                      }
                    } else {
                        CPLError( CE_Warning, CPLE_AppDefined, "Element %li composed of non-linestrings (REF %li of type %i). Ignored.", oNextSerial.lNr, nRefNr, geom->getGeometryType());
                    }
                  }
                  nRefCount = LC_GetRefFlate(&oGrfStat, GRF_INDRE, &nRefNr, &nRefStatus, 1);
              }
              poGeom = poLy;
            }
            break;
        }
        case L_KURVE:    /* curve */
        case L_LINJE:    /* curve, not simplifyable */
        case L_BUEP:  {  /* curve, interpolated from circular arc */
            oGType = wkbLineString;

            OGRLineString *poCurve = (OGRLineString*)(poParent->papoBuiltGeometries[oNextSerial.lNr]);
            if (poCurve == NULL) {
                CPLError( CE_Fatal, CPLE_AppDefined, "Curve %li was not initialized.", oNextSerial.lNr);
                return NULL;
            }
            poGeom = poCurve->clone();
            break;
        }
        case L_TEKST: {  /* text */
            oGType = wkbMultiPoint;

            OGRMultiPoint *poMP = (OGRMultiPoint*)(poParent->papoBuiltGeometries[oNextSerial.lNr]);
            if (poMP == NULL) {
                CPLError( CE_Fatal, CPLE_AppDefined, "Tekst %li was not initialized.", oNextSerial.lNr);
                return NULL;
            }
            poGeom = poMP->clone();
            break;
        }
        case L_SYMBOL: {
            //CPLError( CE_Warning, CPLE_OpenFailed, "Geometry of type SYMBOL treated as point (PUNKT).");
        }
        case L_PUNKT: {  /* point */
            oGType = wkbPoint;
            OGRPoint *poPoint = (OGRPoint*)(poParent->papoBuiltGeometries[oNextSerial.lNr]);
            if (poPoint == NULL) {
                CPLError( CE_Fatal, CPLE_AppDefined, "Point %li was not initialized.", oNextSerial.lNr);
                return NULL;
            }
            poGeom = poPoint->clone();
            break;
        }
        case L_DEF:    /* skip user definitions and headers here */
        case L_HODE: {
            break;
        }
        default: {     /* complain a bit about anything else that is not implemented */
            CPLError( CE_Failure, CPLE_OpenFailed, "Unrecognized geometry of type %i.", nName);
            break;
        }
        }

        if (poGeom == NULL) continue;                         /* skipping L_HODE and unrecognized groups */
        if (oGType != poFeatureDefn->GetGeomType()) {
            if (poGeom != NULL) delete poGeom;
            continue; /* skipping features that are not the correct geometry */
        }

        OGRFeature *poFeature = new OGRFeature( poFeatureDefn );

        /* set all headers found in this group - we export everything, just in case */
        for (iHeaders = oHeaders.begin(); iHeaders != oHeaders.end(); iHeaders++) {
            OGRSOSIDataType *poType = SOSIGetType(iHeaders->first);
            OGRSOSISimpleDataType *poElements = poType->getElements();

            const char *pszLine = iHeaders->second.c_str();
            char** tokens = CSLTokenizeString(iHeaders->second.c_str());

            for (int k=0; k<poType->getElementCount(); k++) {
                if (tokens[k] == 0) break;

                if (strcmp(poElements[k].GetName(),"")==0) continue;
                int iHNr = poHeaderDefn->find(poElements[k].GetName())->second;
                if (iHNr == -1) {
                    CPLError( CE_Warning, CPLE_AppDefined, "Could not find field definition for %s.", poElements[k].GetName());
                    continue;
                }
                OGRFieldType nType = poElements[k].GetType();
                switch (nType) {
                  case OFTInteger: {
                    poFeature->SetField( iHNr, SOSITypeToInt(tokens[k]));
                    break;
                  }
                  case OFTDate: {
                    int date[3];
                    SOSITypeToDate(tokens[k], date);
                    poFeature->SetField( iHNr, date[0], date[1], date[2]);
                    break;
                  }
                  case OFTDateTime: {
                    int date[6];
                    SOSITypeToDateTime(tokens[k], date);
                    if (date[0]>0)
                      poFeature->SetField( iHNr, date[0], date[1], date[2], date[3], date[4], static_cast<float>(date[5]), 1);
                    break;
                  }
                  case OFTReal: {
                    poFeature->SetField( iHNr, SOSITypeToReal(tokens[k]));
                    break;
                  }
                  default: {
                    if ((k==0)&&((pszLine[0] == '\'')||(pszLine[0] == '\"'))) { /* If the value is quoted, ignore these */
                        int nLen = static_cast<int>(strlen(pszLine));
                        char *pszNline = (char*)CPLMalloc(nLen-1);
                        strncpy(pszNline, pszLine+1, nLen-2);
                        pszNline[nLen-2] = '\0';
                        poFeature->SetField( iHNr, pszNline);
                        CPLFree(pszNline);
                    } else {
                        poFeature->SetField( iHNr, tokens[k]);
                    }
                    break;
                  }
                }
          }

          CSLDestroy(tokens);
        }

        if( poGeom != NULL )
            poGeom->assignSpatialReference(poParent->poSRS);

        poFeature->SetGeometryDirectly( poGeom );
        poFeature->SetFID( nNextFID++ );

        /* Loop until we have a feature that matches the definition */
        if ( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) )
                && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) )
            return poFeature;
        delete poFeature;
    }
    return NULL;
}