Esempio n. 1
0
bool Layer::registerFeature( const QString& geom_id, PalGeometry *userGeom, double label_x, double label_y, const QString &labelText,
                             double labelPosX, double labelPosY, bool fixedPos, double angle, bool fixedAngle,
                             int xQuadOffset, int yQuadOffset, double xOffset, double yOffset, bool alwaysShow, double repeatDistance )
{
    if ( geom_id.isEmpty() || label_x < 0 || label_y < 0 )
        return false;

    mMutex.lock();

    if ( hashtable->contains( geom_id ) )
    {
        mMutex.unlock();
        //A feature with this id already exists. Don't throw an exception as sometimes,
        //the same feature is added twice (dateline split with otf-reprojection)
        return false;
    }

    // Split MULTI GEOM and Collection in simple geometries
    const GEOSGeometry *the_geom = userGeom->getGeosGeometry();

    Feature* f = new Feature( this, geom_id, userGeom, label_x, label_y );
    if ( fixedPos )
    {
        f->setFixedPosition( labelPosX, labelPosY );
    }
    if ( xQuadOffset != 0 || yQuadOffset != 0 )
    {
        f->setQuadOffset( xQuadOffset, yQuadOffset );
    }
    if ( xOffset != 0.0 || yOffset != 0.0 )
    {
        f->setPosOffset( xOffset, yOffset );
    }
    if ( fixedAngle )
    {
        f->setFixedAngle( angle );
    }
    // use layer-level defined rotation, but not if position fixed
    if ( !fixedPos && angle != 0.0 )
    {
        f->setFixedAngle( angle );
    }
    f->setRepeatDistance( repeatDistance );

    f->setAlwaysShow( alwaysShow );

    bool first_feat = true;

    double geom_size = -1, biggest_size = -1;
    FeaturePart* biggest_part = NULL;

    // break the (possibly multi-part) geometry into simple geometries
    QLinkedList<const GEOSGeometry*>* simpleGeometries = unmulti( the_geom );
    if ( simpleGeometries == NULL ) // unmulti() failed?
    {
        mMutex.unlock();
        throw InternalException::UnknownGeometry();
    }

    GEOSContextHandle_t geosctxt = geosContext();

    while ( simpleGeometries->size() > 0 )
    {
        const GEOSGeometry* geom = simpleGeometries->takeFirst();

        // ignore invalid geometries (e.g. polygons with self-intersecting rings)
        if ( GEOSisValid_r( geosctxt, geom ) != 1 ) // 0=invalid, 1=valid, 2=exception
        {
//        std::cerr << "ignoring invalid feature " << geom_id << std::endl;
            continue;
        }

        int type = GEOSGeomTypeId_r( geosctxt, geom );

        if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
        {
            mMutex.unlock();
            throw InternalException::UnknownGeometry();
        }

        FeaturePart* fpart = new FeaturePart( f, geom );

        // ignore invalid geometries
        if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
                ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
        {
            delete fpart;
            continue;
        }

        // polygons: reorder coordinates
        if ( type == GEOS_POLYGON && reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
        {
            delete fpart;
            continue;
        }

        if ( mMode == LabelPerFeature && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
        {
            if ( type == GEOS_LINESTRING )
                GEOSLength_r( geosctxt, geom, &geom_size );
            else if ( type == GEOS_POLYGON )
                GEOSArea_r( geosctxt, geom, &geom_size );

            if ( geom_size > biggest_size )
            {
                biggest_size = geom_size;
                delete biggest_part; // safe with NULL part
                biggest_part = fpart;
            }
            continue; // don't add the feature part now, do it later
            // TODO: we should probably add also other parts to act just as obstacles
        }

        // feature part is ready!
        addFeaturePart( fpart, labelText );

        first_feat = false;
    }
    delete simpleGeometries;

    userGeom->releaseGeosGeometry( the_geom );

    mMutex.unlock();

    // if using only biggest parts...
    if (( mMode == LabelPerFeature || f->fixedPosition() ) && biggest_part != NULL )
    {
        addFeaturePart( biggest_part, labelText );
        first_feat = false;
    }

    // add feature to layer if we have added something
    if ( !first_feat )
    {
        features->append( f );
        hashtable->insert( geom_id, f );
    }
    else
    {
        delete f;
    }

    return !first_feat; // true if we've added something
}
Esempio n. 2
0
  bool Layer::registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x, double label_y, const char* labelText,
                               double labelPosX, double labelPosY, bool fixedPos, double angle, bool fixedAngle )
  {
    if ( !geom_id || label_x < 0 || label_y < 0 )
      return false;

    modMutex->lock();

    if ( hashtable->find( geom_id ) )
    {
      modMutex->unlock();
      //A feature with this id already exists. Don't throw an exception as sometimes,
      //the same feature is added twice (dateline split with otf-reprojection)
      return false;
    }

    // Split MULTI GEOM and Collection in simple geometries
    GEOSGeometry *the_geom = userGeom->getGeosGeometry();

    Feature* f = new Feature( this, geom_id, userGeom, label_x, label_y );
    if ( fixedPos )
    {
      f->setFixedPosition( labelPosX, labelPosY );
    }
    if ( fixedAngle )
    {
      f->setFixedAngle( angle );
    }

    bool first_feat = true;

    double geom_size = -1, biggest_size = -1;
    FeaturePart* biggest_part = NULL;

    // break the (possibly multi-part) geometry into simple geometries
    LinkedList <const GEOSGeometry*> *simpleGeometries = unmulti( the_geom );

    while ( simpleGeometries->size() > 0 )
    {
      const GEOSGeometry* geom = simpleGeometries->pop_front();

      // ignore invalid geometries (e.g. polygons with self-intersecting rings)
      if ( GEOSisValid( geom ) != 1 ) // 0=invalid, 1=valid, 2=exception
      {
        std::cerr << "ignoring invalid feature " << geom_id << std::endl;
        continue;
      }

      int type = GEOSGeomTypeId( geom );

      if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
        throw InternalException::UnknownGeometry();

      FeaturePart* fpart = new FeaturePart( f, geom );

      // ignore invalid geometries
      if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
          ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
      {
        delete fpart;
        continue;
      }

      // polygons: reorder coordinates
      if ( type == GEOS_POLYGON && reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
      {
        delete fpart;
        continue;
      }

      if ( mode == LabelPerFeature && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
      {
        if ( type == GEOS_LINESTRING )
          GEOSLength( geom, &geom_size );
        else if ( type == GEOS_POLYGON )
          GEOSArea( geom, &geom_size );

        if ( geom_size > biggest_size )
        {
          biggest_size = geom_size;
          delete biggest_part; // safe with NULL part
          biggest_part = fpart;
        }
        continue; // don't add the feature part now, do it later
        // TODO: we should probably add also other parts to act just as obstacles
      }

      // feature part is ready!
      addFeaturePart( fpart, labelText );

      first_feat = false;
    }
    delete simpleGeometries;

    userGeom->releaseGeosGeometry( the_geom );

    modMutex->unlock();

    // if using only biggest parts...
    if (( mode == LabelPerFeature || f->fixedPosition() ) && biggest_part != NULL )
    {
      addFeaturePart( biggest_part, labelText );
      first_feat = false;
    }

    // add feature to layer if we have added something
    if ( !first_feat )
    {
      features->push_back( f );
      hashtable->insertItem( geom_id, f );
    }
    else
    {
      delete f;
    }

    return !first_feat; // true if we've added something
  }