forked from organicmaps/organicmaps-tmp
Merge pull request #6 from kshalnev/mapcss_dynamic_selector
[styles] Mapcss dynamic selector
This commit is contained in:
commit
beeb153267
21 changed files with 978 additions and 370 deletions
|
@ -8,6 +8,15 @@
|
|||
#include "std/algorithm.hpp"
|
||||
#include "std/iterator.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct less_scales
|
||||
{
|
||||
bool operator() (drule::Key const & l, int r) const { return l.m_scale < r; }
|
||||
bool operator() (int l, drule::Key const & r) const { return l < r.m_scale; }
|
||||
bool operator() (drule::Key const & l, drule::Key const & r) const { return l.m_scale < r.m_scale; }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ClassifObject implementation
|
||||
|
@ -38,10 +47,11 @@ ClassifObject * ClassifObject::Find(string const & s)
|
|||
|
||||
void ClassifObject::AddDrawRule(drule::Key const & k)
|
||||
{
|
||||
for (size_t i = 0; i < m_drawRule.size(); ++i)
|
||||
if (k == m_drawRule[i]) return;
|
||||
|
||||
m_drawRule.push_back(k);
|
||||
auto i = lower_bound(m_drawRule.begin(), m_drawRule.end(), k.m_scale, less_scales());
|
||||
for (; i != m_drawRule.end() && i->m_scale == k.m_scale; ++i)
|
||||
if (k == *i)
|
||||
return; // already exists
|
||||
m_drawRule.insert(i, k);
|
||||
}
|
||||
|
||||
ClassifObjectPtr ClassifObject::BinaryFind(string const & s) const
|
||||
|
@ -61,16 +71,6 @@ void ClassifObject::LoadPolicy::Start(size_t i)
|
|||
base_type::Start(i);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct less_scales
|
||||
{
|
||||
bool operator() (drule::Key const & l, int r) const { return l.m_scale < r; }
|
||||
bool operator() (int l, drule::Key const & r) const { return l < r.m_scale; }
|
||||
bool operator() (drule::Key const & l, drule::Key const & r) const { return l.m_scale < r.m_scale; }
|
||||
};
|
||||
}
|
||||
|
||||
void ClassifObject::LoadPolicy::EndChilds()
|
||||
{
|
||||
ClassifObject * p = Current();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "indexer/drawing_rules.hpp"
|
||||
#include "indexer/scales.hpp"
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/drules_include.hpp"
|
||||
#include "indexer/map_style_reader.hpp"
|
||||
#include "indexer/scales.hpp"
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
|
@ -89,6 +89,18 @@ ShieldRuleProto const * BaseRule::GetShield() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool BaseRule::TestFeature(FeatureType const & ft, int /* zoom */) const
|
||||
{
|
||||
if (nullptr == m_selector)
|
||||
return true;
|
||||
return m_selector->Test(ft);
|
||||
}
|
||||
|
||||
void BaseRule::SetSelector(unique_ptr<ISelector> && selector)
|
||||
{
|
||||
m_selector = move(selector);
|
||||
}
|
||||
|
||||
RulesHolder::RulesHolder()
|
||||
: m_bgColors(scales::UPPER_STYLE_SCALE+1, DEFAULT_BG_COLOR)
|
||||
, m_cityRankTable(GetConstRankCityRankTable())
|
||||
|
@ -330,14 +342,36 @@ namespace
|
|||
RulesHolder & m_holder;
|
||||
|
||||
template <class TRule, class TProtoRule>
|
||||
void AddRule(ClassifObject * p, int scale, rule_type_t type, TProtoRule const & rule)
|
||||
void AddRule(ClassifObject * p, int scale, rule_type_t type, TProtoRule const & rule,
|
||||
vector<string> const & apply_if)
|
||||
{
|
||||
Key k = m_holder.AddRule(scale, type, new TRule(rule));
|
||||
unique_ptr<ISelector> selector;
|
||||
if (!apply_if.empty())
|
||||
{
|
||||
selector = ParseSelector(apply_if);
|
||||
if (selector == nullptr)
|
||||
{
|
||||
LOG(LERROR, ("Runtime selector has not been created:", apply_if));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BaseRule * obj = new TRule(rule);
|
||||
obj->SetSelector(move(selector));
|
||||
Key k = m_holder.AddRule(scale, type, obj);
|
||||
p->SetVisibilityOnScale(true, scale);
|
||||
k.SetPriority(rule.priority());
|
||||
p->AddDrawRule(k);
|
||||
}
|
||||
|
||||
static void DrawElementGetApplyIf(DrawElementProto const & de, vector<string> & apply_if)
|
||||
{
|
||||
apply_if.clear();
|
||||
apply_if.reserve(de.apply_if_size());
|
||||
for (int i = 0; i < de.apply_if_size(); ++i)
|
||||
apply_if.emplace_back(de.apply_if(i));
|
||||
}
|
||||
|
||||
public:
|
||||
DoSetIndex(RulesHolder & holder)
|
||||
: m_holder(holder) {}
|
||||
|
@ -349,6 +383,8 @@ namespace
|
|||
int const i = FindIndex();
|
||||
if (i != -1)
|
||||
{
|
||||
vector<string> apply_if;
|
||||
|
||||
ClassifElementProto const & ce = m_cont.cont(i);
|
||||
for (int j = 0; j < ce.element_size(); ++j)
|
||||
{
|
||||
|
@ -356,26 +392,28 @@ namespace
|
|||
|
||||
using namespace proto_rules;
|
||||
|
||||
DrawElementGetApplyIf(de, apply_if);
|
||||
|
||||
for (int k = 0; k < de.lines_size(); ++k)
|
||||
AddRule<Line>(p, de.scale(), line, de.lines(k));
|
||||
AddRule<Line>(p, de.scale(), line, de.lines(k), apply_if);
|
||||
|
||||
if (de.has_area())
|
||||
AddRule<Area>(p, de.scale(), area, de.area());
|
||||
AddRule<Area>(p, de.scale(), area, de.area(), apply_if);
|
||||
|
||||
if (de.has_symbol())
|
||||
AddRule<Symbol>(p, de.scale(), symbol, de.symbol());
|
||||
AddRule<Symbol>(p, de.scale(), symbol, de.symbol(), apply_if);
|
||||
|
||||
if (de.has_caption())
|
||||
AddRule<Caption>(p, de.scale(), caption, de.caption());
|
||||
AddRule<Caption>(p, de.scale(), caption, de.caption(), apply_if);
|
||||
|
||||
if (de.has_circle())
|
||||
AddRule<Circle>(p, de.scale(), circle, de.circle());
|
||||
AddRule<Circle>(p, de.scale(), circle, de.circle(), apply_if);
|
||||
|
||||
if (de.has_path_text())
|
||||
AddRule<PathText>(p, de.scale(), pathtext, de.path_text());
|
||||
AddRule<PathText>(p, de.scale(), pathtext, de.path_text(), apply_if);
|
||||
|
||||
if (de.has_shield())
|
||||
AddRule<Shield>(p, de.scale(), shield, de.shield());
|
||||
AddRule<Shield>(p, de.scale(), shield, de.shield(), apply_if);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "indexer/drawing_rule_def.hpp"
|
||||
#include "indexer/drules_city_rank_table.hpp"
|
||||
#include "indexer/drules_selector.hpp"
|
||||
|
||||
#include "base/base.hpp"
|
||||
#include "base/buffer_vector.hpp"
|
||||
|
@ -21,6 +22,7 @@ class CaptionDefProto;
|
|||
class CircleRuleProto;
|
||||
class ShieldRuleProto;
|
||||
class ContainerProto;
|
||||
class FeatureType;
|
||||
|
||||
|
||||
namespace drule
|
||||
|
@ -30,6 +32,8 @@ namespace drule
|
|||
mutable buffer_vector<uint32_t, 4> m_id1;
|
||||
char m_type; // obsolete for new styles, can be removed
|
||||
|
||||
unique_ptr<ISelector> m_selector;
|
||||
|
||||
public:
|
||||
static uint32_t const empty_id = 0xFFFFFFFF;
|
||||
|
||||
|
@ -53,6 +57,13 @@ namespace drule
|
|||
virtual CaptionDefProto const * GetCaption(int) const;
|
||||
virtual CircleRuleProto const * GetCircle() const;
|
||||
virtual ShieldRuleProto const * GetShield() const;
|
||||
|
||||
// Test feature by runtime feature style selector
|
||||
// Returns true if rule is applicable for feature, otherwise it returns false
|
||||
bool TestFeature(FeatureType const & ft, int zoom) const;
|
||||
|
||||
// Set runtime feature style selector
|
||||
void SetSelector(unique_ptr<ISelector> && selector);
|
||||
};
|
||||
|
||||
class RulesHolder
|
||||
|
|
157
indexer/drules_selector.cpp
Normal file
157
indexer/drules_selector.cpp
Normal file
|
@ -0,0 +1,157 @@
|
|||
#include "indexer/drules_selector.hpp"
|
||||
#include "indexer/drules_selector_parser.hpp"
|
||||
#include "indexer/ftypes_matcher.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/logging.hpp"
|
||||
|
||||
namespace drule
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class CompositeSelector : public ISelector
|
||||
{
|
||||
public:
|
||||
explicit CompositeSelector(size_t capacity)
|
||||
{
|
||||
m_selectors.reserve(capacity);
|
||||
}
|
||||
|
||||
void Add(unique_ptr<ISelector> && selector)
|
||||
{
|
||||
m_selectors.emplace_back(move(selector));
|
||||
}
|
||||
|
||||
// ISelector overrides:
|
||||
bool Test(FeatureType const & ft) const override
|
||||
{
|
||||
for (auto const & selector : m_selectors)
|
||||
if (!selector->Test(ft))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
vector<unique_ptr<ISelector>> m_selectors;
|
||||
};
|
||||
|
||||
// Runtime feature style selector implementation
|
||||
template <typename TType>
|
||||
class Selector : public ISelector
|
||||
{
|
||||
public:
|
||||
// Signature of function which takes a property from a feature
|
||||
typedef bool (*TGetFeatureTagValueFn)(FeatureType const &, TType & value);
|
||||
|
||||
Selector(TGetFeatureTagValueFn fn, SelectorOperatorType op, TType const & value)
|
||||
: m_getFeatureValueFn(fn), m_evalFn(nullptr), m_value(value)
|
||||
{
|
||||
ASSERT(fn != nullptr, ());
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case SelectorOperatorUnknown: m_evalFn = nullptr; break;
|
||||
case SelectorOperatorNotEqual: m_evalFn = &Selector<TType>::NotEqual; break;
|
||||
case SelectorOperatorLessOrEqual: m_evalFn = &Selector<TType>::LessOrEqual; break;
|
||||
case SelectorOperatorGreaterOrEqual: m_evalFn = &Selector<TType>::GreaterOrEqual; break;
|
||||
case SelectorOperatorEqual: m_evalFn = &Selector<TType>::Equal; break;
|
||||
case SelectorOperatorLess: m_evalFn = &Selector<TType>::Less; break;
|
||||
case SelectorOperatorGreater: m_evalFn = &Selector<TType>::Greater; break;
|
||||
case SelectorOperatorIsNotSet: m_evalFn = &Selector<TType>::IsNotSet; break;
|
||||
case SelectorOperatorIsSet: m_evalFn = &Selector<TType>::IsSet; break;
|
||||
}
|
||||
|
||||
ASSERT(m_evalFn != nullptr, ("Unknown or unexpected selector operator type"));
|
||||
if (nullptr == m_evalFn)
|
||||
m_evalFn = &Selector<TType>::Unknown;
|
||||
}
|
||||
|
||||
// ISelector overrides:
|
||||
bool Test(FeatureType const & ft) const override
|
||||
{
|
||||
TType tagValue;
|
||||
if (!m_getFeatureValueFn(ft, tagValue))
|
||||
return false;
|
||||
return (this->*m_evalFn)(tagValue);
|
||||
}
|
||||
|
||||
private:
|
||||
bool Unknown(TType const &) const { return false; }
|
||||
bool NotEqual(TType const & tagValue) const { return tagValue != m_value; }
|
||||
bool LessOrEqual(TType const & tagValue) const { return tagValue <= m_value; }
|
||||
bool GreaterOrEqual(TType const & tagValue) const { return tagValue >= m_value; }
|
||||
bool Equal(TType const & tagValue) const { return tagValue == m_value; }
|
||||
bool Less(TType const & tagValue) const { return tagValue < m_value; }
|
||||
bool Greater(TType const & tagValue) const { return tagValue > m_value; }
|
||||
bool IsNotSet(TType const & tagValue) const { return tagValue == TType(); }
|
||||
bool IsSet(TType const & tagValue) const { return tagValue != TType(); }
|
||||
|
||||
typedef bool (Selector<TType>::*TOperationFn)(TType const &) const;
|
||||
|
||||
TGetFeatureTagValueFn m_getFeatureValueFn;
|
||||
TOperationFn m_evalFn;
|
||||
TType const m_value;
|
||||
};
|
||||
|
||||
// Feature tag value evaluator for tag 'population'
|
||||
bool GetPopulation(FeatureType const & ft, uint32_t & population)
|
||||
{
|
||||
population = ftypes::GetPopulation(ft);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add new tag value evaluator here
|
||||
|
||||
} // namespace
|
||||
|
||||
unique_ptr<ISelector> ParseSelector(string const & str)
|
||||
{
|
||||
SelectorExpression e;
|
||||
if (!ParseSelector(str, e))
|
||||
{
|
||||
// bad string format
|
||||
LOG(LDEBUG, ("Invalid selector format: ", str));
|
||||
return unique_ptr<ISelector>();
|
||||
}
|
||||
|
||||
// Tag 'population'
|
||||
if (e.m_tag == "population")
|
||||
{
|
||||
int value = 0;
|
||||
if (!e.m_value.empty() && (!strings::to_int(e.m_value, value) || value < 0))
|
||||
{
|
||||
// bad string format
|
||||
LOG(LDEBUG, ("Invalid selector: ", str));
|
||||
return unique_ptr<ISelector>();
|
||||
}
|
||||
return make_unique<Selector<uint32_t>>(&GetPopulation, e.m_operator, static_cast<uint32_t>(value));
|
||||
}
|
||||
|
||||
// Add new tag here
|
||||
|
||||
// unrecognized selector
|
||||
LOG(LDEBUG, ("Unrecognized selector: ", str));
|
||||
return unique_ptr<ISelector>();
|
||||
}
|
||||
|
||||
unique_ptr<ISelector> ParseSelector(vector<string> const & strs)
|
||||
{
|
||||
unique_ptr<CompositeSelector> cs = make_unique<CompositeSelector>(strs.size());
|
||||
|
||||
for (string const & str : strs)
|
||||
{
|
||||
unique_ptr<ISelector> s = ParseSelector(str);
|
||||
if (nullptr == s)
|
||||
{
|
||||
LOG(LDEBUG, ("Invalid composite selector: ", str));
|
||||
return unique_ptr<ISelector>();
|
||||
}
|
||||
cs->Add(move(s));
|
||||
}
|
||||
|
||||
return unique_ptr<ISelector>(cs.release());
|
||||
}
|
||||
|
||||
} // namespace drule
|
29
indexer/drules_selector.hpp
Normal file
29
indexer/drules_selector.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "indexer/feature.hpp"
|
||||
|
||||
#include "std/string.hpp"
|
||||
#include "std/unique_ptr.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace drule
|
||||
{
|
||||
|
||||
// Runtime feature style selector absract interface.
|
||||
class ISelector
|
||||
{
|
||||
public:
|
||||
virtual ~ISelector() = default;
|
||||
|
||||
// If ISelector.Test returns true then style is applicable for the feature,
|
||||
// otherwise, if ISelector.Test returns false, style cannot be applied to the feature.
|
||||
virtual bool Test(FeatureType const & ft) const = 0;
|
||||
};
|
||||
|
||||
// Factory method which builds ISelector from a string.
|
||||
unique_ptr<ISelector> ParseSelector(string const & str);
|
||||
|
||||
// Factory method which builds composite ISelector from a set of string.
|
||||
unique_ptr<ISelector> ParseSelector(vector<string> const & strs);
|
||||
|
||||
} // namespace drule
|
124
indexer/drules_selector_parser.cpp
Normal file
124
indexer/drules_selector_parser.cpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include "indexer/drules_selector_parser.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include "std/algorithm.hpp"
|
||||
|
||||
namespace drule
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool IsTag(string const & str)
|
||||
{
|
||||
// tag consists of a-z or A-Z letters and not empty
|
||||
for (auto const c : str)
|
||||
{
|
||||
if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z'))
|
||||
return false;
|
||||
}
|
||||
return !str.empty();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ParseSelector(string const & str, SelectorExpression & e)
|
||||
{
|
||||
// See http://wiki.openstreetmap.org/wiki/MapCSS/0.2
|
||||
// Now we support following expressions
|
||||
// [tag!=value]
|
||||
// [tag>=value]
|
||||
// [tag<=value]
|
||||
// [tag=value]
|
||||
// [tag>value]
|
||||
// [tag<value]
|
||||
// [!tag]
|
||||
// [tag]
|
||||
|
||||
if (str.empty())
|
||||
return false; // invalid format
|
||||
|
||||
// [!tag]
|
||||
if (str[0] == '!')
|
||||
{
|
||||
string tag(str.begin() + 1, str.end());
|
||||
if (!IsTag(tag))
|
||||
return false; // invalid format
|
||||
|
||||
e.m_operator = SelectorOperatorIsNotSet;
|
||||
e.m_tag = move(tag);
|
||||
e.m_value.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// [tag]
|
||||
if (IsTag(str))
|
||||
{
|
||||
e.m_operator = SelectorOperatorIsSet;
|
||||
e.m_tag = str;
|
||||
e.m_value.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find first entrance of >, < or =
|
||||
size_t pos = string::npos;
|
||||
size_t len = 0;
|
||||
char const c[] = { '>', '<', '=', 0 };
|
||||
for (size_t i = 0; c[i] != 0; ++i)
|
||||
{
|
||||
size_t p = str.find(c[i]);
|
||||
if (p != string::npos)
|
||||
{
|
||||
pos = (pos == string::npos) ? p : min(p, pos);
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no entrance or no space for tag or value then it is invalid format
|
||||
if (pos == 0 || len == 0 || pos == str.size()-1)
|
||||
return false; // invalid format
|
||||
|
||||
// Dedicate the operator type, real operator position and length
|
||||
SelectorOperatorType op = SelectorOperatorUnknown;
|
||||
if (str[pos] == '>')
|
||||
{
|
||||
op = SelectorOperatorGreater;
|
||||
if (str[pos+1] == '=')
|
||||
{
|
||||
++len;
|
||||
op = SelectorOperatorGreaterOrEqual;
|
||||
}
|
||||
}
|
||||
else if (str[pos] == '<')
|
||||
{
|
||||
op = SelectorOperatorLess;
|
||||
if (str[pos+1] == '=')
|
||||
{
|
||||
++len;
|
||||
op = SelectorOperatorLessOrEqual;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(str[pos] == '=', ());
|
||||
op = SelectorOperatorEqual;
|
||||
if (str[pos-1] == '!')
|
||||
{
|
||||
--pos;
|
||||
++len;
|
||||
op = SelectorOperatorNotEqual;
|
||||
}
|
||||
}
|
||||
|
||||
string tag(str.begin(), str.begin() + pos);
|
||||
if (!IsTag(tag))
|
||||
return false; // invalid format
|
||||
|
||||
e.m_operator = op;
|
||||
e.m_tag = move(tag);
|
||||
e.m_value = string(str.begin() + pos + len, str.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace drule
|
48
indexer/drules_selector_parser.hpp
Normal file
48
indexer/drules_selector_parser.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include "std/string.hpp"
|
||||
|
||||
namespace drule
|
||||
{
|
||||
|
||||
enum SelectorOperatorType
|
||||
{
|
||||
SelectorOperatorUnknown = 0,
|
||||
|
||||
// [tag!=value]
|
||||
SelectorOperatorNotEqual,
|
||||
|
||||
// [tag<=value]
|
||||
SelectorOperatorLessOrEqual,
|
||||
|
||||
// [tag>=value]
|
||||
SelectorOperatorGreaterOrEqual,
|
||||
|
||||
// [tag=value]
|
||||
SelectorOperatorEqual,
|
||||
|
||||
// [tag<value]
|
||||
SelectorOperatorLess,
|
||||
|
||||
// [tag>value]
|
||||
SelectorOperatorGreater,
|
||||
|
||||
// [!tag]
|
||||
SelectorOperatorIsNotSet,
|
||||
|
||||
// [tag]
|
||||
SelectorOperatorIsSet,
|
||||
};
|
||||
|
||||
struct SelectorExpression
|
||||
{
|
||||
SelectorOperatorType m_operator;
|
||||
string m_tag;
|
||||
string m_value;
|
||||
|
||||
SelectorExpression() : m_operator(SelectorOperatorUnknown) {}
|
||||
};
|
||||
|
||||
bool ParseSelector(string const & str, SelectorExpression & e);
|
||||
|
||||
} // namespace drule
|
|
@ -3569,6 +3569,7 @@ const int DrawElementProto::kCaptionFieldNumber;
|
|||
const int DrawElementProto::kCircleFieldNumber;
|
||||
const int DrawElementProto::kPathTextFieldNumber;
|
||||
const int DrawElementProto::kShieldFieldNumber;
|
||||
const int DrawElementProto::kApplyIfFieldNumber;
|
||||
#endif // !_MSC_VER
|
||||
|
||||
DrawElementProto::DrawElementProto()
|
||||
|
@ -3624,6 +3625,7 @@ DrawElementProto::DrawElementProto(const DrawElementProto& from)
|
|||
}
|
||||
|
||||
void DrawElementProto::SharedCtor() {
|
||||
::google::protobuf::internal::GetEmptyString();
|
||||
_cached_size_ = 0;
|
||||
scale_ = 0;
|
||||
area_ = NULL;
|
||||
|
@ -3698,6 +3700,7 @@ void DrawElementProto::Clear() {
|
|||
}
|
||||
}
|
||||
lines_.Clear();
|
||||
apply_if_.Clear();
|
||||
::memset(_has_bits_, 0, sizeof(_has_bits_));
|
||||
mutable_unknown_fields()->clear();
|
||||
}
|
||||
|
@ -3818,6 +3821,20 @@ bool DrawElementProto::MergePartialFromCodedStream(
|
|||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectTag(74)) goto parse_apply_if;
|
||||
break;
|
||||
}
|
||||
|
||||
// repeated string apply_if = 9;
|
||||
case 9: {
|
||||
if (tag == 74) {
|
||||
parse_apply_if:
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
|
||||
input, this->add_apply_if()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
if (input->ExpectTag(74)) goto parse_apply_if;
|
||||
if (input->ExpectAtEnd()) goto success;
|
||||
break;
|
||||
}
|
||||
|
@ -3894,6 +3911,12 @@ void DrawElementProto::SerializeWithCachedSizes(
|
|||
8, this->shield(), output);
|
||||
}
|
||||
|
||||
// repeated string apply_if = 9;
|
||||
for (int i = 0; i < this->apply_if_size(); i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteString(
|
||||
9, this->apply_if(i), output);
|
||||
}
|
||||
|
||||
output->WriteRaw(unknown_fields().data(),
|
||||
unknown_fields().size());
|
||||
// @@protoc_insertion_point(serialize_end:DrawElementProto)
|
||||
|
@ -3961,6 +3984,13 @@ int DrawElementProto::ByteSize() const {
|
|||
this->lines(i));
|
||||
}
|
||||
|
||||
// repeated string apply_if = 9;
|
||||
total_size += 1 * this->apply_if_size();
|
||||
for (int i = 0; i < this->apply_if_size(); i++) {
|
||||
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
|
||||
this->apply_if(i));
|
||||
}
|
||||
|
||||
total_size += unknown_fields().size();
|
||||
|
||||
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
|
||||
|
@ -3977,6 +4007,7 @@ void DrawElementProto::CheckTypeAndMergeFrom(
|
|||
void DrawElementProto::MergeFrom(const DrawElementProto& from) {
|
||||
GOOGLE_CHECK_NE(&from, this);
|
||||
lines_.MergeFrom(from.lines_);
|
||||
apply_if_.MergeFrom(from.apply_if_);
|
||||
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
|
||||
if (from.has_scale()) {
|
||||
set_scale(from.scale());
|
||||
|
@ -4044,6 +4075,7 @@ void DrawElementProto::Swap(DrawElementProto* other) {
|
|||
std::swap(circle_, other->circle_);
|
||||
std::swap(path_text_, other->path_text_);
|
||||
std::swap(shield_, other->shield_);
|
||||
apply_if_.Swap(&other->apply_if_);
|
||||
std::swap(_has_bits_[0], other->_has_bits_[0]);
|
||||
_unknown_fields_.swap(other->_unknown_fields_);
|
||||
std::swap(_cached_size_, other->_cached_size_);
|
||||
|
|
|
@ -1555,6 +1555,22 @@ class DrawElementProto : public ::google::protobuf::MessageLite {
|
|||
inline ::ShieldRuleProto* release_shield();
|
||||
inline void set_allocated_shield(::ShieldRuleProto* shield);
|
||||
|
||||
// repeated string apply_if = 9;
|
||||
inline int apply_if_size() const;
|
||||
inline void clear_apply_if();
|
||||
static const int kApplyIfFieldNumber = 9;
|
||||
inline const ::std::string& apply_if(int index) const;
|
||||
inline ::std::string* mutable_apply_if(int index);
|
||||
inline void set_apply_if(int index, const ::std::string& value);
|
||||
inline void set_apply_if(int index, const char* value);
|
||||
inline void set_apply_if(int index, const char* value, size_t size);
|
||||
inline ::std::string* add_apply_if();
|
||||
inline void add_apply_if(const ::std::string& value);
|
||||
inline void add_apply_if(const char* value);
|
||||
inline void add_apply_if(const char* value, size_t size);
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& apply_if() const;
|
||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_apply_if();
|
||||
|
||||
// @@protoc_insertion_point(class_scope:DrawElementProto)
|
||||
private:
|
||||
inline void set_has_scale();
|
||||
|
@ -1583,6 +1599,7 @@ class DrawElementProto : public ::google::protobuf::MessageLite {
|
|||
::CircleRuleProto* circle_;
|
||||
::PathTextRuleProto* path_text_;
|
||||
::ShieldRuleProto* shield_;
|
||||
::google::protobuf::RepeatedPtrField< ::std::string> apply_if_;
|
||||
::google::protobuf::int32 scale_;
|
||||
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
|
||||
friend void protobuf_AddDesc_drules_5fstruct_2eproto_impl();
|
||||
|
@ -3529,6 +3546,60 @@ inline void DrawElementProto::set_allocated_shield(::ShieldRuleProto* shield) {
|
|||
// @@protoc_insertion_point(field_set_allocated:DrawElementProto.shield)
|
||||
}
|
||||
|
||||
// repeated string apply_if = 9;
|
||||
inline int DrawElementProto::apply_if_size() const {
|
||||
return apply_if_.size();
|
||||
}
|
||||
inline void DrawElementProto::clear_apply_if() {
|
||||
apply_if_.Clear();
|
||||
}
|
||||
inline const ::std::string& DrawElementProto::apply_if(int index) const {
|
||||
// @@protoc_insertion_point(field_get:DrawElementProto.apply_if)
|
||||
return apply_if_.Get(index);
|
||||
}
|
||||
inline ::std::string* DrawElementProto::mutable_apply_if(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:DrawElementProto.apply_if)
|
||||
return apply_if_.Mutable(index);
|
||||
}
|
||||
inline void DrawElementProto::set_apply_if(int index, const ::std::string& value) {
|
||||
// @@protoc_insertion_point(field_set:DrawElementProto.apply_if)
|
||||
apply_if_.Mutable(index)->assign(value);
|
||||
}
|
||||
inline void DrawElementProto::set_apply_if(int index, const char* value) {
|
||||
apply_if_.Mutable(index)->assign(value);
|
||||
// @@protoc_insertion_point(field_set_char:DrawElementProto.apply_if)
|
||||
}
|
||||
inline void DrawElementProto::set_apply_if(int index, const char* value, size_t size) {
|
||||
apply_if_.Mutable(index)->assign(
|
||||
reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_set_pointer:DrawElementProto.apply_if)
|
||||
}
|
||||
inline ::std::string* DrawElementProto::add_apply_if() {
|
||||
return apply_if_.Add();
|
||||
}
|
||||
inline void DrawElementProto::add_apply_if(const ::std::string& value) {
|
||||
apply_if_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add:DrawElementProto.apply_if)
|
||||
}
|
||||
inline void DrawElementProto::add_apply_if(const char* value) {
|
||||
apply_if_.Add()->assign(value);
|
||||
// @@protoc_insertion_point(field_add_char:DrawElementProto.apply_if)
|
||||
}
|
||||
inline void DrawElementProto::add_apply_if(const char* value, size_t size) {
|
||||
apply_if_.Add()->assign(reinterpret_cast<const char*>(value), size);
|
||||
// @@protoc_insertion_point(field_add_pointer:DrawElementProto.apply_if)
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
|
||||
DrawElementProto::apply_if() const {
|
||||
// @@protoc_insertion_point(field_list:DrawElementProto.apply_if)
|
||||
return apply_if_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::std::string>*
|
||||
DrawElementProto::mutable_apply_if() {
|
||||
// @@protoc_insertion_point(field_mutable_list:DrawElementProto.apply_if)
|
||||
return &apply_if_;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// ClassifElementProto
|
||||
|
|
|
@ -111,6 +111,7 @@ message DrawElementProto
|
|||
optional CircleRuleProto circle = 6;
|
||||
optional PathTextRuleProto path_text = 7;
|
||||
optional ShieldRuleProto shield = 8;
|
||||
repeated string apply_if = 9;
|
||||
}
|
||||
|
||||
message ClassifElementProto
|
||||
|
|
|
@ -19,6 +19,8 @@ SOURCES += \
|
|||
drawing_rule_def.cpp \
|
||||
drawing_rules.cpp \
|
||||
drules_city_rank_table.cpp \
|
||||
drules_selector.cpp \
|
||||
drules_selector_parser.cpp \
|
||||
feature.cpp \
|
||||
feature_algo.cpp \
|
||||
feature_covering.cpp \
|
||||
|
@ -60,6 +62,8 @@ HEADERS += \
|
|||
drawing_rules.hpp \
|
||||
drules_city_rank_table.hpp \
|
||||
drules_include.hpp \
|
||||
drules_selector.cpp \
|
||||
drules_selector_parser.cpp \
|
||||
feature.hpp \
|
||||
feature_algo.hpp \
|
||||
feature_covering.hpp \
|
||||
|
|
147
indexer/indexer_tests/drules_selector_parser_test.cpp
Normal file
147
indexer/indexer_tests/drules_selector_parser_test.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/drules_selector.hpp"
|
||||
#include "indexer/drules_selector_parser.hpp"
|
||||
|
||||
using namespace drule;
|
||||
|
||||
UNIT_TEST(TestDruleSelectorIsSet)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("name", e), ());
|
||||
|
||||
TEST_EQUAL("name", e.m_tag, ());
|
||||
TEST_EQUAL("", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorIsSet, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorIsNotSet)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("!name", e), ());
|
||||
|
||||
TEST_EQUAL("name", e.m_tag, ());
|
||||
TEST_EQUAL("", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorIsNotSet, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorNotEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population!=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorNotEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorLess)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population<1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorLess, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorGreater)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population>1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorGreater, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorLessOrEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population<=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorLessOrEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorGreaterOrEqual)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST(ParseSelector("population>=1000", e), ());
|
||||
|
||||
TEST_EQUAL("population", e.m_tag, ());
|
||||
TEST_EQUAL("1000", e.m_value, ());
|
||||
TEST_EQUAL(SelectorOperatorGreaterOrEqual, e.m_operator, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleSelectorInvalid)
|
||||
{
|
||||
char const * const badFormats[] =
|
||||
{
|
||||
"",
|
||||
"=badformat",
|
||||
"!=badformat",
|
||||
">badformat",
|
||||
"<badformat",
|
||||
">=badformat",
|
||||
"<=badformat",
|
||||
"bad$name",
|
||||
"!bad$name",
|
||||
"bad$name=1000",
|
||||
};
|
||||
size_t const n = sizeof(badFormats) / sizeof(badFormats[0]);
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
SelectorExpression e;
|
||||
TEST_EQUAL(false, ParseSelector(badFormats[i], e), ("string is", badFormats[i]));
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleParseSelectorValid1)
|
||||
{
|
||||
auto selector = ParseSelector("population<1000");
|
||||
TEST(selector != nullptr, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleParseSelectorValid2)
|
||||
{
|
||||
auto selector = ParseSelector(vector<string>({"population>1000"}));
|
||||
TEST(selector != nullptr, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleParseSelectorValid3)
|
||||
{
|
||||
auto selector = ParseSelector(vector<string>({"population>=1000","population<=1000000"}));
|
||||
TEST(selector != nullptr, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleParseSelectorInvalid1)
|
||||
{
|
||||
auto selector = ParseSelector("");
|
||||
TEST(selector == nullptr, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleParseSelectorInvalid2)
|
||||
{
|
||||
auto selector = ParseSelector(vector<string>({""}));
|
||||
TEST(selector == nullptr, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestDruleParseSelectorInvalid3)
|
||||
{
|
||||
auto selector = ParseSelector(vector<string>({"population>=1000","population<=1000000", ""}));
|
||||
TEST(selector == nullptr, ());
|
||||
}
|
|
@ -28,6 +28,7 @@ SOURCES += \
|
|||
cell_id_test.cpp \
|
||||
checker_test.cpp \
|
||||
city_rank_table_test.cpp \
|
||||
drules_selector_parser_test.cpp \
|
||||
features_offsets_table_test.cpp \
|
||||
geometry_coding_test.cpp \
|
||||
geometry_serialization_test.cpp \
|
||||
|
|
|
@ -30,6 +30,16 @@ namespace
|
|||
return (r1.m_depth < r2.m_depth);
|
||||
}
|
||||
};
|
||||
|
||||
void FilterRulesByRuntimeSelector(FeatureType const & ft, int zoom, drule::KeysT & keys)
|
||||
{
|
||||
keys.erase_if([&ft, zoom](drule::Key const & key)->bool
|
||||
{
|
||||
drule::BaseRule const * const rule = drule::rules().Find(key);
|
||||
ASSERT(rule != nullptr, ());
|
||||
return !rule->TestFeature(ft, zoom);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace di
|
||||
|
@ -64,6 +74,8 @@ namespace di
|
|||
drule::KeysT keys;
|
||||
pair<int, bool> type = feature::GetDrawRule(f, zoom, keys);
|
||||
|
||||
FilterRulesByRuntimeSelector(f, zoom, keys);
|
||||
|
||||
// don't try to do anything to invisible feature
|
||||
if (keys.empty())
|
||||
return;
|
||||
|
|
|
@ -19,7 +19,7 @@ _sym_db = _symbol_database.Default()
|
|||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='drules_struct.proto',
|
||||
package='',
|
||||
serialized_pb=_b('\n\x13\x64rules_struct.proto\"*\n\x0c\x44\x61shDotProto\x12\n\n\x02\x64\x64\x18\x01 \x03(\x01\x12\x0e\n\x06offset\x18\x02 \x01(\x01\":\n\x0cPathSymProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04step\x18\x02 \x02(\x01\x12\x0e\n\x06offset\x18\x03 \x01(\x01\"\xaf\x01\n\rLineRuleProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\x12\x1e\n\x07pathsym\x18\x05 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"\x9c\x01\n\x0cLineDefProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x1e\n\x07pathsym\x18\x04 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"O\n\rAreaRuleProto\x12\r\n\x05\x63olor\x18\x01 \x02(\r\x12\x1d\n\x06\x62order\x18\x02 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"I\n\x0fSymbolRuleProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x16\n\x0e\x61pply_for_type\x18\x02 \x01(\x05\x12\x10\n\x08priority\x18\x03 \x02(\x05\"j\n\x0f\x43\x61ptionDefProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08offset_x\x18\x04 \x01(\x05\x12\x10\n\x08offset_y\x18\x05 \x01(\x05\"l\n\x10\x43\x61ptionRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"a\n\x0f\x43ircleRuleProto\x12\x0e\n\x06radius\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1d\n\x06\x62order\x18\x03 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\"m\n\x11PathTextRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"X\n\x0fShieldRuleProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08priority\x18\x04 \x02(\x05\"\x8f\x02\n\x10\x44rawElementProto\x12\r\n\x05scale\x18\x01 \x02(\x05\x12\x1d\n\x05lines\x18\x02 \x03(\x0b\x32\x0e.LineRuleProto\x12\x1c\n\x04\x61rea\x18\x03 \x01(\x0b\x32\x0e.AreaRuleProto\x12 \n\x06symbol\x18\x04 \x01(\x0b\x32\x10.SymbolRuleProto\x12\"\n\x07\x63\x61ption\x18\x05 \x01(\x0b\x32\x11.CaptionRuleProto\x12 \n\x06\x63ircle\x18\x06 \x01(\x0b\x32\x10.CircleRuleProto\x12%\n\tpath_text\x18\x07 \x01(\x0b\x32\x12.PathTextRuleProto\x12 \n\x06shield\x18\x08 \x01(\x0b\x32\x10.ShieldRuleProto\"G\n\x13\x43lassifElementProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\"\n\x07\x65lement\x18\x02 \x03(\x0b\x32\x11.DrawElementProto\"4\n\x0e\x43ontainerProto\x12\"\n\x04\x63ont\x18\x01 \x03(\x0b\x32\x14.ClassifElementProto*4\n\x08LineJoin\x12\r\n\tROUNDJOIN\x10\x00\x12\r\n\tBEVELJOIN\x10\x01\x12\n\n\x06NOJOIN\x10\x02*3\n\x07LineCap\x12\x0c\n\x08ROUNDCAP\x10\x00\x12\x0b\n\x07\x42UTTCAP\x10\x01\x12\r\n\tSQUARECAP\x10\x02\x42\x02H\x03')
|
||||
serialized_pb=_b('\n\x13\x64rules_struct.proto\"*\n\x0c\x44\x61shDotProto\x12\n\n\x02\x64\x64\x18\x01 \x03(\x01\x12\x0e\n\x06offset\x18\x02 \x01(\x01\":\n\x0cPathSymProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04step\x18\x02 \x02(\x01\x12\x0e\n\x06offset\x18\x03 \x01(\x01\"\xaf\x01\n\rLineRuleProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\x12\x1e\n\x07pathsym\x18\x05 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"\x9c\x01\n\x0cLineDefProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x1e\n\x07pathsym\x18\x04 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"O\n\rAreaRuleProto\x12\r\n\x05\x63olor\x18\x01 \x02(\r\x12\x1d\n\x06\x62order\x18\x02 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"I\n\x0fSymbolRuleProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x16\n\x0e\x61pply_for_type\x18\x02 \x01(\x05\x12\x10\n\x08priority\x18\x03 \x02(\x05\"j\n\x0f\x43\x61ptionDefProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08offset_x\x18\x04 \x01(\x05\x12\x10\n\x08offset_y\x18\x05 \x01(\x05\"l\n\x10\x43\x61ptionRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"a\n\x0f\x43ircleRuleProto\x12\x0e\n\x06radius\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1d\n\x06\x62order\x18\x03 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\"m\n\x11PathTextRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"X\n\x0fShieldRuleProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08priority\x18\x04 \x02(\x05\"\xa1\x02\n\x10\x44rawElementProto\x12\r\n\x05scale\x18\x01 \x02(\x05\x12\x1d\n\x05lines\x18\x02 \x03(\x0b\x32\x0e.LineRuleProto\x12\x1c\n\x04\x61rea\x18\x03 \x01(\x0b\x32\x0e.AreaRuleProto\x12 \n\x06symbol\x18\x04 \x01(\x0b\x32\x10.SymbolRuleProto\x12\"\n\x07\x63\x61ption\x18\x05 \x01(\x0b\x32\x11.CaptionRuleProto\x12 \n\x06\x63ircle\x18\x06 \x01(\x0b\x32\x10.CircleRuleProto\x12%\n\tpath_text\x18\x07 \x01(\x0b\x32\x12.PathTextRuleProto\x12 \n\x06shield\x18\x08 \x01(\x0b\x32\x10.ShieldRuleProto\x12\x10\n\x08\x61pply_if\x18\t \x03(\t\"G\n\x13\x43lassifElementProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\"\n\x07\x65lement\x18\x02 \x03(\x0b\x32\x11.DrawElementProto\"4\n\x0e\x43ontainerProto\x12\"\n\x04\x63ont\x18\x01 \x03(\x0b\x32\x14.ClassifElementProto*4\n\x08LineJoin\x12\r\n\tROUNDJOIN\x10\x00\x12\r\n\tBEVELJOIN\x10\x01\x12\n\n\x06NOJOIN\x10\x02*3\n\x07LineCap\x12\x0c\n\x08ROUNDCAP\x10\x00\x12\x0b\n\x07\x42UTTCAP\x10\x01\x12\r\n\tSQUARECAP\x10\x02\x42\x02H\x03')
|
||||
)
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
|
@ -44,8 +44,8 @@ _LINEJOIN = _descriptor.EnumDescriptor(
|
|||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=1539,
|
||||
serialized_end=1591,
|
||||
serialized_start=1557,
|
||||
serialized_end=1609,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_LINEJOIN)
|
||||
|
||||
|
@ -71,8 +71,8 @@ _LINECAP = _descriptor.EnumDescriptor(
|
|||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=1593,
|
||||
serialized_end=1644,
|
||||
serialized_start=1611,
|
||||
serialized_end=1662,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_LINECAP)
|
||||
|
||||
|
@ -703,6 +703,13 @@ _DRAWELEMENTPROTO = _descriptor.Descriptor(
|
|||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='apply_if', full_name='DrawElementProto.apply_if', index=8,
|
||||
number=9, type=9, cpp_type=9, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
|
@ -715,7 +722,7 @@ _DRAWELEMENTPROTO = _descriptor.Descriptor(
|
|||
oneofs=[
|
||||
],
|
||||
serialized_start=1139,
|
||||
serialized_end=1410,
|
||||
serialized_end=1428,
|
||||
)
|
||||
|
||||
|
||||
|
@ -751,8 +758,8 @@ _CLASSIFELEMENTPROTO = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1412,
|
||||
serialized_end=1483,
|
||||
serialized_start=1430,
|
||||
serialized_end=1501,
|
||||
)
|
||||
|
||||
|
||||
|
@ -781,8 +788,8 @@ _CONTAINERPROTO = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1485,
|
||||
serialized_end=1537,
|
||||
serialized_start=1503,
|
||||
serialized_end=1555,
|
||||
)
|
||||
|
||||
_LINERULEPROTO.fields_by_name['dashdot'].message_type = _DASHDOTPROTO
|
||||
|
|
|
@ -1,36 +1,48 @@
|
|||
from drules_struct_pb2 import *
|
||||
from timer import *
|
||||
from mapcss import MapCSS
|
||||
from optparse import OptionParser
|
||||
import os
|
||||
import csv
|
||||
import sys
|
||||
import json
|
||||
import mapcss.webcolors
|
||||
whatever_to_hex = mapcss.webcolors.webcolors.whatever_to_hex
|
||||
whatever_to_cairo = mapcss.webcolors.webcolors.whatever_to_cairo
|
||||
|
||||
|
||||
WIDTH_SCALE = 1.0
|
||||
|
||||
def komap_mapswithme(options, style, filename):
|
||||
if options.outfile == "-":
|
||||
print "Please specify base output path."
|
||||
exit()
|
||||
else:
|
||||
ddir = os.path.dirname(options.outfile)
|
||||
|
||||
types_file = open(os.path.join(ddir, 'types.txt'), "w")
|
||||
drules_bin = open(os.path.join(options.outfile + '.bin'), "wb")
|
||||
drules_txt = open(os.path.join(options.outfile + '.txt'), "wb")
|
||||
def mwm_encode_color(st, prefix='', default='black'):
|
||||
if prefix:
|
||||
prefix += "-"
|
||||
opacity = hex(255 - int(255 * float(st.get(prefix + "opacity", 1))))
|
||||
color = whatever_to_hex(st.get(prefix + 'color', default))
|
||||
color = color[1] + color[1] + color[3] + color[3] + color[5] + color[5]
|
||||
return int(opacity + color, 16)
|
||||
|
||||
def mwm_encode_image(st, prefix='icon', bgprefix='symbol'):
|
||||
if prefix:
|
||||
prefix += "-"
|
||||
if bgprefix:
|
||||
bgprefix += "-"
|
||||
if prefix + "image" not in st:
|
||||
return False
|
||||
# strip last ".svg"
|
||||
handle = st.get(prefix + "image")[:-4]
|
||||
return handle, handle
|
||||
|
||||
def komap_mapswithme(options):
|
||||
|
||||
ddir = os.path.dirname(options.outfile)
|
||||
|
||||
drules = ContainerProto()
|
||||
classificator = {}
|
||||
class_order = []
|
||||
class_tree = {}
|
||||
visibility = {}
|
||||
textures = {}
|
||||
|
||||
# Build classificator tree from mapcss-mapping.csv file
|
||||
types_file = open(os.path.join(ddir, 'types.txt'), "w")
|
||||
for row in csv.reader(open(os.path.join(ddir, 'mapcss-mapping.csv')), delimiter=';'):
|
||||
cl = row[0].replace("|", "-")
|
||||
pairs = [i.strip(']').split("=") for i in row[1].split(',')[0].split('[')]
|
||||
kv = {}
|
||||
for i in pairs:
|
||||
|
@ -42,9 +54,9 @@ def komap_mapswithme(options, style, filename):
|
|||
kv[i[0].strip('?')] = "yes"
|
||||
else:
|
||||
kv[i[0]] = i[1]
|
||||
classificator[row[0].replace("|", "-")] = kv
|
||||
classificator[cl] = kv
|
||||
if row[2] != "x":
|
||||
class_order.append(row[0].replace("|", "-"))
|
||||
class_order.append(cl)
|
||||
print >> types_file, row[0]
|
||||
else:
|
||||
# compatibility mode
|
||||
|
@ -52,169 +64,130 @@ def komap_mapswithme(options, style, filename):
|
|||
print >> types_file, row[6]
|
||||
else:
|
||||
print >> types_file, "mapswithme"
|
||||
class_tree[row[0].replace("|", "-")] = row[0]
|
||||
class_tree[cl] = row[0]
|
||||
class_order.sort()
|
||||
types_file.close()
|
||||
|
||||
def mwm_encode_color(st, prefix='', default='black'):
|
||||
if prefix:
|
||||
prefix += "-"
|
||||
opacity = hex(255 - int(255 * float(st.get(prefix + "opacity", 1))))
|
||||
color = whatever_to_hex(st.get(prefix + 'color', default))
|
||||
color = color[1] + color[1] + color[3] + color[3] + color[5] + color[5]
|
||||
return int(opacity + color, 16)
|
||||
# Get all mapcss tags which are used in mapcss-mapping.csv
|
||||
mapcss_mapping_tags = set()
|
||||
for v in classificator.values():
|
||||
for t in v.keys():
|
||||
mapcss_mapping_tags.add(t)
|
||||
|
||||
def mwm_encode_image(st, prefix='icon', bgprefix='symbol'):
|
||||
if prefix:
|
||||
prefix += "-"
|
||||
if bgprefix:
|
||||
bgprefix += "-"
|
||||
if prefix + "image" not in st:
|
||||
return False
|
||||
# strip last ".svg"
|
||||
handle = st.get(prefix + "image")[:-4]
|
||||
return handle, handle
|
||||
# Parse style mapcss
|
||||
style = MapCSS(options.minzoom, options.maxzoom + 1)
|
||||
style.parse(filename = options.filename, mapcss_tags = mapcss_mapping_tags)
|
||||
|
||||
# Build optimization tree - class/type -> StyleChoosers
|
||||
for cl in class_order:
|
||||
clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
|
||||
cltags = classificator[cl]
|
||||
style.build_choosers_tree(clname, "line", cltags)
|
||||
style.build_choosers_tree(clname, "area", cltags)
|
||||
style.build_choosers_tree(clname, "node", cltags)
|
||||
style.restore_choosers_order("line")
|
||||
style.restore_choosers_order("area")
|
||||
style.restore_choosers_order("node")
|
||||
|
||||
visibility = {}
|
||||
|
||||
bgpos = 0
|
||||
|
||||
dr_linecaps = {'none': BUTTCAP, 'butt': BUTTCAP, 'round': ROUNDCAP}
|
||||
dr_linejoins = {'none': NOJOIN, 'bevel': BEVELJOIN, 'round': ROUNDJOIN}
|
||||
|
||||
# atbuild = AccumulativeTimer()
|
||||
# atzstyles = AccumulativeTimer()
|
||||
# atdrcont = AccumulativeTimer()
|
||||
# atline = AccumulativeTimer()
|
||||
# atarea = AccumulativeTimer()
|
||||
# atnode = AccumulativeTimer()
|
||||
# Build drules tree
|
||||
|
||||
# atbuild.Start()
|
||||
drules = ContainerProto()
|
||||
|
||||
for cl in class_order:
|
||||
|
||||
clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
|
||||
# clname = cl
|
||||
style.build_choosers_tree(clname, "line", classificator[cl])
|
||||
style.build_choosers_tree(clname, "area", classificator[cl])
|
||||
style.build_choosers_tree(clname, "node", classificator[cl])
|
||||
|
||||
style.restore_choosers_order("line");
|
||||
style.restore_choosers_order("area");
|
||||
style.restore_choosers_order("node");
|
||||
cltags = classificator[cl]
|
||||
cltags["name"] = "name"
|
||||
cltags["addr:housenumber"] = "addr:housenumber"
|
||||
cltags["ref"] = "ref"
|
||||
cltags["int_name"] = "int_name"
|
||||
cltags["addr:flats"] = "addr:flats"
|
||||
|
||||
# atbuild.Stop()
|
||||
dr_cont = ClassifElementProto()
|
||||
dr_cont.name = cl
|
||||
|
||||
for cl in class_order:
|
||||
visstring = ["0"] * (options.maxzoom - options.minzoom + 1)
|
||||
|
||||
clname = cl if cl.find('-') == -1 else cl[:cl.find('-')]
|
||||
# clname = cl
|
||||
txclass = classificator[cl]
|
||||
txclass["name"] = "name"
|
||||
txclass["addr:housenumber"] = "addr:housenumber"
|
||||
txclass["ref"] = "ref"
|
||||
txclass["int_name"] = "int_name"
|
||||
txclass["addr:flats"] = "addr:flats"
|
||||
for zoom in xrange(options.minzoom, options.maxzoom + 1):
|
||||
|
||||
prev_area_len = -1
|
||||
prev_node_len = -1
|
||||
prev_line_len = -1
|
||||
check_area = True
|
||||
check_node = True
|
||||
check_line = True
|
||||
runtime_conditions_arr = []
|
||||
|
||||
# atzstyles.Start()
|
||||
# Get runtime conditions which are used for class 'cl' on zoom 'zoom'
|
||||
if "area" not in cltags:
|
||||
runtime_conditions_arr.extend( style.get_runtime_rules(clname, "line", cltags, zoom) )
|
||||
runtime_conditions_arr.extend( style.get_runtime_rules(clname, "area", cltags, zoom) )
|
||||
if "area" not in cltags:
|
||||
runtime_conditions_arr.extend( style.get_runtime_rules(clname, "node", cltags, zoom) )
|
||||
|
||||
zstyles_arr = [None] * (options.maxzoom - options.minzoom + 1)
|
||||
has_icons_for_areas_arr = [False] * (options.maxzoom - options.minzoom + 1)
|
||||
# If there is no any runtime conditions, do not filter style by runtime conditions
|
||||
if len(runtime_conditions_arr) == 0:
|
||||
runtime_conditions_arr.append(None)
|
||||
|
||||
for zoom in xrange(options.maxzoom, options.minzoom - 1, -1):
|
||||
has_icons_for_areas = False
|
||||
zstyle = {}
|
||||
for runtime_conditions in runtime_conditions_arr:
|
||||
|
||||
if check_line:
|
||||
if "area" not in txclass:
|
||||
# atline.Start()
|
||||
linestyle = style.get_style_dict(clname, "line", txclass, zoom, olddict=zstyle, cache=False)
|
||||
if prev_line_len == -1:
|
||||
prev_line_len = len(linestyle)
|
||||
if len(linestyle) == 0:
|
||||
if prev_line_len != 0:
|
||||
check_line = False
|
||||
has_icons_for_areas = False
|
||||
zstyle = {}
|
||||
|
||||
# Get style for class 'cl' on zoom 'zoom' with corresponding runtime conditions
|
||||
if "area" not in cltags:
|
||||
linestyle = style.get_style_dict(clname, "line", cltags, zoom, olddict=zstyle, filter_by_runtime_conditions=runtime_conditions)
|
||||
zstyle = linestyle
|
||||
# atline.Stop()
|
||||
|
||||
if check_area:
|
||||
# atarea.Start()
|
||||
areastyle = style.get_style_dict(clname, "area", txclass, zoom, olddict=zstyle, cache=False)
|
||||
areastyle = style.get_style_dict(clname, "area", cltags, zoom, olddict=zstyle, filter_by_runtime_conditions=runtime_conditions)
|
||||
for st in areastyle.values():
|
||||
if "icon-image" in st or 'symbol-shape' in st or 'symbol-image' in st:
|
||||
has_icons_for_areas = True
|
||||
break
|
||||
if prev_area_len == -1:
|
||||
prev_area_len = len(areastyle)
|
||||
if len(areastyle) == 0:
|
||||
if prev_area_len != 0:
|
||||
check_area = False
|
||||
zstyle = areastyle
|
||||
# atarea.Stop()
|
||||
|
||||
if check_node:
|
||||
if "area" not in txclass:
|
||||
# atnode.Start()
|
||||
nodestyle = style.get_style_dict(clname, "node", txclass, zoom, olddict=zstyle, cache=False)
|
||||
if prev_node_len == -1:
|
||||
prev_node_len = len(nodestyle)
|
||||
if len(nodestyle) == 0:
|
||||
if prev_node_len != 0:
|
||||
check_node = False
|
||||
if "area" not in cltags:
|
||||
nodestyle = style.get_style_dict(clname, "node", cltags, zoom, olddict=zstyle, filter_by_runtime_conditions=runtime_conditions)
|
||||
zstyle = nodestyle
|
||||
# atnode.Stop()
|
||||
|
||||
if not check_line and not check_area and not check_node:
|
||||
break
|
||||
zstyle = zstyle.values()
|
||||
|
||||
zstyle = zstyle.values()
|
||||
if len(zstyle) == 0:
|
||||
continue
|
||||
|
||||
zstyles_arr[zoom - options.minzoom] = zstyle
|
||||
has_icons_for_areas_arr[zoom - options.minzoom]= has_icons_for_areas
|
||||
has_lines = False
|
||||
has_icons = False
|
||||
has_fills = False
|
||||
for st in zstyle:
|
||||
st = dict([(k, v) for k, v in st.iteritems() if str(v).strip(" 0.")])
|
||||
if 'width' in st or 'pattern-image' in st:
|
||||
has_lines = True
|
||||
if 'icon-image' in st or 'symbol-shape' in st or 'symbol-image' in st:
|
||||
has_icons = True
|
||||
if 'fill-color' in st:
|
||||
has_fills = True
|
||||
|
||||
# atzstyles.Stop()
|
||||
has_text = None
|
||||
txfmt = []
|
||||
for st in zstyle:
|
||||
if st.get('text') and not st.get('text') in txfmt:
|
||||
txfmt.append(st.get('text'))
|
||||
if has_text is None:
|
||||
has_text = []
|
||||
has_text.append(st)
|
||||
|
||||
# atdrcont.Start()
|
||||
if (not has_lines) and (not has_text) and (not has_fills) and (not has_icons):
|
||||
continue
|
||||
|
||||
dr_cont = ClassifElementProto()
|
||||
dr_cont.name = cl
|
||||
for zoom in xrange(options.minzoom, options.maxzoom + 1):
|
||||
zstyle = zstyles_arr[zoom - options.minzoom]
|
||||
if zstyle is None or len(zstyle) == 0:
|
||||
continue
|
||||
has_icons_for_areas = has_icons_for_areas_arr[zoom - options.minzoom]
|
||||
|
||||
has_lines = False
|
||||
has_icons = False
|
||||
has_fills = False
|
||||
for st in zstyle:
|
||||
st = dict([(k, v) for k, v in st.iteritems() if str(v).strip(" 0.")])
|
||||
if 'width' in st or 'pattern-image' in st:
|
||||
has_lines = True
|
||||
if 'icon-image' in st or 'symbol-shape' in st or 'symbol-image' in st:
|
||||
has_icons = True
|
||||
if 'fill-color' in st:
|
||||
has_fills = True
|
||||
|
||||
has_text = None
|
||||
txfmt = []
|
||||
for st in zstyle:
|
||||
if st.get('text') and not st.get('text') in txfmt:
|
||||
txfmt.append(st.get('text'))
|
||||
if has_text is None:
|
||||
has_text = []
|
||||
has_text.append(st)
|
||||
|
||||
if has_lines or has_text or has_fills or has_icons:
|
||||
visstring[zoom] = "1"
|
||||
|
||||
dr_element = DrawElementProto()
|
||||
dr_element.scale = zoom
|
||||
|
||||
if runtime_conditions:
|
||||
for rc in runtime_conditions:
|
||||
dr_element.apply_if.append(str(rc))
|
||||
|
||||
for st in zstyle:
|
||||
if st.get('-x-kot-layer') == 'top':
|
||||
st['z-index'] = float(st.get('z-index', 0)) + 15001.
|
||||
|
@ -266,7 +239,6 @@ def komap_mapswithme(options, style, filename):
|
|||
dr_line.pathsym.offset = st.get('pattern-offset', 0)
|
||||
dr_line.priority = int(st.get('z-index', 0)) + 1000
|
||||
dr_element.lines.extend([dr_line])
|
||||
textures[icon[0]] = icon[1]
|
||||
if st.get('shield-font-size'):
|
||||
dr_element.shield.height = int(st.get('shield-font-size', 10))
|
||||
dr_element.shield.color = mwm_encode_color(st, "shield-text")
|
||||
|
@ -281,7 +253,6 @@ def komap_mapswithme(options, style, filename):
|
|||
icon = mwm_encode_image(st)
|
||||
dr_element.symbol.name = icon[0]
|
||||
dr_element.symbol.priority = min(19100, (16000 + int(st.get('z-index', 0))))
|
||||
textures[icon[0]] = icon[1]
|
||||
has_icons = False
|
||||
if st.get('symbol-shape'):
|
||||
dr_element.circle.radius = float(st.get('symbol-size'))
|
||||
|
@ -337,15 +308,18 @@ def komap_mapswithme(options, style, filename):
|
|||
if dr_cont.element:
|
||||
drules.cont.extend([dr_cont])
|
||||
|
||||
# atdrcont.Stop()
|
||||
|
||||
visibility["world|" + class_tree[cl] + "|"] = "".join(visstring)
|
||||
|
||||
# atwrite = AccumulativeTimer()
|
||||
# atwrite.Start()
|
||||
# Write drules_proto.bin and drules_proto.txt files
|
||||
|
||||
drules_bin = open(os.path.join(options.outfile + '.bin'), "wb")
|
||||
drules_txt = open(os.path.join(options.outfile + '.txt'), "wb")
|
||||
drules_bin.write(drules.SerializeToString())
|
||||
drules_txt.write(unicode(drules))
|
||||
drules_bin.close()
|
||||
drules_txt.close()
|
||||
|
||||
# Write classificator.txt and visibility.txt files
|
||||
|
||||
visnodes = set()
|
||||
for k, v in visibility.iteritems():
|
||||
|
@ -373,7 +347,6 @@ def komap_mapswithme(options, style, filename):
|
|||
for i in range(len(oldoffset) / 4, len(offset) / 4, -1):
|
||||
print >> visibility_file, " " * i + "{}"
|
||||
print >> classificator_file, " " * i + "{}"
|
||||
|
||||
oldoffset = offset
|
||||
end = "-"
|
||||
if k in visnodes:
|
||||
|
@ -384,58 +357,31 @@ def komap_mapswithme(options, style, filename):
|
|||
print >> visibility_file, " " * i + "{}"
|
||||
print >> classificator_file, " " * i + "{}"
|
||||
|
||||
# atwrite.Stop()
|
||||
|
||||
# print "build, sec: %s" % (atbuild.ElapsedSec())
|
||||
# print "zstyle %s times, sec: %s" % (atzstyles.Count(), atzstyles.ElapsedSec())
|
||||
# print "drcont %s times, sec: %s" % (atdrcont.Count(), atdrcont.ElapsedSec())
|
||||
# print "line %s times, sec: %s" % (atline.Count(), atline.ElapsedSec())
|
||||
# print "area %s times, sec: %s" % (atarea.Count(), atarea.ElapsedSec())
|
||||
# print "node %s times, sec: %s" % (atnode.Count(), atnode.ElapsedSec())
|
||||
# print "writing files, sec: %s" % (atwrite.ElapsedSec())
|
||||
visibility_file.close()
|
||||
classificator_file.close()
|
||||
|
||||
# Main
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("-s", "--stylesheet", dest="filename",
|
||||
help="read MapCSS stylesheet from FILE", metavar="FILE")
|
||||
parser.add_option("-f", "--minzoom", dest="minzoom", default=0, type="int",
|
||||
help="minimal available zoom level", metavar="ZOOM")
|
||||
parser.add_option("-t", "--maxzoom", dest="maxzoom", default=19, type="int",
|
||||
help="maximal available zoom level", metavar="ZOOM")
|
||||
parser.add_option("-l", "--locale", dest="locale",
|
||||
help="language that should be used for labels (ru, en, be, uk..)", metavar="LANG")
|
||||
parser.add_option("-o", "--output-file", dest="outfile", default="-",
|
||||
help="output filename (defaults to stdout)", metavar="FILE")
|
||||
parser.add_option("-p", "--osm2pgsql-style", dest="osm2pgsqlstyle", default="-",
|
||||
help="osm2pgsql stylesheet filename", metavar="FILE")
|
||||
parser.add_option("-b", "--background-only", dest="bgonly", action="store_true", default=False,
|
||||
help="Skip rendering of icons and labels", metavar="BOOL")
|
||||
parser.add_option("-T", "--text-scale", dest="textscale", default=1, type="float",
|
||||
help="text size scale", metavar="SCALE")
|
||||
parser.add_option("-c", "--config", dest="conffile", default="komap.conf",
|
||||
help="config file name", metavar="FILE")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if (options.filename is None):
|
||||
parser.error("MapCSS stylesheet filename is required")
|
||||
|
||||
try:
|
||||
# atparse = AccumulativeTimer()
|
||||
# atbuild = AccumulativeTimer()
|
||||
parser = OptionParser()
|
||||
parser.add_option("-s", "--stylesheet", dest="filename",
|
||||
help="read MapCSS stylesheet from FILE", metavar="FILE")
|
||||
parser.add_option("-f", "--minzoom", dest="minzoom", default=0, type="int",
|
||||
help="minimal available zoom level", metavar="ZOOM")
|
||||
parser.add_option("-t", "--maxzoom", dest="maxzoom", default=19, type="int",
|
||||
help="maximal available zoom level", metavar="ZOOM")
|
||||
parser.add_option("-o", "--output-file", dest="outfile", default="-",
|
||||
help="output filename (defaults to stdout)", metavar="FILE")
|
||||
|
||||
# atparse.Start()
|
||||
style = MapCSS(options.minzoom, options.maxzoom + 1) # zoom levels
|
||||
style.parse(filename = options.filename)
|
||||
# atparse.Stop()
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
# atbuild.Start()
|
||||
komap_mapswithme(options, style, options.filename)
|
||||
# atbuild.Stop()
|
||||
if (options.filename is None):
|
||||
parser.error("MapCSS stylesheet filename is required")
|
||||
|
||||
# print "mapcss parse, sec: %s" % (atparse.ElapsedSec())
|
||||
# print "build, sec: %s" % (atbuild.ElapsedSec())
|
||||
if options.outfile == "-":
|
||||
parser.error("Please specify base output path.")
|
||||
|
||||
komap_mapswithme(options)
|
||||
|
||||
exit(0)
|
||||
|
||||
|
|
|
@ -17,96 +17,19 @@
|
|||
|
||||
import re
|
||||
|
||||
# Fast conditions
|
||||
|
||||
class EqConditionDD:
|
||||
def __init__(self, params):
|
||||
self.value = params[1]
|
||||
def extract_tags(self):
|
||||
return set(["*"])
|
||||
def test(self, tags):
|
||||
return self.value
|
||||
|
||||
class EqCondition:
|
||||
def __init__(self, params):
|
||||
self.tag = params[0]
|
||||
self.value = params[1]
|
||||
def extract_tags(self):
|
||||
return set([self.tag])
|
||||
def test(self, tags):
|
||||
if self.tag in tags:
|
||||
return tags[self.tag] == self.value
|
||||
else:
|
||||
return False
|
||||
|
||||
class NotEqCondition:
|
||||
def __init__(self, params):
|
||||
self.tag = params[0]
|
||||
self.value = params[1]
|
||||
def extract_tags(self):
|
||||
return set([self.tag])
|
||||
def test(self, tags):
|
||||
if self.tag in tags:
|
||||
return tags[self.tag] != self.value
|
||||
else:
|
||||
return False
|
||||
|
||||
class SetCondition:
|
||||
def __init__(self, params):
|
||||
self.tag = params[0]
|
||||
def extract_tags(self):
|
||||
return set([self.tag])
|
||||
def test(self, tags):
|
||||
if self.tag in tags:
|
||||
return tags[self.tag] != ''
|
||||
return False
|
||||
|
||||
class UnsetCondition:
|
||||
def __init__(self, params):
|
||||
self.tag = params[0]
|
||||
def extract_tags(self):
|
||||
return set([self.tag])
|
||||
def test(self, tags):
|
||||
if self.tag in tags:
|
||||
return tags[self.tag] == ''
|
||||
return True
|
||||
|
||||
class TrueCondition:
|
||||
def __init__(self, params):
|
||||
self.tag = params[0]
|
||||
def extract_tags(self):
|
||||
return set([self.tag])
|
||||
def test(self, tags):
|
||||
if self.tag in tags:
|
||||
return tags[self.tag] == 'yes'
|
||||
return False
|
||||
|
||||
class UntrueCondition:
|
||||
def __init__(self, params):
|
||||
self.tag = params[0]
|
||||
def extract_tags(self):
|
||||
return set([self.tag])
|
||||
def test(self, tags):
|
||||
if self.tag in tags:
|
||||
return tags[self.tag] == 'no'
|
||||
return False
|
||||
|
||||
# Slow condition
|
||||
|
||||
class Condition:
|
||||
def __init__(self, typez, params):
|
||||
self.type = typez # eq, regex, lt, gt etc.
|
||||
if type(params) == type(str()):
|
||||
params = (params,)
|
||||
self.params = params # e.g. ('highway','primary')
|
||||
self.params = params # e.g. ('highway','primary')
|
||||
if typez == "regex":
|
||||
self.regex = re.compile(self.params[0], re.I)
|
||||
self.compiled_regex = ""
|
||||
|
||||
def extract_tags(self):
|
||||
def extract_tag(self):
|
||||
if self.params[0][:2] == "::" or self.type == "regex":
|
||||
return set(["*"]) # unknown
|
||||
return set([self.params[0]])
|
||||
return "*" # unknown
|
||||
return self.params[0]
|
||||
|
||||
def test(self, tags):
|
||||
"""
|
||||
|
@ -136,7 +59,6 @@ class Condition:
|
|||
if params[0] in tags:
|
||||
return tags[params[0]] == ''
|
||||
return True
|
||||
|
||||
if t == '<':
|
||||
return (Number(tags[params[0]]) < Number(params[1]))
|
||||
if t == '<=':
|
||||
|
@ -150,6 +72,32 @@ class Condition:
|
|||
return False
|
||||
|
||||
def __repr__(self):
|
||||
t = self.type
|
||||
params = self.params
|
||||
if t == 'eq' and params[0][:2] == "::":
|
||||
return "::%s" % (params[1])
|
||||
if t == 'eq':
|
||||
return "%s=%s" % (params[0], params[1])
|
||||
if t == 'ne':
|
||||
return "%s=%s" % (params[0], params[1])
|
||||
if t == 'regex':
|
||||
return "%s=~/%s/" % (params[0], params[1]);
|
||||
if t == 'true':
|
||||
return "%s?" % (params[0])
|
||||
if t == 'untrue':
|
||||
return "!%s?" % (params[0])
|
||||
if t == 'set':
|
||||
return "%s" % (params[0])
|
||||
if t == 'unset':
|
||||
return "!%s" % (params[0])
|
||||
if t == '<':
|
||||
return "%s<%s" % (params[0], params[1])
|
||||
if t == '<=':
|
||||
return "%s<=%s" % (params[0], params[1])
|
||||
if t == '>':
|
||||
return "%s>%s" % (params[0], params[1])
|
||||
if t == '>=':
|
||||
return "%s>=%s" % (params[0], params[1])
|
||||
return "%s %s " % (self.type, repr(self.params))
|
||||
|
||||
def __eq__(self, a):
|
||||
|
@ -164,23 +112,3 @@ def Number(tt):
|
|||
except ValueError:
|
||||
return 0
|
||||
|
||||
# Some conditions we can optimize by using "python polymorthism"
|
||||
|
||||
def OptimizeCondition(condition):
|
||||
if (condition.type == "eq"):
|
||||
if (condition.params[0][:2] == "::"):
|
||||
return EqConditionDD(condition.params)
|
||||
else:
|
||||
return EqCondition(condition.params)
|
||||
elif (condition.type == "ne"):
|
||||
return NotEqCondition(condition.params)
|
||||
elif (condition.type == "set"):
|
||||
return SetCondition(condition.params)
|
||||
elif (condition.type == "unset"):
|
||||
return UnsetCondition(condition.params)
|
||||
elif (condition.type == "true"):
|
||||
return TrueCondition(condition.params)
|
||||
elif (condition.type == "untrue"):
|
||||
return UntrueCondition(condition.params)
|
||||
else:
|
||||
return condition
|
||||
|
|
|
@ -25,6 +25,7 @@ type_matches = {
|
|||
|
||||
class Rule():
|
||||
def __init__(self, s=''):
|
||||
self.runtime_conditions = []
|
||||
self.conditions = []
|
||||
# self.isAnd = True
|
||||
self.minZoom = 0
|
||||
|
@ -34,7 +35,7 @@ class Rule():
|
|||
self.subject = s # "", "way", "node" or "relation"
|
||||
|
||||
def __repr__(self):
|
||||
return "%s|z%s-%s %s" % (self.subject, self.minZoom, self.maxZoom, self.conditions)
|
||||
return "%s|z%s-%s %s %s" % (self.subject, self.minZoom, self.maxZoom, self.conditions, self.runtime_conditions)
|
||||
|
||||
def test(self, obj, tags, zoom):
|
||||
if (zoom < self.minZoom) or (zoom > self.maxZoom):
|
||||
|
@ -58,8 +59,9 @@ class Rule():
|
|||
def extract_tags(self):
|
||||
a = set()
|
||||
for condition in self.conditions:
|
||||
a.update(condition.extract_tags())
|
||||
a.add(condition.extract_tag())
|
||||
if "*" in a:
|
||||
a = set(["*"])
|
||||
break
|
||||
return a
|
||||
|
||||
|
|
|
@ -106,21 +106,42 @@ class StyleChooser:
|
|||
a.add("*")
|
||||
return a
|
||||
|
||||
def updateStyles(self, sl, ftype, tags, zoom, scale, zscale):
|
||||
def get_runtime_conditions(self, ftype, tags, zoom):
|
||||
if self.selzooms:
|
||||
if zoom < self.selzooms[0] or zoom > self.selzooms[1]:
|
||||
return None
|
||||
|
||||
rule_and_object_id = self.testChain(self.ruleChains, ftype, tags, zoom)
|
||||
|
||||
if not rule_and_object_id:
|
||||
return None
|
||||
|
||||
rule = rule_and_object_id[0]
|
||||
|
||||
if (len(rule.runtime_conditions) == 0):
|
||||
return None
|
||||
|
||||
return rule.runtime_conditions
|
||||
|
||||
def updateStyles(self, sl, ftype, tags, zoom, xscale, zscale, filter_by_runtime_conditions):
|
||||
# Are any of the ruleChains fulfilled?
|
||||
if self.selzooms:
|
||||
if zoom < self.selzooms[0] or zoom > self.selzooms[1]:
|
||||
return sl
|
||||
|
||||
#if ftype not in self.compatible_types:
|
||||
# return sl
|
||||
#return sl
|
||||
|
||||
object_id = self.testChain(self.ruleChains, ftype, tags, zoom)
|
||||
rule_and_object_id = self.testChain(self.ruleChains, ftype, tags, zoom)
|
||||
|
||||
if not object_id:
|
||||
if not rule_and_object_id:
|
||||
return sl
|
||||
|
||||
w = 0
|
||||
rule = rule_and_object_id[0]
|
||||
object_id = rule_and_object_id[1]
|
||||
|
||||
if filter_by_runtime_conditions and (filter_by_runtime_conditions != rule.runtime_conditions):
|
||||
return sl
|
||||
|
||||
for r in self.styles:
|
||||
if self.has_evals:
|
||||
|
@ -134,9 +155,8 @@ class StyleChooser:
|
|||
for p, q in combined_style.iteritems():
|
||||
if "color" in p:
|
||||
combined_style[p] = cairo_to_hex(q)
|
||||
b = b.compute(tags, combined_style, scale, zscale)
|
||||
b = b.compute(tags, combined_style, xscale, zscale)
|
||||
ra[a] = b
|
||||
#r = ra
|
||||
ra = make_nice_style(ra)
|
||||
else:
|
||||
ra = r.copy()
|
||||
|
@ -171,7 +191,7 @@ class StyleChooser:
|
|||
for r in chain:
|
||||
tt = r.test(obj, tags, zoom)
|
||||
if tt:
|
||||
return tt
|
||||
return r, tt
|
||||
return False
|
||||
|
||||
def newGroup(self):
|
||||
|
@ -203,9 +223,16 @@ class StyleChooser:
|
|||
"""
|
||||
adds into the current ruleChain (existing Rule)
|
||||
"""
|
||||
c = OptimizeCondition(c)
|
||||
self.ruleChains[-1].conditions.append(c)
|
||||
|
||||
def addRuntimeCondition(self, c):
|
||||
# print "addRuntimeCondition ", c
|
||||
"""
|
||||
adds into the current ruleChain (existing Rule)
|
||||
"""
|
||||
self.ruleChains[-1].runtime_conditions.append(c)
|
||||
self.ruleChains[-1].runtime_conditions.sort()
|
||||
|
||||
def addStyles(self, a):
|
||||
# print "addStyle ", a
|
||||
"""
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
import re
|
||||
import os
|
||||
import logging
|
||||
from hashlib import md5
|
||||
|
||||
from copy import copy, deepcopy
|
||||
|
||||
|
||||
from StyleChooser import StyleChooser
|
||||
from Condition import Condition
|
||||
|
||||
|
@ -30,7 +25,6 @@ from Condition import Condition
|
|||
NEEDED_KEYS = set(["width", "casing-width", "fill-color", "fill-image", "icon-image", "text", "extrude",
|
||||
"background-image", "background-color", "pattern-image", "shield-text", "symbol-shape"])
|
||||
|
||||
|
||||
WHITESPACE = re.compile(r'^ \s+ ', re.S | re.X)
|
||||
|
||||
COMMENT = re.compile(r'^ \/\* .+? \*\/ \s* ', re.S | re.X)
|
||||
|
@ -39,6 +33,7 @@ CLASS = re.compile(r'^ ([\.:]:?[*\w]+) \s* ', re.S | re.X)
|
|||
ZOOM = re.compile(r'^ \| \s* z([\d\-]+) \s* ', re.I | re.S | re.X)
|
||||
GROUP = re.compile(r'^ , \s* ', re.I | re.S | re.X)
|
||||
CONDITION = re.compile(r'^ \[(.+?)\] \s* ', re.S | re.X)
|
||||
RUNTIME_CONDITION = re.compile(r'^ \((.+?)\) \s* ', re.S | re.X)
|
||||
OBJECT = re.compile(r'^ (\*|[\w]+) \s* ', re.S | re.X)
|
||||
DECLARATION = re.compile(r'^ \{(.+?)\} \s* ', re.S | re.X)
|
||||
IMPORT = re.compile(r'^@import\("(.+?)"\); \s* ', re.S | re.X)
|
||||
|
@ -139,19 +134,23 @@ class MapCSS():
|
|||
tmp.append(ec)
|
||||
self.choosers_by_type_and_tag[type][tag] = tmp
|
||||
|
||||
def get_style(self, clname, type, tags={}, zoom=0, scale=1, zscale=.5, cache=True):
|
||||
def get_runtime_rules(self, clname, type, tags, zoom):
|
||||
"""
|
||||
Kothic styling API
|
||||
Returns array of runtime_conditions which are used for clname/type/tags/zoom
|
||||
"""
|
||||
if cache:
|
||||
shash = md5(repr(type) + repr(tags) + repr(zoom)).digest()
|
||||
if shash in self.cache["style"]:
|
||||
return deepcopy(self.cache["style"][shash])
|
||||
runtime_rules = []
|
||||
if type in self.choosers_by_type_and_tag:
|
||||
for chooser in self.choosers_by_type_and_tag[type][clname]:
|
||||
runtime_conditions = chooser.get_runtime_conditions(type, tags, zoom)
|
||||
if runtime_conditions:
|
||||
runtime_rules.append(runtime_conditions)
|
||||
return runtime_rules
|
||||
|
||||
def get_style(self, clname, type, tags, zoom, xscale, zscale, filter_by_runtime_conditions):
|
||||
style = []
|
||||
if type in self.choosers_by_type_and_tag:
|
||||
choosers = self.choosers_by_type_and_tag[type][clname]
|
||||
for chooser in choosers:
|
||||
style = chooser.updateStyles(style, type, tags, zoom, scale, zscale)
|
||||
for chooser in self.choosers_by_type_and_tag[type][clname]:
|
||||
style = chooser.updateStyles(style, type, tags, zoom, xscale, zscale, filter_by_runtime_conditions)
|
||||
style = [x for x in style if x["object-id"] != "::*"]
|
||||
for x in style:
|
||||
for k, v in [('width', 0), ('casing-width', 0)]:
|
||||
|
@ -163,13 +162,13 @@ class MapCSS():
|
|||
if not NEEDED_KEYS.isdisjoint(x):
|
||||
st.append(x)
|
||||
style = st
|
||||
|
||||
if cache:
|
||||
self.cache["style"][shash] = deepcopy(style)
|
||||
return style
|
||||
|
||||
def get_style_dict(self, clname, type, tags={}, zoom=0, scale=1, zscale=.5, olddict={}, cache=True):
|
||||
r = self.get_style(clname, type, tags, zoom, scale, zscale, cache)
|
||||
def get_style_dict(self, clname, type, tags={}, zoom=0, xscale=1, zscale=.5, olddict={}, filter_by_runtime_conditions=None):
|
||||
"""
|
||||
Kothic styling API
|
||||
"""
|
||||
r = self.get_style(clname, type, tags, zoom, xscale, zscale, filter_by_runtime_conditions)
|
||||
d = olddict
|
||||
for x in r:
|
||||
if x.get('object-id', '') not in d:
|
||||
|
@ -178,7 +177,7 @@ class MapCSS():
|
|||
return d
|
||||
|
||||
def subst_variables(self, t):
|
||||
"""Expects an array from parseDeclaration."""
|
||||
""" Expects an array from parseDeclaration. """
|
||||
for k in t[0]:
|
||||
t[0][k] = VARIABLE.sub(self.get_variable, t[0][k])
|
||||
return t
|
||||
|
@ -189,7 +188,7 @@ class MapCSS():
|
|||
raise Exception("Variable not found: " + str(format(name)))
|
||||
return self.variables[name] if name in self.variables else m.group()
|
||||
|
||||
def parse(self, css=None, clamp=True, stretch=1000, filename=None):
|
||||
def parse(self, css=None, clamp=True, stretch=1000, filename=None, mapcss_tags=None):
|
||||
"""
|
||||
Parses MapCSS given as string
|
||||
"""
|
||||
|
@ -251,6 +250,19 @@ class MapCSS():
|
|||
sc.newGroup()
|
||||
previous = oGROUP
|
||||
|
||||
# RuntimeCondition - (population>=10000)
|
||||
elif RUNTIME_CONDITION.match(css):
|
||||
if (previous == oDECLARATION):
|
||||
self.choosers.append(sc)
|
||||
sc = StyleChooser(self.scalepair)
|
||||
if (previous != oOBJECT) and (previous != oZOOM) and (previous != oCONDITION):
|
||||
sc.newObject()
|
||||
cond = RUNTIME_CONDITION.match(css).groups()[0]
|
||||
log.debug("runtime condition found: %s" % (cond))
|
||||
css = RUNTIME_CONDITION.sub("", css)
|
||||
sc.addRuntimeCondition(parseCondition(cond))
|
||||
previous = oCONDITION
|
||||
|
||||
# Condition - [highway=primary]
|
||||
elif CONDITION.match(css):
|
||||
if (previous == oDECLARATION):
|
||||
|
@ -260,8 +272,12 @@ class MapCSS():
|
|||
sc.newObject()
|
||||
cond = CONDITION.match(css).groups()[0]
|
||||
log.debug("condition found: %s" % (cond))
|
||||
c = parseCondition(cond)
|
||||
tag = c.extract_tag()
|
||||
if (tag != "*") and (mapcss_tags != None) and (tag not in mapcss_tags):
|
||||
raise Exception("Unknown tag '" + tag + "' in condition " + cond)
|
||||
css = CONDITION.sub("", css)
|
||||
sc.addCondition(parseCondition(cond))
|
||||
sc.addCondition(c)
|
||||
previous = oCONDITION
|
||||
|
||||
# Object - way, node, relation
|
||||
|
|
|
@ -19,7 +19,7 @@ _sym_db = _symbol_database.Default()
|
|||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='drules_struct.proto',
|
||||
package='',
|
||||
serialized_pb=_b('\n\x13\x64rules_struct.proto\"*\n\x0c\x44\x61shDotProto\x12\n\n\x02\x64\x64\x18\x01 \x03(\x01\x12\x0e\n\x06offset\x18\x02 \x01(\x01\":\n\x0cPathSymProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04step\x18\x02 \x02(\x01\x12\x0e\n\x06offset\x18\x03 \x01(\x01\"\xaf\x01\n\rLineRuleProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\x12\x1e\n\x07pathsym\x18\x05 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"\x9c\x01\n\x0cLineDefProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x1e\n\x07pathsym\x18\x04 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"O\n\rAreaRuleProto\x12\r\n\x05\x63olor\x18\x01 \x02(\r\x12\x1d\n\x06\x62order\x18\x02 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"I\n\x0fSymbolRuleProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x16\n\x0e\x61pply_for_type\x18\x02 \x01(\x05\x12\x10\n\x08priority\x18\x03 \x02(\x05\"j\n\x0f\x43\x61ptionDefProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08offset_x\x18\x04 \x01(\x05\x12\x10\n\x08offset_y\x18\x05 \x01(\x05\"l\n\x10\x43\x61ptionRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"a\n\x0f\x43ircleRuleProto\x12\x0e\n\x06radius\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1d\n\x06\x62order\x18\x03 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\"m\n\x11PathTextRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"X\n\x0fShieldRuleProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08priority\x18\x04 \x02(\x05\"\x8f\x02\n\x10\x44rawElementProto\x12\r\n\x05scale\x18\x01 \x02(\x05\x12\x1d\n\x05lines\x18\x02 \x03(\x0b\x32\x0e.LineRuleProto\x12\x1c\n\x04\x61rea\x18\x03 \x01(\x0b\x32\x0e.AreaRuleProto\x12 \n\x06symbol\x18\x04 \x01(\x0b\x32\x10.SymbolRuleProto\x12\"\n\x07\x63\x61ption\x18\x05 \x01(\x0b\x32\x11.CaptionRuleProto\x12 \n\x06\x63ircle\x18\x06 \x01(\x0b\x32\x10.CircleRuleProto\x12%\n\tpath_text\x18\x07 \x01(\x0b\x32\x12.PathTextRuleProto\x12 \n\x06shield\x18\x08 \x01(\x0b\x32\x10.ShieldRuleProto\"G\n\x13\x43lassifElementProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\"\n\x07\x65lement\x18\x02 \x03(\x0b\x32\x11.DrawElementProto\"4\n\x0e\x43ontainerProto\x12\"\n\x04\x63ont\x18\x01 \x03(\x0b\x32\x14.ClassifElementProto*4\n\x08LineJoin\x12\r\n\tROUNDJOIN\x10\x00\x12\r\n\tBEVELJOIN\x10\x01\x12\n\n\x06NOJOIN\x10\x02*3\n\x07LineCap\x12\x0c\n\x08ROUNDCAP\x10\x00\x12\x0b\n\x07\x42UTTCAP\x10\x01\x12\r\n\tSQUARECAP\x10\x02\x42\x02H\x03')
|
||||
serialized_pb=_b('\n\x13\x64rules_struct.proto\"*\n\x0c\x44\x61shDotProto\x12\n\n\x02\x64\x64\x18\x01 \x03(\x01\x12\x0e\n\x06offset\x18\x02 \x01(\x01\":\n\x0cPathSymProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04step\x18\x02 \x02(\x01\x12\x0e\n\x06offset\x18\x03 \x01(\x01\"\xaf\x01\n\rLineRuleProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\x12\x1e\n\x07pathsym\x18\x05 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"\x9c\x01\n\x0cLineDefProto\x12\r\n\x05width\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1e\n\x07\x64\x61shdot\x18\x03 \x01(\x0b\x32\r.DashDotProto\x12\x1e\n\x07pathsym\x18\x04 \x01(\x0b\x32\r.PathSymProto\x12\x17\n\x04join\x18\x06 \x01(\x0e\x32\t.LineJoin\x12\x15\n\x03\x63\x61p\x18\x07 \x01(\x0e\x32\x08.LineCap\"O\n\rAreaRuleProto\x12\r\n\x05\x63olor\x18\x01 \x02(\r\x12\x1d\n\x06\x62order\x18\x02 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"I\n\x0fSymbolRuleProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x16\n\x0e\x61pply_for_type\x18\x02 \x01(\x05\x12\x10\n\x08priority\x18\x03 \x02(\x05\"j\n\x0f\x43\x61ptionDefProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08offset_x\x18\x04 \x01(\x05\x12\x10\n\x08offset_y\x18\x05 \x01(\x05\"l\n\x10\x43\x61ptionRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"a\n\x0f\x43ircleRuleProto\x12\x0e\n\x06radius\x18\x01 \x02(\x01\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x1d\n\x06\x62order\x18\x03 \x01(\x0b\x32\r.LineDefProto\x12\x10\n\x08priority\x18\x04 \x02(\x05\"m\n\x11PathTextRuleProto\x12!\n\x07primary\x18\x01 \x02(\x0b\x32\x10.CaptionDefProto\x12#\n\tsecondary\x18\x02 \x01(\x0b\x32\x10.CaptionDefProto\x12\x10\n\x08priority\x18\x03 \x02(\x05\"X\n\x0fShieldRuleProto\x12\x0e\n\x06height\x18\x01 \x02(\x05\x12\r\n\x05\x63olor\x18\x02 \x02(\r\x12\x14\n\x0cstroke_color\x18\x03 \x01(\r\x12\x10\n\x08priority\x18\x04 \x02(\x05\"\xa1\x02\n\x10\x44rawElementProto\x12\r\n\x05scale\x18\x01 \x02(\x05\x12\x1d\n\x05lines\x18\x02 \x03(\x0b\x32\x0e.LineRuleProto\x12\x1c\n\x04\x61rea\x18\x03 \x01(\x0b\x32\x0e.AreaRuleProto\x12 \n\x06symbol\x18\x04 \x01(\x0b\x32\x10.SymbolRuleProto\x12\"\n\x07\x63\x61ption\x18\x05 \x01(\x0b\x32\x11.CaptionRuleProto\x12 \n\x06\x63ircle\x18\x06 \x01(\x0b\x32\x10.CircleRuleProto\x12%\n\tpath_text\x18\x07 \x01(\x0b\x32\x12.PathTextRuleProto\x12 \n\x06shield\x18\x08 \x01(\x0b\x32\x10.ShieldRuleProto\x12\x10\n\x08\x61pply_if\x18\t \x03(\t\"G\n\x13\x43lassifElementProto\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\"\n\x07\x65lement\x18\x02 \x03(\x0b\x32\x11.DrawElementProto\"4\n\x0e\x43ontainerProto\x12\"\n\x04\x63ont\x18\x01 \x03(\x0b\x32\x14.ClassifElementProto*4\n\x08LineJoin\x12\r\n\tROUNDJOIN\x10\x00\x12\r\n\tBEVELJOIN\x10\x01\x12\n\n\x06NOJOIN\x10\x02*3\n\x07LineCap\x12\x0c\n\x08ROUNDCAP\x10\x00\x12\x0b\n\x07\x42UTTCAP\x10\x01\x12\r\n\tSQUARECAP\x10\x02\x42\x02H\x03')
|
||||
)
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
|
@ -44,8 +44,8 @@ _LINEJOIN = _descriptor.EnumDescriptor(
|
|||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=1539,
|
||||
serialized_end=1591,
|
||||
serialized_start=1557,
|
||||
serialized_end=1609,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_LINEJOIN)
|
||||
|
||||
|
@ -71,8 +71,8 @@ _LINECAP = _descriptor.EnumDescriptor(
|
|||
],
|
||||
containing_type=None,
|
||||
options=None,
|
||||
serialized_start=1593,
|
||||
serialized_end=1644,
|
||||
serialized_start=1611,
|
||||
serialized_end=1662,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_LINECAP)
|
||||
|
||||
|
@ -703,6 +703,13 @@ _DRAWELEMENTPROTO = _descriptor.Descriptor(
|
|||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='apply_if', full_name='DrawElementProto.apply_if', index=8,
|
||||
number=9, type=9, cpp_type=9, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
|
@ -715,7 +722,7 @@ _DRAWELEMENTPROTO = _descriptor.Descriptor(
|
|||
oneofs=[
|
||||
],
|
||||
serialized_start=1139,
|
||||
serialized_end=1410,
|
||||
serialized_end=1428,
|
||||
)
|
||||
|
||||
|
||||
|
@ -751,8 +758,8 @@ _CLASSIFELEMENTPROTO = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1412,
|
||||
serialized_end=1483,
|
||||
serialized_start=1430,
|
||||
serialized_end=1501,
|
||||
)
|
||||
|
||||
|
||||
|
@ -781,8 +788,8 @@ _CONTAINERPROTO = _descriptor.Descriptor(
|
|||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=1485,
|
||||
serialized_end=1537,
|
||||
serialized_start=1503,
|
||||
serialized_end=1555,
|
||||
)
|
||||
|
||||
_LINERULEPROTO.fields_by_name['dashdot'].message_type = _DASHDOTPROTO
|
||||
|
|
Loading…
Add table
Reference in a new issue