示例#1
0
void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
                           OGRFeature *feature ) {
#ifdef DEBUG_VERBOSE
    CPLDebug( "OGR_ILI",
              "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s",
              geomIdx, OGRGeometryTypeToName(eType) );
#endif
    if (eType == wkbNone)
    {
      CPLError( CE_Warning, CPLE_AppDefined,
                "Calling ILI1Reader::ReadGeom with wkbNone" );
    }

    // Initialize geometry.

    OGRCompoundCurve *ogrCurve = new OGRCompoundCurve();
    OGRCurvePolygon *ogrPoly = NULL; //current polygon
    OGRMultiCurve *ogrMultiLine = NULL; //current multi line

    if (eType == wkbMultiCurve || eType == wkbMultiLineString)
    {
      ogrMultiLine = new OGRMultiCurve();
    }
    else if (eType == wkbPolygon || eType == wkbCurvePolygon)
    {
      ogrPoly = new OGRCurvePolygon();
    }

    OGRPoint ogrPoint; // Current point.
    ogrPoint.setX(CPLAtof(stgeom[1])); ogrPoint.setY(CPLAtof(stgeom[2]));

    OGRLineString *ogrLine = new OGRLineString();
    ogrLine->addPoint(&ogrPoint);

    // Parse geometry.

    char **tokens = NULL;
    bool end = false;
    OGRCircularString *arc = NULL; //current arc

    while (!end && (tokens = ReadParseLine()) != NULL)
    {
      const char *firsttok = CSLGetField(tokens, 0);
      if( firsttok == NULL )
      {
          // do nothing
      }
      else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3)
      {
        ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2]));
        if (arc) {
          arc->addPoint(&ogrPoint);
          OGRErr error =  ogrCurve->addCurveDirectly(arc);
          if (error != OGRERR_NONE) {
            char* pszJSon = arc->exportToJson();
            CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
                     pszJSon ? pszJSon : "(null)" );
            CPLFree(pszJSon);
            delete arc;
          }
          arc = NULL;
        }
        ogrLine->addPoint(&ogrPoint);
      }
      else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3)
      {
        //Finish line and start arc
        if (ogrLine->getNumPoints() > 1) {
          OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
          if (error != OGRERR_NONE) {
            char* pszJSon = ogrLine->exportToJson();
            CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
                     pszJSon ? pszJSon : "(null)" );
            CPLFree(pszJSon);
            delete ogrLine;
          }
          ogrLine = new OGRLineString();
        } else {
          ogrLine->empty();
        }
        delete arc;
        arc = new OGRCircularString();
        arc->addPoint(&ogrPoint);
        ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2]));
        arc->addPoint(&ogrPoint);
      }
      else if (EQUAL(firsttok, "ELIN"))
      {
        if (ogrLine->getNumPoints() > 1) { // Ignore single LIPT after ARCP
          OGRErr error = ogrCurve->addCurveDirectly(ogrLine);
          if (error != OGRERR_NONE) {
            char* pszJSon = ogrLine->exportToJson();
            CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
                     pszJSon ? pszJSon : "(null)" );
            CPLFree(pszJSon);
            delete ogrLine;
          }
          ogrLine = NULL;
        }
        if (!ogrCurve->IsEmpty()) {
          if (ogrMultiLine)
          {
            OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve);
            if (error != OGRERR_NONE) {
              char* pszJSon = ogrCurve->exportToJson();
              CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
                       pszJSon ? pszJSon : "(null)" );
              CPLFree(pszJSon);
              delete ogrCurve;
            }
            ogrCurve = NULL;
          }
          if (ogrPoly)
          {
            OGRErr error = ogrPoly->addRingDirectly(ogrCurve);
            if (error != OGRERR_NONE) {
              char* pszJSon = ogrCurve->exportToJson();
              CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s",
                       pszJSon ? pszJSon : "(null)" );
              CPLFree(pszJSon);
              delete ogrCurve;
            }
            ogrCurve = NULL;
          }
        }
        end = true;
      }
      else if (EQUAL(firsttok, "EEDG"))
      {
        end = true;
      }
      else if (EQUAL(firsttok, "LATT"))
      {
        //Line Attributes (ignored)
      }
      else if (EQUAL(firsttok, "EFLA"))
      {
        end = true;
      }
      else if (EQUAL(firsttok, "ETAB"))
      {
        end = true;
      }
      else
      {
        CPLError( CE_Warning, CPLE_AppDefined,
                  "Unexpected token: %s", firsttok );
      }

      CSLDestroy(tokens);
    }
    delete arc;

    delete ogrLine;

    //Set feature geometry
    if (eType == wkbMultiCurve)
    {
      feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine);
      delete ogrCurve;
    }
    else if (eType == wkbMultiLineString)
    {
      feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine->getLinearGeometry());
      delete ogrMultiLine;
      delete ogrCurve;
    }
    else if (eType == wkbCurvePolygon)
    {
      feature->SetGeomFieldDirectly(geomIdx, ogrPoly);
      delete ogrCurve;
    }
    else if (eType == wkbPolygon)
    {
      feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry());
      delete ogrPoly;
      delete ogrCurve;
    }
    else
    {
      feature->SetGeomFieldDirectly(geomIdx, ogrCurve);
    }
}
示例#2
0
void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
                                     int nSurfaceFieldIndex )
{
    CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries",
              GetLayerDefn()->GetName());
    OGRwkbGeometryType geomType
        = GetLayerDefn()->GetGeomFieldDefn(nSurfaceFieldIndex)->GetType();

    std::map<OGRFeature*, std::vector<OGRCurve*> > oMapFeatureToGeomSet;

    poSurfaceLineLayer->ResetReading();

    // First map: for each target curvepolygon, find all belonging curves
    while (OGRFeature *linefeature = poSurfaceLineLayer->GetNextFeatureRef()) {
        //OBJE entries with same _RefTID are polygon rings of same feature
        OGRFeature *feature = nullptr;
        if (poFeatureDefn->GetFieldDefn(0)->GetType() == OFTString)
        {
          feature = GetFeatureRef(linefeature->GetFieldAsString(1));
        }
        else
        {
          GIntBig reftid = linefeature->GetFieldAsInteger64(1);
          feature = GetFeatureRef(reftid);
        }
        if (feature)
        {
            OGRGeometry* poGeom = linefeature->GetGeomFieldRef(0);
            OGRMultiCurve *curves = dynamic_cast<OGRMultiCurve *>(poGeom);
            if( curves )
            {
                for (auto&& curve: curves )
                {
                    if( !curve->IsEmpty() )
                        oMapFeatureToGeomSet[feature].push_back(curve);
                }
            }
        }
        else
        {
            CPLError( CE_Warning, CPLE_AppDefined,
                      "Couldn't join feature FID " CPL_FRMT_GIB,
                      linefeature->GetFieldAsInteger64(1) );
        }
    }

    // Now for each target polygon, assemble the curves together.
    std::map<OGRFeature*, std::vector<OGRCurve*> >::const_iterator oIter =
                                                oMapFeatureToGeomSet.begin();
    for( ; oIter != oMapFeatureToGeomSet.end(); ++oIter )
    {
        OGRFeature* feature = oIter->first;
        std::vector<OGRCurve*> oCurves = oIter->second;

        std::vector<OGRCurve*> oSetDestCurves;
        double dfLargestArea = 0.0;
        OGRCurve* poLargestCurve = nullptr;
        while( true )
        {
            std::vector<OGRCurve*>::iterator oIterCurves = oCurves.begin();
            if( oIterCurves == oCurves.end() )
                break;

            OGRPoint endPointCC;
            OGRCompoundCurve* poCC = new OGRCompoundCurve();

            bool bFirst = true;
            while( true )
            {
                bool bNewCurveAdded = false;
                const double dfEps = 1e-14;
                for(oIterCurves = oCurves.begin();
                                oIterCurves != oCurves.end(); ++oIterCurves )
                {
                    OGRCurve* curve = *oIterCurves;
                    OGRPoint startPoint;
                    OGRPoint endPoint;
                    curve->StartPoint(&startPoint);
                    curve->EndPoint(&endPoint);
                    if( bFirst ||
                        (fabs(startPoint.getX() - endPointCC.getX()) < dfEps &&
                         fabs(startPoint.getY() - endPointCC.getY()) < dfEps) )
                    {
                        bFirst = false;

                        curve->EndPoint(&endPointCC);

                        const OGRwkbGeometryType eCurveType =
                                        wkbFlatten(curve->getGeometryType());
                        if( eCurveType == wkbCompoundCurve )
                        {
                            OGRCompoundCurve* poCCSub = curve->toCompoundCurve();
                            for( auto&& subCurve: poCCSub )
                            {
                                poCC->addCurve(subCurve);
                            }
                        }
                        else
                        {
                            poCC->addCurve( curve );
                        }
                        oCurves.erase( oIterCurves );
                        bNewCurveAdded = true;
                        break;
                    }
                    else
                    if( fabs(endPoint.getX() - endPointCC.getX()) < dfEps &&
                        fabs(endPoint.getY() - endPointCC.getY()) < dfEps )
                    {
                        curve->StartPoint(&endPointCC);

                        const OGRwkbGeometryType eCurveType =
                                        wkbFlatten(curve->getGeometryType());
                        if( eCurveType == wkbLineString ||
                            eCurveType == wkbCircularString )
                        {
                            OGRSimpleCurve* poSC = curve->clone()->toSimpleCurve();
                            poSC->reversePoints();
                            poCC->addCurveDirectly( poSC );
                        }
                        else if( eCurveType == wkbCompoundCurve )
                        {
                            // Reverse the order of the elements of the
                            // compound curve
                            OGRCompoundCurve* poCCSub = curve->toCompoundCurve();
                            for( int i=poCCSub->getNumCurves()-1; i >= 0; --i )
                            {
                                OGRSimpleCurve* poSC = poCCSub->getCurve(i)->
                                    clone()->toSimpleCurve();
                                poSC->reversePoints();
                                poCC->addCurveDirectly(poSC);
                            }
                        }

                        oCurves.erase( oIterCurves );
                        bNewCurveAdded = true;
                        break;
                    }
                }
                if( !bNewCurveAdded || oCurves.empty() || poCC->get_IsClosed() )
                    break;
            }

            if( !poCC->get_IsClosed() )
            {
                char* pszJSon = poCC->exportToJson();
                CPLError(CE_Warning, CPLE_AppDefined,
                         "A ring %s for feature " CPL_FRMT_GIB " in layer %s "
                         "was not closed. Dropping it",
                         pszJSon, feature->GetFID(), GetName());
                delete poCC;
                CPLFree(pszJSon);
            }
            else
            {
                double dfArea = poCC->get_Area();
                if( dfArea >= dfLargestArea )
                {
                    dfLargestArea = dfArea;
                    poLargestCurve = poCC;
                }
                oSetDestCurves.push_back(poCC);
            }
        }

        // Now build the final polygon by first inserting the largest ring.
        OGRCurvePolygon *poPoly = (geomType == wkbPolygon) ?
                                new OGRPolygon() : new OGRCurvePolygon();
        if( poLargestCurve )
        {
            std::vector<OGRCurve*>::iterator oIterCurves =
                                                    oSetDestCurves.begin();
            for( ; oIterCurves != oSetDestCurves.end(); ++oIterCurves )
            {
                OGRCurve* poCurve = *oIterCurves;
                if( poCurve == poLargestCurve )
                {
                    oSetDestCurves.erase( oIterCurves );
                    break;
                }
            }

            if (geomType == wkbPolygon)
            {
                poLargestCurve = OGRCurve::CastToLinearRing(poLargestCurve);
            }
            OGRErr error = poPoly->addRingDirectly(poLargestCurve);
            if (error != OGRERR_NONE)
            {
                char* pszJSon = poLargestCurve->exportToJson();
                CPLError(CE_Warning, CPLE_AppDefined,
                         "Cannot add ring %s to feature " CPL_FRMT_GIB
                         " in layer %s",
                         pszJSon, feature->GetFID(), GetName() );
                CPLFree(pszJSon);
            }

            oIterCurves = oSetDestCurves.begin();
            for( ; oIterCurves != oSetDestCurves.end(); ++oIterCurves )
            {
                OGRCurve* poCurve = *oIterCurves;
                if (geomType == wkbPolygon)
                {
                    poCurve = OGRCurve::CastToLinearRing(poCurve);
                }
                error = poPoly->addRingDirectly(poCurve);
                if (error != OGRERR_NONE)
                {
                    char* pszJSon = poCurve->exportToJson();
                    CPLError(CE_Warning, CPLE_AppDefined,
                            "Cannot add ring %s to feature " CPL_FRMT_GIB
                            " in layer %s",
                            pszJSon, feature->GetFID(), GetName() );
                    CPLFree(pszJSon);
                }
            }
        }

        feature->SetGeomFieldDirectly(nSurfaceFieldIndex, poPoly);
    }

    ResetReading();
}