Example #1
0
  void EmitFeatureBase(FeatureBuilder1 & ft, FeatureParams const & params)
  {
    ft.SetParams(params);
    if (ft.PreSerialize())
    {
      string addr;
      if (m_addrWriter && ftypes::IsBuildingChecker::Instance()(params.m_Types) && ft.FormatFullAddress(addr))
        m_addrWriter->Write(addr.c_str(), addr.size());

      static uint32_t const placeType = classif().GetTypeByPath({"place"});
      uint32_t const type = params.FindType(placeType, 1);

      if (type != ftype::GetEmptyValue() && !ft.GetName().empty())
      {
        m_places.ReplaceEqualInRect(Place(ft, type),
            [](Place const & p1, Place const & p2) { return p1.IsEqual(p2); },
            [](Place const & p1, Place const & p2) { return p1.IsBetterThan(p2); });
      }
      else
        m_emitter(ft);
    }
  }
Example #2
0
void BookingDataset::BuildHotel(Hotel const & hotel,
                                function<void(FeatureBuilder1 &)> const & fn) const
{
  FeatureBuilder1 fb;
  FeatureParams params;

  fb.SetCenter(MercatorBounds::FromLatLon(hotel.lat, hotel.lon));

  auto & metadata = params.GetMetadata();
  metadata.Set(feature::Metadata::FMD_SPONSORED_ID, strings::to_string(hotel.id));
  metadata.Set(feature::Metadata::FMD_WEBSITE, hotel.descUrl);
  metadata.Set(feature::Metadata::FMD_RATING, strings::to_string(hotel.ratingUser));
  metadata.Set(feature::Metadata::FMD_STARS, strings::to_string(hotel.stars));
  metadata.Set(feature::Metadata::FMD_PRICE_RATE, strings::to_string(hotel.priceCategory));

  // params.AddAddress(hotel.address);
  // TODO(mgsergio): addr:full ???

  if (!hotel.street.empty())
    fb.AddStreet(hotel.street);

  if (!hotel.houseNumber.empty())
    fb.AddHouseNumber(hotel.houseNumber);

  params.AddName(StringUtf8Multilang::GetLangByCode(StringUtf8Multilang::kDefaultCode),
                 hotel.name);
  if (!hotel.translations.empty())
  {
    // TODO(mgsergio): Move parsing to the hotel costruction stage.
    vector<string> parts;
    strings::ParseCSVRow(hotel.translations, '|', parts);
    CHECK_EQUAL(parts.size() % 3, 0, ("Invalid translation string:", hotel.translations));
    for (auto i = 0; i < parts.size(); i += 3)
    {
      auto const langCode = StringUtf8Multilang::GetLangIndex(parts[i]);
      params.AddName(StringUtf8Multilang::GetLangByCode(langCode), parts[i + 1]);
      // TODO(mgsergio): e.AddTag("addr:full:" + parts[i], parts[i + 2]);
    }
  }

  auto const & clf = classif();
  params.AddType(clf.GetTypeByPath({"sponsored", "booking"}));
  // Matching booking.com hotel types to OpenStreetMap values.
  // Booking types are listed in the closed API docs.
  switch (hotel.type)
  {
    case 19:
    case 205: params.AddType(clf.GetTypeByPath({"tourism", "motel"})); break;

    case 21:
    case 206:
    case 212: params.AddType(clf.GetTypeByPath({"tourism", "resort"})); break;

    case 3:
    case 23:
    case 24:
    case 25:
    case 202:
    case 207:
    case 208:
    case 209:
    case 210:
    case 216:
    case 220:
    case 223: params.AddType(clf.GetTypeByPath({"tourism", "guest_house"})); break;

    case 14:
    case 204:
    case 213:
    case 218:
    case 219:
    case 226:
    case 222: params.AddType(clf.GetTypeByPath({"tourism", "hotel"})); break;

    case 211:
    case 224:
    case 228: params.AddType(clf.GetTypeByPath({"tourism", "chalet"})); break;

    case 13:
    case 225:
    case 203: params.AddType(clf.GetTypeByPath({"tourism", "hostel"})); break;

    case 215:
    case 221:
    case 227:
    case 2:
    case 201: params.AddType(clf.GetTypeByPath({"tourism", "apartment"})); break;

    case 214: params.AddType(clf.GetTypeByPath({"tourism", "camp_site"})); break;

    default: params.AddType(clf.GetTypeByPath({"tourism", "hotel"})); break;
  }

  fb.SetParams(params);

  fn(fb);
}
Example #3
0
  /// The main entry point for parsing process.
  void EmitElement(OsmElement * p)
  {
    enum class FeatureState {Unknown, Ok, EmptyTags, HasNoTypes, BrokenRef, ShortGeom, InvalidType};

    FeatureParams params;
    FeatureState state = FeatureState::Unknown;

    switch(p->type)
    {
      case OsmElement::EntityType::Node:
      {
        if (p->m_tags.empty())
        {
          state = FeatureState::EmptyTags;
          break;
        }

        if (!ParseType(p, params))
        {
          state = FeatureState::HasNoTypes;
          break;
        }

        m2::PointD const pt = MercatorBounds::FromLatLon(p->lat, p->lon);
        EmitPoint(pt, params, osm::Id::Node(p->id));
        state = FeatureState::Ok;
        break;
      }

      case OsmElement::EntityType::Way:
      {
        FeatureBuilder1 ft;

        // Parse geometry.
        for (uint64_t ref : p->Nodes())
        {
          m2::PointD pt;
          if (!m_holder.GetNode(ref, pt.y, pt.x))
          {
            state = FeatureState::BrokenRef;
            break;
          }
          ft.AddPoint(pt);
        }

        if (state == FeatureState::BrokenRef)
          break;

        if (ft.GetPointsCount() < 2)
        {
          state = FeatureState::ShortGeom;
          break;
        }

        if (!ParseType(p, params))
        {
          state = FeatureState::HasNoTypes;
          break;
        }

        ft.SetOsmId(osm::Id::Way(p->id));
        bool isCoastLine = (m_coastType != 0 && params.IsTypeExist(m_coastType));

        EmitArea(ft, params, [&] (FeatureBuilder1 & ft)
        {
          isCoastLine = false;  // emit coastline feature only once
          HolesProcessor processor(p->id, this);
          m_holder.ForEachRelationByWay(p->id, processor);
          ft.SetAreaAddHoles(processor.GetHoles());
        });

        EmitLine(ft, params, isCoastLine);
        state = FeatureState::Ok;
        break;
      }

      case OsmElement::EntityType::Relation:
      {
        {
          // 1. Check, if this is our processable relation. Here we process only polygon relations.
          size_t i = 0;
          size_t const count = p->m_tags.size();
          for (; i < count; ++i)
          {
            if (p->m_tags[i].key == "type" && p->m_tags[i].value == "multipolygon")
              break;
          }
          if (i == count)
          {
            state = FeatureState::InvalidType;
            break;
          }
        }

        if (!ParseType(p, params))
        {
          state = FeatureState::HasNoTypes;
          break;
        }

        HolesAccumulator holes(this);
        AreaWayMerger<TCache> outer(m_holder);

        // 3. Iterate ways to get 'outer' and 'inner' geometries
        for (auto const & e : p->Members())
        {
          if (e.type != OsmElement::EntityType::Way)
            continue;

          if (e.role == "outer")
            outer.AddWay(e.ref);
          else if (e.role == "inner")
            holes(e.ref);
        }

        auto const & holesGeometry = holes.GetHoles();
        outer.ForEachArea(true, [&] (FeatureBuilder1::TPointSeq const & pts, vector<uint64_t> const & ids)
        {
          FeatureBuilder1 ft;

          for (uint64_t id : ids)
            ft.AddOsmId(osm::Id::Way(id));

          for (auto const & pt : pts)
            ft.AddPoint(pt);

          ft.AddOsmId(osm::Id::Relation(p->id));
          EmitArea(ft, params, [&holesGeometry] (FeatureBuilder1 & ft) {ft.SetAreaAddHoles(holesGeometry);});
        });

        state = FeatureState::Ok;
        break;
      }

      default:
        state = FeatureState::Unknown;
        break;
    }

//    if (state == FeatureState::Ok)
//    {
//      Classificator const & c = classif();
//      static char const * const stateText[] = {"U", "Ok", "ET", "HNT", "BR", "SG", "IT"};
//      stringstream ss;
//      ss << p->id << " [" << stateText[static_cast<typename underlying_type<FeatureState>::type>(state)] << "]";
//      for (auto const & p : params.m_Types)
//        ss << " " << c.GetReadableObjectName(p);
//      ss << endl;
//      std::ofstream file("feature_types_new2.txt", ios::app);
//      file.write(ss.str().data(), ss.str().size());
//    }
  }