forked from organicmaps/organicmaps
[indexer_tool] Added --simplify_countries_level
Now country polygons which are enabled by --split_by_polygons parameter can be optionally simplified by giving simplificator level values
This commit is contained in:
parent
770c00d653
commit
99e1e6b7a8
6 changed files with 67 additions and 28 deletions
|
@ -301,7 +301,7 @@ bool GenerateImpl(GenerateInfo & info)
|
|||
{
|
||||
typedef Polygonizer<FeaturesCollector, MercatorBounds, RectId> FeaturePolygonizerType;
|
||||
// prefix is data dir
|
||||
FeaturePolygonizerType bucketer(info.datFilePrefix, collectorInitData);
|
||||
FeaturePolygonizerType bucketer(info.datFilePrefix, collectorInitData, info.m_simplifyCountriesLevel);
|
||||
TParser<FeaturePolygonizerType, holder_t> parser(bucketer, holder);
|
||||
ParseXMLFromStdIn(parser);
|
||||
bucketer.GetBucketNames(MakeBackInsertFunctor(info.bucketNames));
|
||||
|
|
|
@ -16,7 +16,8 @@ namespace feature
|
|||
struct GenerateInfo
|
||||
{
|
||||
GenerateInfo()
|
||||
: m_maxScaleForWorldFeatures(-1), m_worldOnly(false), m_splitByPolygons(false) {}
|
||||
: m_maxScaleForWorldFeatures(-1), m_worldOnly(false), m_splitByPolygons(false),
|
||||
m_simplifyCountriesLevel(-1) {}
|
||||
string dir, datFilePrefix, datFileSuffix;
|
||||
int cellBucketingLevel;
|
||||
vector<string> bucketNames;
|
||||
|
@ -26,6 +27,7 @@ namespace feature
|
|||
int m_maxScaleForWorldFeatures;
|
||||
bool m_worldOnly;
|
||||
bool m_splitByPolygons;
|
||||
int m_simplifyCountriesLevel;
|
||||
};
|
||||
|
||||
bool GenerateFeatures(GenerateInfo & info, bool lightNodes);
|
||||
|
|
|
@ -49,6 +49,7 @@ DEFINE_int32(worldmap_max_zoom, -1, "If specified, features for zoomlevels [0..t
|
|||
" which are enabled in classificator will be added to the separate world.map");
|
||||
DEFINE_bool(world_only, false, "Generate only world features for given worldmap_max_zoom");
|
||||
DEFINE_bool(split_by_polygons, false, "Use kml shape files to split planet by regions and countries");
|
||||
DEFINE_int32(simplify_countries_level, -1, "If positive, simplifies country polygons. Recommended values [10..15]");
|
||||
|
||||
string AddSlashIfNeeded(string const & str)
|
||||
{
|
||||
|
@ -126,6 +127,7 @@ int main(int argc, char ** argv)
|
|||
|
||||
// split data by countries polygons
|
||||
genInfo.m_splitByPolygons = FLAGS_split_by_polygons;
|
||||
genInfo.m_simplifyCountriesLevel = FLAGS_simplify_countries_level;
|
||||
|
||||
genInfo.cellBucketingLevel = FLAGS_bucketing_level;
|
||||
genInfo.m_maxScaleForWorldFeatures = FLAGS_worldmap_max_zoom;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "kml_parser.hpp"
|
||||
#include "feature_sorter.hpp"
|
||||
|
||||
#include "../../base/string_utils.hpp"
|
||||
#include "../../base/logging.hpp"
|
||||
|
@ -27,9 +28,10 @@ namespace kml
|
|||
string m_data;
|
||||
|
||||
CountryPolygons & m_country;
|
||||
int m_simplifyCountriesLevel;
|
||||
|
||||
public:
|
||||
KmlParser(CountryPolygons & country);
|
||||
KmlParser(CountryPolygons & country, int simplifyCountriesLevel);
|
||||
|
||||
bool Push(string const & element);
|
||||
void Pop(string const & element);
|
||||
|
@ -37,7 +39,8 @@ namespace kml
|
|||
void CharData(string const & data);
|
||||
};
|
||||
|
||||
KmlParser::KmlParser(CountryPolygons & country) : m_country(country)
|
||||
KmlParser::KmlParser(CountryPolygons & country, int simplifyCountriesLevel)
|
||||
: m_country(country), m_simplifyCountriesLevel(simplifyCountriesLevel)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -74,17 +77,20 @@ namespace kml
|
|||
double lat;
|
||||
CHECK(utils::to_double(latStr, lat), ("invalid lon", latStr));
|
||||
// to mercator
|
||||
double const x = MercatorBounds::LonToX(lon);
|
||||
double const y = MercatorBounds::LatToY(lat);
|
||||
m_rect.Add(m2::PointD(x, y));
|
||||
// convert points to uint32_t
|
||||
typedef CellIdConverter<MercatorBounds, RectId> CellIdConverterType;
|
||||
uint32_t const ix = static_cast<uint32_t>(CellIdConverterType::XToCellIdX(x));
|
||||
uint32_t const iy = static_cast<uint32_t>(CellIdConverterType::YToCellIdY(y));
|
||||
m_container.push_back(Region::value_type(ix, iy));
|
||||
m2::PointD const mercPoint(MercatorBounds::LonToX(lon), MercatorBounds::LatToY(lat));
|
||||
m_rect.Add(mercPoint);
|
||||
m_container.push_back(mercPoint);
|
||||
}
|
||||
};
|
||||
|
||||
m2::PointU MercatorPointToPointU(m2::PointD const & pt)
|
||||
{
|
||||
typedef CellIdConverter<MercatorBounds, RectId> CellIdConverterType;
|
||||
uint32_t const ix = static_cast<uint32_t>(CellIdConverterType::XToCellIdX(pt.x));
|
||||
uint32_t const iy = static_cast<uint32_t>(CellIdConverterType::YToCellIdY(pt.y));
|
||||
return m2::PointU(ix, iy);
|
||||
}
|
||||
|
||||
void KmlParser::Pop(string const & element)
|
||||
{
|
||||
if (element == "Placemark")
|
||||
|
@ -98,17 +104,33 @@ namespace kml
|
|||
|
||||
if (m_tags[size - 3] == "outerBoundaryIs")
|
||||
{
|
||||
typedef vector<Region::value_type> ContainerT;
|
||||
ContainerT points;
|
||||
// first, collect points in Mercator
|
||||
typedef vector<m2::PointD> MercPointsContainerT;
|
||||
MercPointsContainerT points;
|
||||
m2::RectD rect;
|
||||
PointsCollector<ContainerT> collector(points, rect);
|
||||
PointsCollector<MercPointsContainerT> collector(points, rect);
|
||||
utils::TokenizeString(m_data, " \n\r\a", collector);
|
||||
size_t const numPoints = points.size();
|
||||
if (numPoints > 3 && points[numPoints - 1] == points[0])
|
||||
{
|
||||
// remove last point which is equal to first
|
||||
points.pop_back();
|
||||
m_country.m_regions.push_back(Region(points.begin(), points.end()));
|
||||
|
||||
// second, simplify points if necessary
|
||||
if (m_simplifyCountriesLevel > 0)
|
||||
{
|
||||
MercPointsContainerT simplifiedPoints;
|
||||
feature::SimplifyPoints(points, simplifiedPoints, m_simplifyCountriesLevel);
|
||||
LOG_SHORT(LINFO, (m_country.m_name, numPoints, "simplified to ", simplifiedPoints.size()));
|
||||
points.swap(simplifiedPoints);
|
||||
}
|
||||
|
||||
// third, convert mercator doubles to uint points
|
||||
Region region;
|
||||
for (MercPointsContainerT::iterator it = points.begin(); it != points.end(); ++it)
|
||||
region.AddPoint(MercatorPointToPointU(*it));
|
||||
|
||||
m_country.m_regions.push_back(region);
|
||||
m_country.m_rect.Add(rect);
|
||||
}
|
||||
else
|
||||
|
@ -147,9 +169,10 @@ namespace kml
|
|||
}
|
||||
}
|
||||
|
||||
bool LoadPolygonsFromKml(string const & kmlFile, CountryPolygons & country)
|
||||
bool LoadPolygonsFromKml(string const & kmlFile, CountryPolygons & country,
|
||||
int simplifyCountriesLevel)
|
||||
{
|
||||
KmlParser parser(country);
|
||||
KmlParser parser(country, simplifyCountriesLevel);
|
||||
try
|
||||
{
|
||||
FileReader file(kmlFile);
|
||||
|
@ -166,16 +189,19 @@ namespace kml
|
|||
{
|
||||
string m_baseDir;
|
||||
CountryPolygons & m_out;
|
||||
int m_simplifyCountriesLevel;
|
||||
|
||||
public:
|
||||
PolygonLoader(string const & basePolygonsDir, CountryPolygons & polygons)
|
||||
: m_baseDir(basePolygonsDir), m_out(polygons) {}
|
||||
PolygonLoader(string const & basePolygonsDir, CountryPolygons & polygons,
|
||||
int simplifyCountriesLevel)
|
||||
: m_baseDir(basePolygonsDir), m_out(polygons),
|
||||
m_simplifyCountriesLevel(simplifyCountriesLevel) {}
|
||||
void operator()(string const & name)
|
||||
{
|
||||
if (m_out.m_name.empty())
|
||||
m_out.m_name = name;
|
||||
CountryPolygons current;
|
||||
if (LoadPolygonsFromKml(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, current)
|
||||
if (LoadPolygonsFromKml(m_baseDir + BORDERS_DIR + name + BORDERS_EXTENSION, current, m_simplifyCountriesLevel)
|
||||
&& current.m_regions.size())
|
||||
{
|
||||
m_out.m_regions.insert(m_out.m_regions.end(),
|
||||
|
@ -185,8 +211,14 @@ namespace kml
|
|||
}
|
||||
};
|
||||
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries)
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries,
|
||||
int simplifyCountriesLevel)
|
||||
{
|
||||
if (simplifyCountriesLevel > 0)
|
||||
{
|
||||
LOG_SHORT(LINFO, ("Simplificator level for country polygons:", simplifyCountriesLevel));
|
||||
}
|
||||
|
||||
countries.clear();
|
||||
ifstream stream((baseDir + POLYGONS_FILE).c_str());
|
||||
std::string line;
|
||||
|
@ -197,7 +229,7 @@ namespace kml
|
|||
if (line.empty())
|
||||
continue;
|
||||
CountryPolygons country;
|
||||
PolygonLoader loader(baseDir, country);
|
||||
PolygonLoader loader(baseDir, country, simplifyCountriesLevel);
|
||||
utils::TokenizeString(line, ",", loader);
|
||||
if (!country.m_regions.empty())
|
||||
countries.push_back(country);
|
||||
|
|
|
@ -21,5 +21,7 @@ namespace kml
|
|||
|
||||
typedef vector<CountryPolygons> CountriesContainerT;
|
||||
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries);
|
||||
/// @param[in] simplifyCountriesLevel if positive, used as a level for simplificator
|
||||
bool LoadCountriesList(string const & baseDir, CountriesContainerT & countries,
|
||||
int simplifyCountriesLevel = -1);
|
||||
}
|
||||
|
|
|
@ -23,14 +23,15 @@ namespace feature
|
|||
class Polygonizer
|
||||
{
|
||||
public:
|
||||
Polygonizer(string const & dir, typename FeatureOutT::InitDataType const & featureOutInitData)
|
||||
Polygonizer(string const & dir, typename FeatureOutT::InitDataType const & featureOutInitData,
|
||||
int simplifyCountriesLevel)
|
||||
: m_FeatureOutInitData(featureOutInitData)
|
||||
{
|
||||
CHECK(kml::LoadCountriesList(dir, m_countries), ("Error loading polygons"));
|
||||
LOG(LINFO, ("Loaded polygons count for regions:"));
|
||||
CHECK(kml::LoadCountriesList(dir, m_countries, simplifyCountriesLevel), ("Error loading polygons"));
|
||||
LOG_SHORT(LINFO, ("Loaded polygons count for regions:"));
|
||||
for (size_t i = 0; i < m_countries.size(); ++i)
|
||||
{
|
||||
LOG(LINFO, (m_countries[i].m_name, m_countries[i].m_regions.size()));
|
||||
LOG_SHORT(LINFO, (m_countries[i].m_name, m_countries[i].m_regions.size()));
|
||||
}
|
||||
|
||||
m_Buckets.resize(m_countries.size());
|
||||
|
|
Loading…
Add table
Reference in a new issue