예제 #1
0
/*!
  \brief Recursively read feature and add all elements to points_cache and types_cache.
  
  ftype: if > 0 use this type (because parts of Polygon are read as wkbLineString)
  
  \param Map pointer to Map_info structure
  \param[out] hGeom OGR geometry
  \param ftype feature type
  
  \return 0 on success
  \return 1 on error
*/
static int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
{
    int line, i, np, ng, tp;
    OGRwkbGeometryType type;
    OGRGeometryH hGeom2;

    G_debug(4, "cache_feature() ftype = %d", ftype);

    /* Alloc space */
    line = Map->fInfo.ogr.lines_num;
    if (line == Map->fInfo.ogr.lines_alloc) {
	Map->fInfo.ogr.lines_alloc += 20;
	Map->fInfo.ogr.lines =
	    (struct line_pnts **)G_realloc((void *)Map->fInfo.ogr.lines,
					   Map->fInfo.ogr.lines_alloc *
					   sizeof(struct line_pnts *));

	Map->fInfo.ogr.lines_types =
	    (int *)G_realloc(Map->fInfo.ogr.lines_types,
			     Map->fInfo.ogr.lines_alloc * sizeof(int));

	for (i = Map->fInfo.ogr.lines_num; i < Map->fInfo.ogr.lines_alloc; i++)
	    Map->fInfo.ogr.lines[i] = Vect_new_line_struct();

    }
    Vect_reset_line(Map->fInfo.ogr.lines[line]);

    type = wkbFlatten(OGR_G_GetGeometryType(hGeom));

    switch (type) {
    case wkbPoint:
	G_debug(4, "Point");
	Vect_append_point(Map->fInfo.ogr.lines[line],
			  OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
			  OGR_G_GetZ(hGeom, 0));
	Map->fInfo.ogr.lines_types[line] = GV_POINT;
	Map->fInfo.ogr.lines_num++;
	return 0;
	break;

    case wkbLineString:
	G_debug(4, "LineString");
	np = OGR_G_GetPointCount(hGeom);
	for (i = 0; i < np; i++) {
	    Vect_append_point(Map->fInfo.ogr.lines[line],
			      OGR_G_GetX(hGeom, i), OGR_G_GetY(hGeom, i),
			      OGR_G_GetZ(hGeom, i));
	}

	if (ftype > 0) {	/* Polygon rings */
	    Map->fInfo.ogr.lines_types[line] = ftype;
	}
	else {
	    Map->fInfo.ogr.lines_types[line] = GV_LINE;
	}
	Map->fInfo.ogr.lines_num++;
	return 0;
	break;

    case wkbMultiPoint:
    case wkbMultiLineString:
    case wkbPolygon:
    case wkbMultiPolygon:
    case wkbGeometryCollection:
	ng = OGR_G_GetGeometryCount(hGeom);
	G_debug(4, "%d geoms -> next level", ng);
	if (type == wkbPolygon) {
	    tp = GV_BOUNDARY;
	}
	else {
	    tp = -1;
	}
	for (i = 0; i < ng; i++) {
	    hGeom2 = OGR_G_GetGeometryRef(hGeom, i);
	    cache_feature(Map, hGeom2, tp);
	}
	return 0;
	break;

    default:
	G_warning(_("OGR feature type %d not supported"), type);
	return 1;
	break;
    }
}
예제 #2
0
static S57_geo   *_ogrLoadObject(const char *objname, void *feature, OGRGeometryH hGeomNext)
{
    S57_geo           *geoData = NULL;
    OGRGeometryH       hGeom   = NULL;
    OGRwkbGeometryType eType   = wkbNone;

    if (NULL != feature)
        hGeom = OGR_F_GetGeometryRef((OGRFeatureH)feature);
    else
        hGeom = hGeomNext;

    if (NULL != hGeom)
        eType = OGR_G_GetGeometryType(hGeom);
    else
        eType = wkbNone; // DSIS

    switch (eType) {
        // POINT
        case wkbPoint25D:
        case wkbPoint: {
            geocoord *pointxyz = g_new(geocoord, 3);

            pointxyz[0] = OGR_G_GetX(hGeom, 0);
            pointxyz[1] = OGR_G_GetY(hGeom, 0);
            pointxyz[2] = OGR_G_GetZ(hGeom, 0);

            geoData = S57_setPOINT(pointxyz);
            _setExtent(geoData, hGeom);

            break;
        }

        // LINE
        case wkbLineString25D:
        case wkbLineString: {
            int count = OGR_G_GetPointCount(hGeom);

            // NOTE: when S52_USE_SUPP_LINE_OVERLAP then Edge might have 0 node
            /* so this code fail
            if (count < 2) {
                PRINTF("WARNING: a line with less than 2 points!?\n");
                g_assert(0);
                return NULL;
            }
            */

            geocoord *linexyz = NULL;
            if (0 != count)
                linexyz = g_new(geocoord, 3*count);

            for (int node=0; node<count; ++node) {
                linexyz[node*3+0] = OGR_G_GetX(hGeom, node);
                linexyz[node*3+1] = OGR_G_GetY(hGeom, node);
                linexyz[node*3+2] = OGR_G_GetZ(hGeom, node);
            }

            geoData = S57_setLINES(count, linexyz);

            _setExtent(geoData, hGeom);

            break;
        }

        // AREA
        case wkbPolygon25D:
        case wkbPolygon: {
            // Note: S57 area have CW outer ring and CCW inner ring
            guint        nRingCount = OGR_G_GetGeometryCount(hGeom);
            guint       *ringxyznbr;
            geocoord   **ringxyz;
            double       area = 0;

            ringxyznbr = g_new(guint,      nRingCount);
            ringxyz    = g_new(geocoord *, nRingCount);

            // NOTE: to check winding on an open area
            //for (i = n-1, j = 0; j < n; i = j, j++) {
            //     ai = x[i] * y[j] - x[j] * y[i];
            //}

            for (guint iRing=0; iRing<nRingCount; ++iRing) {
                OGRGeometryH hRing;
                guint vert_count = _getGeoPtCount(hGeom, iRing, &hRing);

                ringxyznbr[iRing] = vert_count;

                // skip this ring if no vertex
                if (0 == vert_count) {
                    // FIXME: what should be done here,
                    // FIX: S52 - discard this ring or the object or the layer or the whole chart (update)
                    // FIX: GDAL/OGR - is it a bug in the reader or in the chart it self (S57)
                    // FIX: or this is an empty Geo
                    PRINTF("WARNING: wkbPolygon, empty ring  (%s)\n", objname);
                    g_assert(0);
                    continue;
                }

                ringxyz[iRing]    = g_new(geocoord, vert_count*3*sizeof(geocoord));

                // check if last vertex is NOT the first vertex (ie ring not close)
                if ((OGR_G_GetX(hRing, 0) != OGR_G_GetX(hRing, vert_count-1)) ||
                    (OGR_G_GetY(hRing, 0) != OGR_G_GetY(hRing, vert_count-1)) ) {

                    PRINTF("ERROR: S-57 ring (AREA) not closed (%s)\n", objname);

                    g_assert(0);
                    continue;

                    // Note: to compute area of an open poly
                    //double area = 0;
                    //for (guint i=vert_count-1, j=0; j<vert_count; i=j, ++j) {
                    //    double x1 = OGR_G_GetX(hRing, i);
                    //    double y1 = OGR_G_GetY(hRing, i);
                    //    double x2 = OGR_G_GetX(hRing, j);
                    //    double y2 = OGR_G_GetY(hRing, j);
                    //    area += (x1*y2) - (x2*y1);
                    //}
                }

                for (guint i=0; (i+1)<vert_count; i++) {
                    double x1 = OGR_G_GetX(hRing, i  );
                    double y1 = OGR_G_GetY(hRing, i  );
                    double x2 = OGR_G_GetX(hRing, i+1);
                    double y2 = OGR_G_GetY(hRing, i+1);
                    area += (x1*y2) - (x2*y1);
                }

                // CW if area is < 0, else CCW
                //PRINTF("AREA(ring=%i/%i): %s (%s)\n", iRing, nRingCount, (area <= 0.0) ? "CW" : "CCW", objname);

                // CCW winding
                if (area > 0.0) {
                    // if first ring reverse winding to CW
                    if (0 == iRing) {
                        // debug
                        //PRINTF("DEBUG: reversing S-57 outer ring to CW (%s)\n", objname);
                        //g_assert(0);
                        for (guint node=0; node<vert_count; ++node) {
                            ringxyz[iRing][node*3+0] = OGR_G_GetX(hRing, vert_count - node-1);
                            ringxyz[iRing][node*3+1] = OGR_G_GetY(hRing, vert_count - node-1);
                            ringxyz[iRing][node*3+2] = OGR_G_GetZ(hRing, vert_count - node-1);
                        }
                    } else {
                        for (guint node=0; node<vert_count; ++node) {
                            ringxyz[iRing][node*3+0] = OGR_G_GetX(hRing, node);
                            ringxyz[iRing][node*3+1] = OGR_G_GetY(hRing, node);
                            ringxyz[iRing][node*3+2] = OGR_G_GetZ(hRing, node);
                        }
                    }


                } else {  // CW winding
                    if (0 == iRing) {
                        for (guint node=0; node<vert_count; ++node) {
                            ringxyz[iRing][node*3+0] = OGR_G_GetX(hRing, node);
                            ringxyz[iRing][node*3+1] = OGR_G_GetY(hRing, node);
                            ringxyz[iRing][node*3+2] = OGR_G_GetZ(hRing, node);
                        }
                    } else {
                        // if NOT first ring reverse winding (CCW)
                        //PRINTF("DEBUG: reversing S-57 inner ring to CCW (%s)\n", objname);
                        //g_assert(0);

                        for (guint node=0; node<vert_count; ++node) {
                            ringxyz[iRing][node*3+0] = OGR_G_GetX(hRing, vert_count - node-1);
                            ringxyz[iRing][node*3+1] = OGR_G_GetY(hRing, vert_count - node-1);
                            ringxyz[iRing][node*3+2] = OGR_G_GetZ(hRing, vert_count - node-1);
                        }
                    }

                }
            }     // for loop

            //geoData = S57_setAREAS(nRingCount, ringxyznbr, ringxyz, (area <= 0.0) ? S57_AW_CW : S57_AW_CCW);
            geoData = S57_setAREAS(nRingCount, ringxyznbr, ringxyz);
            _setExtent(geoData, hGeom);

            if (0 == g_strcmp0(WORLD_BASENM, objname)) {
                // Note: loading shapefile as a 'marfea' use a transparent fill so NODATA
                // is still visible (seem better than 'mnufea' wich has no colour fill)
                S57_setName(geoData, "marfea");

                // pslb3_2.pdf (p. II-22): Mariners' Object Class: Manufacturers' feature
                //    Note that manufacturers' areas, whether non-chart or chart areas, should not use area colour fill.
                //S57_setName(geoData, "mnufea");
            }

            break;
        }

#ifdef S52_USE_WORLD
        // shapefile area
        case wkbMultiPolygon: {
            guint nPolyCount = OGR_G_GetGeometryCount(hGeom);
            for (guint iPoly=0; iPoly<nPolyCount; ++iPoly) {
                OGRGeometryH hGeomNext = OGR_G_GetGeometryRef(hGeom, iPoly);
                // recursion
                S57_geo *geo = _ogrLoadObject(objname, NULL, hGeomNext);
                if (NULL == geoData)
                    geoData = geo;
                else
                    S57_setNextPoly(geoData, geo);

            }
            break;
        }
#endif

        case wkbGeometryCollection:
        case wkbMultiLineString: {
            PRINTF("WARNING: wkbGeometryCollection & wkbMultiLineString not handled \n");
            g_assert(0);  // land here if GDAL/OGR was patched multi-line
            break;
        }

        case wkbNone:
            // DSID layer get here
            geoData = S57_set_META();
            break; // META_T

        case wkbMultiPoint:
            // ogr SPLIT_MULTIPOINT prob !!
            PRINTF("DEBUG: Multi-Pass!!!\n");
            //PRINTF("ERROR: set env var OGR_S57_OPTIONS to SPLIT_MULTIPOINT:ON\n");
            //PRINTF("FIXME: or wkbMultiLineString found!\n");
            //g_assert_not_reached(); // MultiLineString (need this for line removal)

            //geoData = S57_set_META();

            //GvCollectionShape *collection  = (GvCollectionShape *) shape;
            //int nCollection = gv_shape_collection_get_count(shape);
            break;

        default:
            // FIXME: find a decent default (see openev/gvshapes.h)!!!
            PRINTF("WKB type not handled  = %i %0x\n", eType, eType);
            g_assert(0); 

    }

    // debug
    //PRINTF("name: %s\n", objname);

    return geoData;
}
예제 #3
0
/*!
  \brief Recursively descend to feature and read the part
  
  \param Map pointer to Map_info structure
  \param hGeom OGR geometry
  \param offset given offset
  \param[out] Points container used to store line pointes within
  
  \return feature type
  \return -1 on error
*/
static int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
		     struct line_pnts *Points)
{
    int i, nPoints;
    int eType, line;
    OGRGeometryH hGeom2;

    /* Read coors if hGeom is a simple element (wkbPoint,
     * wkbLineString) otherwise descend to geometry specified by
     * offset[offset] */

    eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
    G_debug(4, "OGR geometry type: %d", eType);

    switch (eType) {
    case wkbPoint:
	G_debug(4, "\t->Point");
	if (Points) {
	    Vect_append_point(Points, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
			      OGR_G_GetZ(hGeom, 0));
	}
	return GV_POINT;
	break;

    case wkbLineString:
	G_debug(4, "\t->LineString");	
	if (Points) {
	    nPoints = OGR_G_GetPointCount(hGeom);
	    for (i = 0; i < nPoints; i++) {
		Vect_append_point(Points, OGR_G_GetX(hGeom, i),
				  OGR_G_GetY(hGeom, i), OGR_G_GetZ(hGeom, i));
	    }
	}
	return GV_LINE;
	break;

    case wkbPolygon:
    case wkbMultiPoint:
    case wkbMultiLineString:
    case wkbMultiPolygon:
    case wkbGeometryCollection:
	G_debug(4, " \t->more geoms -> part %d", Map->fInfo.ogr.offset[offset]);
	hGeom2 = OGR_G_GetGeometryRef(hGeom, Map->fInfo.ogr.offset[offset]);
	line = read_line(Map, hGeom2, offset + 1, Points);
	if (eType == wkbPolygon || wkbMultiPolygon)
	    return GV_BOUNDARY;
	if (eType == wkbMultiPoint)
	    return GV_POINT;
	if (eType == wkbMultiLineString)
	    return GV_LINE;
	return line;
	break;

    default:
	G_warning(_("OGR feature type '%s' not supported"),
		  OGRGeometryTypeToName(eType));
	break;
    }

    return -1;
}
예제 #4
0
OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )

{
/* -------------------------------------------------------------------- */
/*      This is a geometry with sub-geometries.                         */
/* -------------------------------------------------------------------- */
    if( OGR_G_GetGeometryCount( hGeom ) > 0 )
    {
        OGRErr eErr = OGRERR_NONE;

        for( int iGeom = 0;
             iGeom < OGR_G_GetGeometryCount(hGeom) && eErr == OGRERR_NONE;
             iGeom++ )
        {
            // We need to emit polygon @P and @H items while we still
            // know this is a polygon and which is the outer and inner
            // ring.
            if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon )
            {
                if( !bHaveAngle )
                {
                    VSIFPrintfL( fp, ">\n" );
                    bHaveAngle = TRUE;
                }
                if( iGeom == 0 )
                    VSIFPrintfL( fp, "# @P\n" );
                else
                    VSIFPrintfL( fp, "# @H\n" );
            }

            eErr = WriteGeometry( OGR_G_GetGeometryRef( hGeom, iGeom ),
                                  bHaveAngle );
            bHaveAngle = FALSE;
        }
        return eErr;
    }

/* -------------------------------------------------------------------- */
/*      If this is not a point we need to have an angle bracket to      */
/*      mark the vertex list.                                           */
/* -------------------------------------------------------------------- */
    if( wkbFlatten(OGR_G_GetGeometryType(hGeom)) != wkbPoint
        && !bHaveAngle )
        VSIFPrintfL( fp, ">\n" );

/* -------------------------------------------------------------------- */
/*      Dump vertices.                                                  */
/* -------------------------------------------------------------------- */
    const int nPointCount = OGR_G_GetPointCount(hGeom);
    const int nDim = OGR_G_GetCoordinateDimension(hGeom);
    // For testing only. Ticket #6453
    const bool bUseTab = CPLTestBool( CPLGetConfigOption("GMT_USE_TAB", "FALSE") );

    for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
    {
        const double dfX = OGR_G_GetX( hGeom, iPoint );
        const double dfY = OGR_G_GetY( hGeom, iPoint );
        const double dfZ = OGR_G_GetZ( hGeom, iPoint );

        sRegion.Merge( dfX, dfY );
        char szLine[128];
        OGRMakeWktCoordinate( szLine, dfX, dfY, dfZ, nDim );
        if( bUseTab )
        {
            for( char* szPtr = szLine; *szPtr != '\0'; ++szPtr )
            {
                if( *szPtr == ' ' )
                    *szPtr = '\t';
            }
        }
        if( VSIFPrintfL( fp, "%s\n", szLine ) < 1 )
        {
            CPLError( CE_Failure, CPLE_FileIO,
                      "Gmt write failure: %s",
                      VSIStrerror( errno ) );
            return OGRERR_FAILURE;
        }
    }

    return OGRERR_NONE;
}