Exemple #1
0
  bool LabelPosition::crossesBoundary( PointSet *polygon ) const
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !polygon->mGeos )
      polygon->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();
    try
    {
      if ( GEOSPreparedOverlaps_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1
           || GEOSPreparedTouches_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1 )
      {
        return true;
      }
      else if ( nextPart )
      {
        return nextPart->crossesBoundary( polygon );
      }
    }
    catch ( GEOSException &e )
    {
      QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
      return false;
    }

    return false;
  }
Exemple #2
0
  bool LabelPosition::crossesLine( PointSet* line ) const
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !line->mGeos )
      line->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();
    try
    {
      if ( GEOSPreparedIntersects_r( geosctxt, line->preparedGeom(), mGeos ) == 1 )
      {
        return true;
      }
      else if ( nextPart )
      {
        return nextPart->crossesLine( line );
      }
    }
    catch ( GEOSException &e )
    {
      QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
      return false;
    }

    return false;
  }
Exemple #3
0
  bool LabelPosition::isInConflictSinglePart( LabelPosition* lp )
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !lp->mGeos )
      lp->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();
    bool result = ( GEOSPreparedIntersects_r( geosctxt, preparedGeom(), lp->mGeos ) == 1 );
    return result;
  }
Exemple #4
0
  int LabelPosition::polygonIntersectionCost( PointSet *polygon ) const
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !polygon->mGeos )
      polygon->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();

    int cost = 0;
    //check the label center. if covered by polygon, initial cost of 4
    if ( polygon->containsPoint(( x[0] + x[2] ) / 2.0, ( y[0] + y[2] ) / 2.0 ) )
      cost += 4;

    try
    {
      //calculate proportion of label candidate which is covered by polygon
      GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosctxt, mGeos, polygon->mGeos );
      if ( !intersectionGeom )
        return cost;

      double positionArea = 0;
      if ( GEOSArea_r( geosctxt, mGeos, &positionArea ) != 1 )
      {
        GEOSGeom_destroy_r( geosctxt, intersectionGeom );
        return cost;
      }

      double intersectionArea = 0;
      if ( GEOSArea_r( geosctxt, intersectionGeom, &intersectionArea ) != 1 )
      {
        intersectionArea = 0;
      }

      GEOSGeom_destroy_r( geosctxt, intersectionGeom );

      double portionCovered = intersectionArea / positionArea;
      cost += ceil( portionCovered * 8.0 ); //cost of 8 if totally covered
      return cost;
    }
    catch ( GEOSException &e )
    {
      QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
      return cost;
    }
  }
Exemple #5
0
QLinkedList<const GEOSGeometry *>* pal::Util::unmulti( const GEOSGeometry *the_geom )
{
  QLinkedList<const GEOSGeometry*> *queue = new QLinkedList<const GEOSGeometry*>;
  QLinkedList<const GEOSGeometry*> *final_queue = new QLinkedList<const GEOSGeometry*>;

  const GEOSGeometry *geom;

  queue->append( the_geom );
  int nGeom;
  int i;

  GEOSContextHandle_t geosctxt = geosContext();

  while ( !queue->isEmpty() )
  {
    geom = queue->takeFirst();
    int type = GEOSGeomTypeId_r( geosctxt, geom );
    switch ( type )
    {
      case GEOS_MULTIPOINT:
      case GEOS_MULTILINESTRING:
      case GEOS_MULTIPOLYGON:
        nGeom = GEOSGetNumGeometries_r( geosctxt, geom );
        for ( i = 0; i < nGeom; i++ )
        {
          queue->append( GEOSGetGeometryN_r( geosctxt, geom, i ) );
        }
        break;
      case GEOS_POINT:
      case GEOS_LINESTRING:
      case GEOS_POLYGON:
        final_queue->append( geom );
        break;
      default:
        QgsDebugMsg( QString( "unexpected geometry type:%1" ).arg( type ) );
        delete final_queue;
        delete queue;
        return nullptr;
    }
  }
  delete queue;

  return final_queue;
}
Exemple #6
0
  bool LabelPosition::isInConflictSinglePart( LabelPosition* lp )
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !lp->mGeos )
      lp->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();
    try
    {
      bool result = ( GEOSPreparedIntersects_r( geosctxt, preparedGeom(), lp->mGeos ) == 1 );
      return result;
    }
    catch ( GEOSException &e )
    {
      QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
      return false;
    }
  }
Exemple #7
0
  bool LabelPosition::crossesLine( PointSet* line ) const
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !line->mGeos )
      line->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();
    if ( GEOSPreparedIntersects_r( geosctxt, line->preparedGeom(), mGeos ) == 1 )
    {
      return true;
    }
    else if ( nextPart )
    {
      return nextPart->crossesLine( line );
    }

    return false;
  }
Exemple #8
0
  QLinkedList<const GEOSGeometry *> *unmulti( const GEOSGeometry *the_geom )
  {
    QLinkedList<const GEOSGeometry*> *queue = new QLinkedList<const GEOSGeometry*>;
    QLinkedList<const GEOSGeometry*> *final_queue = new QLinkedList<const GEOSGeometry*>;

    const GEOSGeometry *geom;

    queue->append( the_geom );
    int nGeom;
    int i;

    while ( !queue->isEmpty() )
    {
      geom = queue->takeFirst();
      GEOSContextHandle_t geosctxt = geosContext();
      switch ( GEOSGeomTypeId_r( geosctxt, geom ) )
      {
        case GEOS_MULTIPOINT:
        case GEOS_MULTILINESTRING:
        case GEOS_MULTIPOLYGON:
          nGeom = GEOSGetNumGeometries_r( geosctxt, geom );
          for ( i = 0; i < nGeom; i++ )
          {
            queue->append( GEOSGetGeometryN_r( geosctxt, geom, i ) );
          }
          break;
        case GEOS_POINT:
        case GEOS_LINESTRING:
        case GEOS_POLYGON:
          final_queue->append( geom );
          break;
        default:
          delete final_queue;
          delete queue;
          return NULL;
      }
    }
    delete queue;

    return final_queue;
  }
Exemple #9
0
  bool LabelPosition::crossesBoundary( PointSet *polygon ) const
  {
    if ( !mGeos )
      createGeosGeom();

    if ( !polygon->mGeos )
      polygon->createGeosGeom();

    GEOSContextHandle_t geosctxt = geosContext();
    if ( GEOSPreparedOverlaps_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1
         || GEOSPreparedTouches_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1 )
    {
      return true;
    }
    else if ( nextPart )
    {
      return nextPart->crossesBoundary( polygon );
    }

    return false;
  }
Exemple #10
0
void Layer::chopFeaturesAtRepeatDistance()
{
    GEOSContextHandle_t geosctxt = geosContext();
    QLinkedList<FeaturePart*> * newFeatureParts = new QLinkedList<FeaturePart*>;
    while ( !featureParts->isEmpty() )
    {
        FeaturePart* fpart = featureParts->takeFirst();
        const GEOSGeometry* geom = fpart->geos();
        double chopInterval = fpart->getFeature()->repeatDistance();
        if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
        {

            double bmin[2], bmax[2];
            fpart->getBoundingBox( bmin, bmax );
            rtree->Remove( bmin, bmax, fpart );

            const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );

            // get number of points
            unsigned int n;
            GEOSCoordSeq_getSize_r( geosctxt, cs, &n );

            // Read points
            std::vector<Point> points( n );
            for ( unsigned int i = 0; i < n; ++i )
            {
                GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
                GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
            }

            // Cumulative length vector
            std::vector<double> len( n, 0 );
            for ( unsigned int i = 1; i < n; ++i )
            {
                double dx = points[i].x - points[i - 1].x;
                double dy = points[i].y - points[i - 1].y;
                len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
            }

            // Walk along line
            unsigned int cur = 0;
            double lambda = 0;
            std::vector<Point> part;
            for ( ;; )
            {
                lambda += chopInterval;
                for ( ; cur < n && lambda > len[cur]; ++cur )
                {
                    part.push_back( points[cur] );
                }
                if ( cur >= n )
                {
                    break;
                }
                double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
                Point p;
                p.x = points[cur - 1].x + c * ( points[cur].x - points[cur - 1].x );
                p.y = points[cur - 1].y + c * ( points[cur].y - points[cur - 1].y );
                part.push_back( p );
                GEOSCoordSequence* cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 );
                for ( std::size_t i = 0; i < part.size(); ++i )
                {
                    GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
                    GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
                }

                GEOSGeometry* newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
                FeaturePart* newfpart = new FeaturePart( fpart->getFeature(), newgeom );
                newFeatureParts->append( newfpart );
                newfpart->getBoundingBox( bmin, bmax );
                rtree->Insert( bmin, bmax, newfpart );
                part.clear();
                part.push_back( p );
            }
            // Create final part
            part.push_back( points[n - 1] );
            GEOSCoordSequence* cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 );
            for ( std::size_t i = 0; i < part.size(); ++i )
            {
                GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
                GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
            }

            GEOSGeometry* newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
            FeaturePart* newfpart = new FeaturePart( fpart->getFeature(), newgeom );
            newFeatureParts->append( newfpart );
            newfpart->getBoundingBox( bmin, bmax );
            rtree->Insert( bmin, bmax, newfpart );
        }
        else
        {
            newFeatureParts->append( fpart );
        }
    }

    delete featureParts;
    featureParts = newFeatureParts;
}
Exemple #11
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
}