Fix buildings from xml loading.

This commit is contained in:
Sergey Magidovich 2016-05-05 11:02:28 +03:00 committed by Vladimir Byko-Ianko
parent abb449bc7f
commit 1a467a1b97
3 changed files with 24 additions and 21 deletions

View file

@ -10,19 +10,6 @@
#include "std/algorithm.hpp"
#include "std/unique_ptr.hpp"
namespace
{
m2::PointD CalculateCenter(vector<m2::PointD> const & geometry)
{
ASSERT(!geometry.empty() && geometry.size() % 3 == 0,
("Invalid geometry should be handled in caller. geometry.size() =", geometry.size()));
auto const boundingBox = ApplyCalculator(begin(geometry), end(geometry),
m2::CalculateBoundingBox());
return ApplyCalculator(begin(geometry), end(geometry), m2::CalculatePointOnSurface(boundingBox));
}
} // namespace
namespace editor
{
FeatureID MigrateNodeFeatureIndex(osm::Editor::TForEachFeaturesNearByFn & forEach,
@ -57,10 +44,11 @@ FeatureID MigrateWayFeatureIndex(osm::Editor::TForEachFeaturesNearByFn & forEach
auto bestScore = 0.6; // initial score is used as a threshold.
auto geometry = xml.GetGeometry();
if (geometry.empty() || geometry.size() % 3 != 0)
if (geometry.empty())
MYTHROW(MigrationError, ("Feature has invalid geometry", xml));
auto const someFeaturePoint = CalculateCenter(geometry);
// This can be any point on a feature.
auto const someFeaturePoint = geometry[0];
sort(begin(geometry), end(geometry)); // Sort to use in set_intersection.
auto count = 0;

View file

@ -389,8 +389,14 @@ Framework::Framework()
return streets.first[streets.second].m_name;
return {};
});
editor.SetForEachFeatureAtPointFn(bind(&Framework::ForEachFeatureAtPoint, this, _1, _2));
// Due to floating points accuracy issues (geometry is saved in editor up to 7 digits
// after dicimal poin) some feature vertexes are threated as external to a given feature.
auto const pointToFeatureDistanceToleranceInMeters = 1e-3;
editor.SetForEachFeatureAtPointFn(bind(&Framework::ForEachFeatureAtPoint, this, _1, _2,
pointToFeatureDistanceToleranceInMeters));
editor.LoadMapEdits();
m_model.GetIndex().AddObserver(editor);
}
Framework::~Framework()
@ -1741,7 +1747,8 @@ bool Framework::ShowMapForURL(string const & url)
return false;
}
void Framework::ForEachFeatureAtPoint(TFeatureTypeFn && fn, m2::PointD const & mercator) const
void Framework::ForEachFeatureAtPoint(TFeatureTypeFn && fn, m2::PointD const & mercator,
double featureDistanceToleranceInMeters) const
{
constexpr double kSelectRectWidthInMeters = 1.1;
constexpr double kMetersToLinearFeature = 3;
@ -1760,10 +1767,17 @@ void Framework::ForEachFeatureAtPoint(TFeatureTypeFn && fn, m2::PointD const & m
fn(ft);
break;
case feature::GEOM_AREA:
if (ft.GetLimitRect(kScale).IsPointInside(mercator) &&
feature::GetMinDistanceMeters(ft, mercator) == 0.0)
{
fn(ft);
auto limitRect = ft.GetLimitRect(kScale);
// Be a little more tolerant. When used by editor mercator is given
// with some error, so we must extend limit rect a bit.
limitRect.Inflate(MercatorBounds::GetCellID2PointAbsEpsilon(),
MercatorBounds::GetCellID2PointAbsEpsilon());
if (limitRect.IsPointInside(mercator) &&
feature::GetMinDistanceMeters(ft, mercator) <= featureDistanceToleranceInMeters)
{
fn(ft);
}
}
break;
case feature::GEOM_UNDEFINED:

View file

@ -523,7 +523,8 @@ public:
/// @returns nullptr if no feature was found at the given mercator point.
unique_ptr<FeatureType> GetFeatureAtPoint(m2::PointD const & mercator) const;
using TFeatureTypeFn = function<void(FeatureType &)>;
void ForEachFeatureAtPoint(TFeatureTypeFn && fn, m2::PointD const & mercator) const;
void ForEachFeatureAtPoint(TFeatureTypeFn && fn, m2::PointD const & mercator,
double featureDistanceToleranceInMeters = 0.0) const;
/// Set parse to false if you don't need all feature fields ready.
/// TODO(AlexZ): Refactor code which uses this method to get rid of it.
/// FeatureType instances shoud not be used outside ForEach* core methods.