Object* OgrFileImport::importGeometry(MapPart* map_part, OGRFeatureH feature, OGRGeometryH geometry) { auto geometry_type = wkbFlatten(OGR_G_GetGeometryType(geometry)); switch (geometry_type) { case OGRwkbGeometryType::wkbPoint: return importPointGeometry(map_part, feature, geometry); case OGRwkbGeometryType::wkbLineString: return importLineStringGeometry(map_part, feature, geometry); case OGRwkbGeometryType::wkbPolygon: return importPolygonGeometry(map_part, feature, geometry); case OGRwkbGeometryType::wkbGeometryCollection: case OGRwkbGeometryType::wkbMultiLineString: case OGRwkbGeometryType::wkbMultiPoint: case OGRwkbGeometryType::wkbMultiPolygon: return importGeometryCollection(map_part, feature, geometry); default: qDebug("OgrFileImport: Unknown or unsupported geometry type: %d", geometry_type); ++unsupported_geometry_type; return nullptr; } }
Polygon::Polygon(OGRGeometryH g, const SpatialReference& srs, geos::ErrorHandler& err) : m_srs(srs) , m_ctx(err.ctx) { OGRwkbGeometryType t = OGR_G_GetGeometryType(g); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << "pdal::Polygon cannot construct geometry because " "OGR geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } OGRGeometry *ogr_g = (OGRGeometry*)g; // // Convert the the GDAL geom to WKB in order to avoid the version // context issues with exporting directoly to GEOS. OGRwkbByteOrder bo = GEOS_getWKBByteOrder() == GEOS_WKB_XDR ? wkbXDR : wkbNDR; int wkbSize = ogr_g->WkbSize(); std::vector<unsigned char> wkb(wkbSize); ogr_g->exportToWkb(bo, wkb.data()); m_geom = GEOSGeomFromWKB_buf_r(m_ctx, wkb.data(), wkbSize); prepare(); }
bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) const { feature.setFeatureId( OGR_F_GetFID( fet ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect; bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); if ( geom ) { feature.setGeometry( QgsOgrUtils::ogrGeometryToQgsGeometry( geom ) ); } else feature.clearGeometry(); if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection && geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection ) { // OK } else if (( useIntersect && ( !feature.hasGeometry() || !feature.geometry().intersects( mRequest.filterRect() ) ) ) || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { OGR_F_Destroy( fet ); return false; } } if ( !mFetchGeometry ) { feature.clearGeometry(); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) { getFeatureAttribute( fet, feature, *it ); } } else { // all attributes for ( int idx = 0; idx < mSource->mFields.count(); ++idx ) { getFeatureAttribute( fet, feature, idx ); } } return true; }
/*! \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 get_line_type(const struct Map_info *Map, long FID) { int eType; OGRFeatureH hFeat; OGRGeometryH hGeom; G_debug(4, "get_line_type() fid = %ld", FID); hFeat = OGR_L_GetFeature(Map->fInfo.ogr.layer, FID); if (hFeat == NULL) return -1; hGeom = OGR_F_GetGeometryRef(hFeat); if (hGeom == NULL) return -1; eType = wkbFlatten(OGR_G_GetGeometryType(hGeom)); OGR_F_Destroy(hFeat); G_debug(4, "OGR Geometry of type: %d", eType); switch (eType) { case wkbPoint: case wkbMultiPoint: return GV_POINT; break; case wkbLineString: case wkbMultiLineString: return GV_LINE; break; case wkbPolygon: case wkbMultiPolygon: case wkbGeometryCollection: return GV_BOUNDARY; break; default: G_warning(_("OGR feature type %d not supported"), eType); break; } return -1; }
void AttributeFilter::UpdateGEOSBuffer(PointBuffer& buffer, AttributeInfo& info) { QuadIndex idx(buffer); idx.build(); if (!info.lyr) // wake up the layer { if (info.layer.size()) info.lyr = OGR_DS_GetLayerByName(info.ds.get(), info.layer.c_str()); else if (info.query.size()) { info.lyr = OGR_DS_ExecuteSQL(info.ds.get(), info.query.c_str(), 0, 0); } else info.lyr = OGR_DS_GetLayer(info.ds.get(), 0); if (!info.lyr) { std::ostringstream oss; oss << "Unable to select layer '" << info.layer << "'"; throw pdal_error(oss.str()); } } OGRFeaturePtr feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); int field_index(1); // default to first column if nothing was set if (info.column.size()) { field_index = OGR_F_GetFieldIndex(feature.get(), info.column.c_str()); if (field_index == -1) { std::ostringstream oss; oss << "No column name '" << info.column << "' was found."; throw pdal_error(oss.str()); } } while(feature) { OGRGeometryH geom = OGR_F_GetGeometryRef(feature.get()); OGRwkbGeometryType t = OGR_G_GetGeometryType(geom); int f_count = OGR_F_GetFieldCount (feature.get()); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << "Geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } OGRGeometry* ogr_g = (OGRGeometry*) geom; GEOSGeometry* geos_g (0); if (!m_geosEnvironment) { #if (GDAL_VERSION_MINOR < 11) && (GDAL_VERSION_MAJOR == 1) geos_g = ogr_g->exportToGEOS(); #else m_geosEnvironment = ogr_g->createGEOSContext(); geos_g = ogr_g->exportToGEOS(m_geosEnvironment); #endif } GEOSPreparedGeometry const* geos_pg = GEOSPrepare_r(m_geosEnvironment, geos_g); if (!geos_pg) throw pdal_error("unable to prepare geometry for index-accelerated intersection"); // Compute a total bounds for the geometry. Query the QuadTree to // find out the points that are inside the bbox. Then test each // point in the bbox against the prepared geometry. BOX3D box = computeBounds(m_geosEnvironment, geos_g); std::vector<std::size_t> ids = idx.getPoints(box); for (const auto& i : ids) { double x = buffer.getFieldAs<double>(Dimension::Id::X, i); double y = buffer.getFieldAs<double>(Dimension::Id::Y, i); double z = buffer.getFieldAs<double>(Dimension::Id::Z, i); GEOSGeometry* p = createGEOSPoint(m_geosEnvironment, x, y ,z); if (static_cast<bool>(GEOSPreparedContains_r(m_geosEnvironment, geos_pg, p))) { // We're in the poly, write the attribute value int32_t v = OGR_F_GetFieldAsInteger(feature.get(), field_index); buffer.setField(info.dim, i, v); // log()->get(LogLevel::Debug) << "Setting value: " << v << std::endl; } GEOSGeom_destroy_r(m_geosEnvironment, p); } feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); } }
// Create and add a placement to the current lithograph if it doesn't overlap // with current labels. void simplet_lithograph_add_placement(simplet_lithograph_t *litho, OGRFeatureH feature, simplet_list_t *styles, cairo_t *proj_ctx) { simplet_style_t *field = simplet_lookup_style(styles, "text-field"); if(!field) return; OGRFeatureDefnH defn; if(!(defn = OGR_F_GetDefnRef(feature))) return; int idx = OGR_FD_GetFieldIndex(defn, (const char*) field->arg); if(idx < 0) return; // Find the largest sub geometry of a particular multi-geometry. OGRGeometryH super = OGR_F_GetGeometryRef(feature); OGRGeometryH geom = super; double area = 0.0; switch(wkbFlatten(OGR_G_GetGeometryType(super))) { case wkbMultiPolygon: case wkbGeometryCollection: for(int i = 0; i < OGR_G_GetGeometryCount(super); i++) { OGRGeometryH subgeom = OGR_G_GetGeometryRef(super, i); if(subgeom == NULL) continue; double ar = OGR_G_Area(subgeom); if(ar > area) { geom = subgeom; area = ar; } } break; default: ; } // Find the center of our geometry. This sometimes throws an invalid geometry // error, so there is a slight bug here somehow. OGRGeometryH center; if(!(center = OGR_G_CreateGeometry(wkbPoint))) return; if(OGR_G_Centroid(geom, center) == OGRERR_FAILURE) { OGR_G_DestroyGeometry(center); return; } // Turn font hinting off cairo_font_options_t *opts; if(!(opts = cairo_font_options_create())){ OGR_G_DestroyGeometry(center); return; } cairo_font_options_set_hint_style(opts, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics(opts, CAIRO_HINT_METRICS_OFF); pango_cairo_context_set_font_options(litho->pango_ctx, opts); cairo_font_options_destroy(opts); // Get the field containing the text for the label. char *txt = simplet_copy_string(OGR_F_GetFieldAsString(feature, idx)); PangoLayout *layout = pango_layout_new(litho->pango_ctx); pango_layout_set_text(layout, txt, -1); free(txt); // Grab the font to use and apply tracking. simplet_style_t *font = simplet_lookup_style(styles, "font"); simplet_apply_styles(layout, styles, "letter-spacing", NULL); const char *font_family; if(!font) font_family = "helvetica 12px"; else font_family = font->arg; PangoFontDescription *desc = pango_font_description_from_string(font_family); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); double x = OGR_G_GetX(center, 0), y = OGR_G_GetY(center, 0); cairo_user_to_device(proj_ctx, &x, &y); // Finally try the placement and test for overlaps. try_and_insert_placement(litho, layout, x, y); OGR_G_DestroyGeometry(center); }
CPLErr GDALWarpCutlineMasker( void *pMaskFuncArg, CPL_UNUSED int nBandCount, CPL_UNUSED GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte ** /*ppImageData */, int bMaskIsFloat, void *pValidityMask ) { GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg; float *pafMask = (float *) pValidityMask; CPLErr eErr; GDALDriverH hMemDriver; if( nXSize < 1 || nYSize < 1 ) return CE_None; /* -------------------------------------------------------------------- */ /* Do some minimal checking. */ /* -------------------------------------------------------------------- */ if( !bMaskIsFloat ) { CPLAssert( FALSE ); return CE_Failure; } if( psWO == NULL || psWO->hCutline == NULL ) { CPLAssert( FALSE ); return CE_Failure; } hMemDriver = GDALGetDriverByName("MEM"); if (hMemDriver == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "GDALWarpCutlineMasker needs MEM driver"); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Check the polygon. */ /* -------------------------------------------------------------------- */ OGRGeometryH hPolygon = (OGRGeometryH) psWO->hCutline; OGREnvelope sEnvelope; if( wkbFlatten(OGR_G_GetGeometryType(hPolygon)) != wkbPolygon && wkbFlatten(OGR_G_GetGeometryType(hPolygon)) != wkbMultiPolygon ) { CPLAssert( FALSE ); return CE_Failure; } OGR_G_GetEnvelope( hPolygon, &sEnvelope ); if( sEnvelope.MaxX + psWO->dfCutlineBlendDist < nXOff || sEnvelope.MinX - psWO->dfCutlineBlendDist > nXOff + nXSize || sEnvelope.MaxY + psWO->dfCutlineBlendDist < nYOff || sEnvelope.MinY - psWO->dfCutlineBlendDist > nYOff + nYSize ) { // We are far from the blend line - everything is masked to zero. // It would be nice to realize no work is required for this whole // chunk! memset( pafMask, 0, sizeof(float) * nXSize * nYSize ); return CE_None; } /* -------------------------------------------------------------------- */ /* Create a byte buffer into which we can burn the */ /* mask polygon and wrap it up as a memory dataset. */ /* -------------------------------------------------------------------- */ GByte *pabyPolyMask = (GByte *) CPLCalloc( nXSize, nYSize ); GDALDatasetH hMemDS; double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }; char szDataPointer[100]; char *apszOptions[] = { szDataPointer, NULL }; memset( szDataPointer, 0, sizeof(szDataPointer) ); sprintf( szDataPointer, "DATAPOINTER=" ); CPLPrintPointer( szDataPointer+strlen(szDataPointer), pabyPolyMask, sizeof(szDataPointer) - strlen(szDataPointer) ); hMemDS = GDALCreate( hMemDriver, "warp_temp", nXSize, nYSize, 0, GDT_Byte, NULL ); GDALAddBand( hMemDS, GDT_Byte, apszOptions ); GDALSetGeoTransform( hMemDS, adfGeoTransform ); /* -------------------------------------------------------------------- */ /* Burn the polygon into the mask with 1.0 values. */ /* -------------------------------------------------------------------- */ int nTargetBand = 1; double dfBurnValue = 255.0; int anXYOff[2]; char **papszRasterizeOptions = NULL; if( CSLFetchBoolean( psWO->papszWarpOptions, "CUTLINE_ALL_TOUCHED", FALSE )) papszRasterizeOptions = CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" ); anXYOff[0] = nXOff; anXYOff[1] = nYOff; eErr = GDALRasterizeGeometries( hMemDS, 1, &nTargetBand, 1, &hPolygon, CutlineTransformer, anXYOff, &dfBurnValue, papszRasterizeOptions, NULL, NULL ); CSLDestroy( papszRasterizeOptions ); // Close and ensure data flushed to underlying array. GDALClose( hMemDS ); /* -------------------------------------------------------------------- */ /* In the case with no blend distance, we just apply this as a */ /* mask, zeroing out everything outside the polygon. */ /* -------------------------------------------------------------------- */ if( psWO->dfCutlineBlendDist == 0.0 ) { int i; for( i = nXSize * nYSize - 1; i >= 0; i-- ) { if( pabyPolyMask[i] == 0 ) ((float *) pValidityMask)[i] = 0.0; } } else { eErr = BlendMaskGenerator( nXOff, nYOff, nXSize, nYSize, pabyPolyMask, (float *) pValidityMask, hPolygon, psWO->dfCutlineBlendDist ); } /* -------------------------------------------------------------------- */ /* Clean up. */ /* -------------------------------------------------------------------- */ CPLFree( pabyPolyMask ); return eErr; }
/*! \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; } }
/*! \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; }
void AttributeFilter::UpdateGEOSBuffer(PointView& view) { QuadIndex idx(view); if (m_layer.size()) m_lyr = OGR_DS_GetLayerByName(m_ds.get(), m_layer.c_str()); else if (m_query.size()) m_lyr = OGR_DS_ExecuteSQL(m_ds.get(), m_query.c_str(), 0, 0); else m_lyr = OGR_DS_GetLayer(m_ds.get(), 0); if (!m_lyr) { std::ostringstream oss; oss << getName() << ": Unable to select layer '" << m_layer << "'"; throw pdal_error(oss.str()); } OGRFeaturePtr feature = OGRFeaturePtr(OGR_L_GetNextFeature(m_lyr), OGRFeatureDeleter()); int field_index(1); // default to first column if nothing was set if (m_column.size()) { field_index = OGR_F_GetFieldIndex(feature.get(), m_column.c_str()); if (field_index == -1) { std::ostringstream oss; oss << getName() << ": No column name '" << m_column << "' was found."; throw pdal_error(oss.str()); } } while (feature) { OGRGeometryH geom = OGR_F_GetGeometryRef(feature.get()); OGRwkbGeometryType t = OGR_G_GetGeometryType(geom); int32_t fieldVal = OGR_F_GetFieldAsInteger(feature.get(), field_index); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << getName() << ": Geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } pdal::Polygon p(geom, view.spatialReference(), GlobalEnvironment::get().geos()); // Compute a total bounds for the geometry. Query the QuadTree to // find out the points that are inside the bbox. Then test each // point in the bbox against the prepared geometry. BOX3D box = p.bounds(); std::vector<PointId> ids = idx.getPoints(box); for (const auto& i : ids) { PointRef ref(view, i); if (p.covers(ref)) view.setField(m_dim, i, fieldVal); } feature = OGRFeaturePtr(OGR_L_GetNextFeature(m_lyr), OGRFeatureDeleter()); } }
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; }
bool QgsOgrFeatureIterator::readFeature( gdal::ogr_feature_unique_ptr fet, QgsFeature &feature ) const { feature.setId( OGR_F_GetFID( fet.get() ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups bool useIntersect = !mRequest.filterRect().isNull(); bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet.get() ); if ( geom ) { QgsGeometry g = QgsOgrUtils::ogrGeometryToQgsGeometry( geom ); // Insure that multipart datasets return multipart geometry if ( QgsWkbTypes::isMultiType( mSource->mWkbType ) && !g.isMultipart() ) { g.convertToMultiType(); } feature.setGeometry( g ); } else feature.clearGeometry(); if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection && geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection ) { // OK } else if ( ( useIntersect && ( !feature.hasGeometry() || ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && !feature.geometry().intersects( mFilterRect ) ) || ( !( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) && !feature.geometry().boundingBoxIntersects( mFilterRect ) ) ) ) || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten( ( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { return false; } } if ( !mFetchGeometry ) { feature.clearGeometry(); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.constBegin(); it != attrs.constEnd(); ++it ) { getFeatureAttribute( fet.get(), feature, *it ); } } else { // all attributes const auto fieldCount = mSource->mFields.count(); for ( int idx = 0; idx < fieldCount; ++idx ) { getFeatureAttribute( fet.get(), feature, idx ); } } return true; }
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; }