Exemple #1
0
  bool LabelPosition::pruneCallback( LabelPosition *lp, void *ctx )
  {
    FeaturePart *feat = (( PruneCtx* ) ctx )->obstacle;

    if (( feat == lp->feature ) || ( feat->getHoleOf() && feat->getHoleOf() != lp->feature ) )
    {
      return true;
    }

    CostCalculator::addObstacleCostPenalty( lp, feat );

    return true;
  }
Exemple #2
0
bool LabelPosition::pruneCallback( LabelPosition *candidatePosition, void *ctx )
{
  FeaturePart *obstaclePart = ( reinterpret_cast< PruneCtx* >( ctx ) )->obstacle;

  // test whether we should ignore this obstacle for the candidate. We do this if:
  // 1. it's not a hole, and the obstacle belongs to the same label feature as the candidate (eg
  // features aren't obstacles for their own labels)
  // 2. it IS a hole, and the hole belongs to a different label feature to the candidate (eg, holes
  // are ONLY obstacles for the labels of the feature they belong to)
  if (( !obstaclePart->getHoleOf() && candidatePosition->feature->hasSameLabelFeatureAs( obstaclePart ) )
      || ( obstaclePart->getHoleOf() && !candidatePosition->feature->hasSameLabelFeatureAs( dynamic_cast< FeaturePart* >( obstaclePart->getHoleOf() ) ) ) )
  {
    return true;
  }

  CostCalculator::addObstacleCostPenalty( candidatePosition, obstaclePart );

  return true;
}
Exemple #3
0
void Layer::joinConnectedFeatures()
{
    // go through all label texts
    QString labelText;
    while ( !connectedTexts->isEmpty() )
    {
        labelText = connectedTexts->takeFirst();

        //std::cerr << "JOIN: " << labelText << std::endl;
        QHash< QString, QLinkedList<FeaturePart*>* >::const_iterator partsPtr = connectedHashtable->find( labelText );
        if ( partsPtr == connectedHashtable->constEnd() )
            continue; // shouldn't happen
        QLinkedList<FeaturePart*>* parts = *partsPtr;

        // go one-by-one part, try to merge
        while ( !parts->isEmpty() )
        {
            // part we'll be checking against other in this round
            FeaturePart* partCheck = parts->takeFirst();

            FeaturePart* otherPart = _findConnectedPart( partCheck, parts );
            if ( otherPart )
            {
                //std::cerr << "- connected " << partCheck << " with " << otherPart << std::endl;

                // remove partCheck from r-tree
                double bmin[2], bmax[2];
                partCheck->getBoundingBox( bmin, bmax );
                rtree->Remove( bmin, bmax, partCheck );
                featureParts->removeOne( partCheck );

                otherPart->getBoundingBox( bmin, bmax );

                // merge points from partCheck to p->item
                if ( otherPart->mergeWithFeaturePart( partCheck ) )
                {
                    // reinsert p->item to r-tree (probably not needed)
                    rtree->Remove( bmin, bmax, otherPart );
                    otherPart->getBoundingBox( bmin, bmax );
                    rtree->Insert( bmin, bmax, otherPart );
                }
            }
        }

        // we're done processing feature parts with this particular label text
        delete parts;
    }

    // we're done processing connected fetures
    delete connectedHashtable;
    connectedHashtable = NULL;
    delete connectedTexts;
    connectedTexts = NULL;
}
Exemple #4
0
void Layer::chopFeaturesAtRepeatDistance()
{
  GEOSContextHandle_t geosctxt = geosContext();
  QLinkedList<FeaturePart*> newFeatureParts;
  while ( !mFeatureParts.isEmpty() )
  {
    FeaturePart* fpart = mFeatureParts.takeFirst();
    const GEOSGeometry* geom = fpart->geos();
    double chopInterval = fpart->repeatDistance();
    if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
    {
      chopInterval *= ceil( fpart->getLabelWidth() / fpart->repeatDistance() );

      double bmin[2], bmax[2];
      fpart->getBoundingBox( bmin, bmax );
      mFeatureIndex->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;
      QVector<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 ( int 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->feature(), newgeom );
        newFeatureParts.append( newfpart );
        newfpart->getBoundingBox( bmin, bmax );
        mFeatureIndex->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 ( int 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->feature(), newgeom );
      newFeatureParts.append( newfpart );
      newfpart->getBoundingBox( bmin, bmax );
      mFeatureIndex->Insert( bmin, bmax, newfpart );
      delete fpart;
    }
    else
    {
      newFeatureParts.append( fpart );
    }
  }

  mFeatureParts = newFeatureParts;
}
Exemple #5
0
void Layer::joinConnectedFeatures()
{
  // go through all label texts
  int connectedFeaturesId = 0;
  Q_FOREACH ( const QString& labelText, mConnectedTexts )
  {
    if ( !mConnectedHashtable.contains( labelText ) )
      continue; // shouldn't happen

    connectedFeaturesId++;

    QLinkedList<FeaturePart*>* parts = mConnectedHashtable.value( labelText );

    // go one-by-one part, try to merge
    while ( !parts->isEmpty() && parts->count() > 1 )
    {
      // part we'll be checking against other in this round
      FeaturePart* partCheck = parts->takeFirst();

      FeaturePart* otherPart = _findConnectedPart( partCheck, parts );
      if ( otherPart )
      {
        // remove partCheck from r-tree
        double checkpartBMin[2], checkpartBMax[2];
        partCheck->getBoundingBox( checkpartBMin, checkpartBMax );

        double otherPartBMin[2], otherPartBMax[2];
        otherPart->getBoundingBox( otherPartBMin, otherPartBMax );

        // merge points from partCheck to p->item
        if ( otherPart->mergeWithFeaturePart( partCheck ) )
        {
          // remove the parts we are joining from the index
          mFeatureIndex->Remove( checkpartBMin, checkpartBMax, partCheck );
          mFeatureIndex->Remove( otherPartBMin, otherPartBMax, otherPart );

          // reinsert merged line to r-tree (probably not needed)
          otherPart->getBoundingBox( otherPartBMin, otherPartBMax );
          mFeatureIndex->Insert( otherPartBMin, otherPartBMax, otherPart );

          mConnectedFeaturesIds.insert( partCheck->featureId(), connectedFeaturesId );
          mConnectedFeaturesIds.insert( otherPart->featureId(), connectedFeaturesId );

          mFeatureParts.removeOne( partCheck );
          delete partCheck;
        }
      }
    }

    // we're done processing feature parts with this particular label text
    delete parts;
    mConnectedHashtable.remove( labelText );
  }

  // we're done processing connected features

  //should be empty, but clear to be safe
  qDeleteAll( mConnectedHashtable );
  mConnectedHashtable.clear();

  mConnectedTexts.clear();
}