예제 #1
0
S57_geo       *S57_ogrLoadObject(const char *objname, void *feature)
{
    return_if_null(objname);
    return_if_null(feature);

    // debug
    //PRINTF("DEBUG: start loading object (%s:%X)\n", objname, feature);

    S57_geo *geoData = _ogrLoadObject(objname, feature, NULL);
    if (NULL == geoData)
        return NULL;

    if (0 != strcmp(WORLD_BASENM, objname)) {
        S57_setName(geoData, objname);
    }
    _setAtt(geoData, feature);


    // debug
    //if (207 == S57_getGeoID(geoData)) {
    //    S57_dumpData(geoData, FALSE);
    //}

    //PRINTF("DEBUG: finish loading object (%s)\n", objname);

    return geoData;
}
예제 #2
0
S57_geo       *S57_ogrLoadObject(const char *objname, void *feature)
{
    return_if_null(objname);
    return_if_null(feature);

    // debug
    //PRINTF("DEBUG: start loading object (%s:%X)\n", objname, feature);

    S57_geo *geoData = _ogrLoadObject(objname, feature, NULL);
    if (NULL == geoData)
        return NULL;

    // FIXME: world has no name!
    //if (0 != g_strcmp0(WORLD_BASENM, objname)) {
        S57_setName(geoData, objname);
    //}

    _setAtt(geoData, feature);

    //PRINTF("DEBUG: finish loading object (%s)\n", objname);

    return geoData;
}
예제 #3
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;
}