Introduce concept of adaptive roads
This commit is contained in:
parent
6f220689d4
commit
be50369a77
6 changed files with 139 additions and 49 deletions
|
@ -410,6 +410,13 @@ public class RenderingRulesStorage {
|
|||
return renderingAttributes.get(attribute);
|
||||
}
|
||||
|
||||
public String[] getRenderingAttributeNames() {
|
||||
return renderingAttributes.keySet().toArray(new String[renderingAttributes.size()]);
|
||||
}
|
||||
public RenderingRule[] getRenderingAttributeValues() {
|
||||
return renderingAttributes.values().toArray(new RenderingRule[renderingAttributes.size()]);
|
||||
}
|
||||
|
||||
public RenderingRule[] getRules(int state){
|
||||
if(state >= tagValueGlobalRules.length || tagValueGlobalRules[state] == null) {
|
||||
return new RenderingRule[0];
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<!-- next line corrects for shadowColor appearing very dark with solid shadow in day view, bridges would not stand out -->
|
||||
<filter minzoom="14" nightMode="false" attrIntValue="3" shadowColor="#969696"/>
|
||||
<filter minzoom="14" attrIntValue="3" shadowColor="#464646"/>
|
||||
<filter minzoom="9" maxzoom="13" attrIntValue="3" shadowColor="#464646"/>
|
||||
<filter minzoom="9" maxzoom="13" attrIntValue="3" shadowColor="#969696"/>
|
||||
<filter attrIntValue="0"/>
|
||||
</renderingAttribute>
|
||||
|
||||
|
@ -57,13 +57,25 @@
|
|||
<filter attrColorValue="#B400FFFF"/>
|
||||
</renderingAttribute>
|
||||
|
||||
<renderingAttribute name="polygonMinSizeToDisplay">
|
||||
<filter attrIntValue="100"/>
|
||||
</renderingAttribute>
|
||||
|
||||
<renderingAttribute name="roadDensityZoomTile">
|
||||
<filter attrIntValue="3"/>
|
||||
</renderingAttribute>
|
||||
|
||||
<renderingAttribute name="roadsDensityLimitPerTile">
|
||||
<filter attrIntValue="12"/>
|
||||
</renderingAttribute>
|
||||
|
||||
<!-- filter does not work for renderingConstant - the last one will be used, but better use separate depends Rendering style -->
|
||||
<!-- roadColors="Modified Mapnik" -->
|
||||
<renderingConstant name="motorwayRoadColor" value="#809bff"/>
|
||||
<renderingConstant name="trunkRoadColor" value="#FF8095"/>
|
||||
<renderingConstant name="primaryRoadColor" value="#FFAA80"/>
|
||||
<renderingConstant name="secondaryRoadColor" value="#ffd080"/>
|
||||
<renderingConstant name="tertiaryRoadColor" value="#ffff80"/>
|
||||
<renderingConstant name="motorwayRoadColor" value="#809bff"/>
|
||||
<renderingConstant name="trunkRoadColor" value="#FF8095"/>
|
||||
<renderingConstant name="primaryRoadColor" value="#FFAA80"/>
|
||||
<renderingConstant name="secondaryRoadColor" value="#ffd080"/>
|
||||
<renderingConstant name="tertiaryRoadColor" value="#ffff80"/>
|
||||
<!-- transparent to see conjunctions -->
|
||||
<!-- <renderingConstant name="motorwayRoadColor" value="#55809bff"/>
|
||||
<renderingConstant name="trunkRoadColor" value="#55FF8095"/>
|
||||
|
|
|
@ -198,6 +198,9 @@ public :
|
|||
// not expect any shadow
|
||||
int shadowLevelMin;
|
||||
int shadowLevelMax;
|
||||
int polygonMinSizeToDisplay;
|
||||
int roadDensityZoomTile;
|
||||
int roadsDensityLimitPerTile;
|
||||
|
||||
public:
|
||||
RenderingContext() : shadowLevelMax(0), shadowLevelMin(256), density(true), useEnglishNames(false), pointCount(0),
|
||||
|
@ -205,6 +208,9 @@ public:
|
|||
setRotate(0);
|
||||
setZoom(15);
|
||||
setDefaultColor(0xfff1eee8);
|
||||
roadsDensityLimitPerTile = 0;
|
||||
roadDensityZoomTile = 0;
|
||||
polygonMinSizeToDisplay = 0;
|
||||
}
|
||||
virtual ~RenderingContext();
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ jclass RenderingRulesStorageClass;
|
|||
jfieldID RenderingRulesStorageClass_dictionary;
|
||||
jfieldID RenderingRulesStorage_PROPS;
|
||||
jmethodID RenderingRulesStorage_getRules;
|
||||
jmethodID RenderingRulesStorage_getRenderingAttributeNames;
|
||||
jmethodID RenderingRulesStorage_getRenderingAttributeValues;
|
||||
|
||||
jclass RenderingRuleSearchRequestClass;
|
||||
jfieldID RenderingRuleSearchRequest_storage;
|
||||
|
@ -111,20 +113,33 @@ void initDictionary(JNIEnv* env, RenderingRulesStorage* storage, jobject javaSto
|
|||
uint32_t i = 0;
|
||||
for (; i < sz; i++) {
|
||||
jstring st = (jstring) env->CallObjectMethod(listDictionary, List_get, i);
|
||||
// if(st != NULL)
|
||||
// {
|
||||
const char* utf = env->GetStringUTFChars(st, NULL);
|
||||
std::string d = std::string(utf);
|
||||
|
||||
env->ReleaseStringUTFChars(st, utf);
|
||||
env->DeleteLocalRef(st);
|
||||
// assert = i
|
||||
storage->registerString(d);
|
||||
// }
|
||||
}
|
||||
env->DeleteLocalRef(listDictionary);
|
||||
}
|
||||
|
||||
void initAttributes(JNIEnv* env, RenderingRulesStorage* st, jobject javaStorage) {
|
||||
jobjectArray attributeNames = (jobjectArray) env->CallObjectMethod(javaStorage, RenderingRulesStorage_getRenderingAttributeNames);
|
||||
jobjectArray attributeValues = (jobjectArray) env->CallObjectMethod(javaStorage, RenderingRulesStorage_getRenderingAttributeValues);
|
||||
uint32_t sz = env->GetArrayLength(attributeNames);
|
||||
for (uint32_t i = 0; i < sz; i++) {
|
||||
jstring nm = (jstring) env->GetObjectArrayElement(attributeNames, i);
|
||||
jobject vl = env->GetObjectArrayElement(attributeValues, i);
|
||||
RenderingRule* rule = createRenderingRule(env, vl, st);
|
||||
st->renderingAttributes[getString(env, nm)] = rule;
|
||||
env->DeleteLocalRef(nm);
|
||||
env->DeleteLocalRef(vl);
|
||||
}
|
||||
env->DeleteLocalRef(attributeNames);
|
||||
env->DeleteLocalRef(attributeValues);
|
||||
|
||||
}
|
||||
|
||||
void initProperties(JNIEnv* env, RenderingRulesStorage* st, jobject javaStorage) {
|
||||
jobject props = env->GetObjectField(javaStorage, RenderingRulesStorage_PROPS);
|
||||
jobject listProps = env->GetObjectField(props, RenderingRuleStorageProperties_rules);
|
||||
|
@ -165,6 +180,7 @@ RenderingRulesStorage* createRenderingRulesStorage(JNIEnv* env, jobject storage)
|
|||
initDictionary(env, res, storage);
|
||||
initProperties(env, res, storage);
|
||||
initRules(env, res, storage);
|
||||
initAttributes(env, res, storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -261,6 +277,10 @@ void loadJniRenderingRules(JNIEnv* env) {
|
|||
"Lnet/osmand/render/RenderingRuleStorageProperties;");
|
||||
RenderingRulesStorage_getRules = env->GetMethodID(RenderingRulesStorageClass, "getRules",
|
||||
"(I)[Lnet/osmand/render/RenderingRule;");
|
||||
RenderingRulesStorage_getRenderingAttributeNames = env->GetMethodID(RenderingRulesStorageClass, "getRenderingAttributeNames",
|
||||
"()[Ljava/lang/String;");
|
||||
RenderingRulesStorage_getRenderingAttributeValues = env->GetMethodID(RenderingRulesStorageClass, "getRenderingAttributeValues",
|
||||
"()[Lnet/osmand/render/RenderingRule;");
|
||||
|
||||
ListClass = findClass(env, "java/util/List");
|
||||
List_size = env->GetMethodID(ListClass, "size", "()I");
|
||||
|
|
|
@ -131,6 +131,34 @@ extern "C" JNIEXPORT jlong JNICALL Java_net_osmand_NativeLibrary_searchNativeObj
|
|||
|
||||
//////////////////////////////////////////
|
||||
///////////// JNI RENDERING //////////////
|
||||
void fillRenderingAttributes(JNIRenderingContext& rc, RenderingRuleSearchRequest* req) {
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("defaultColor")) {
|
||||
rc.setDefaultColor(req->getIntPropertyValue(req->props()->R_ATTR_COLOR_VALUE));
|
||||
}
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("shadowRendering")) {
|
||||
rc.setShadowRenderingMode(req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE));
|
||||
rc.setShadowRenderingColor(req->getIntPropertyValue(req->props()->R_SHADOW_COLOR));
|
||||
}
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("polygonMinSizeToDisplay")) {
|
||||
rc.polygonMinSizeToDisplay = req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE);
|
||||
}
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("roadDensityZoomTile")) {
|
||||
rc.roadDensityZoomTile = req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE);
|
||||
}
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("roadsDensityLimitPerTile")) {
|
||||
rc.roadsDensityLimitPerTile = req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID_BUILD
|
||||
#include <android/bitmap.h>
|
||||
|
@ -204,22 +232,11 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib
|
|||
JNIRenderingContext rc;
|
||||
pullFromJavaRenderingContext(ienv, renderingContext, &rc);
|
||||
ResultPublisher* result = ((ResultPublisher*) searchResult);
|
||||
// std::vector <BaseMapDataObject* > mapDataObjects = marshalObjects(binaryMapDataObjects);
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("defaultColor")) {
|
||||
rc.setDefaultColor(req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE));
|
||||
}
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("shadowRendering")) {
|
||||
rc.setShadowRenderingMode(req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE));
|
||||
rc.setShadowRenderingColor(req->getIntPropertyValue(req->props()->R_SHADOW_COLOR));
|
||||
}
|
||||
|
||||
fillRenderingAttributes(rc, req);
|
||||
osmand_log_print(LOG_INFO, "Rendering image");
|
||||
initObjects.pause();
|
||||
|
||||
|
||||
// Main part do rendering
|
||||
rc.nativeOperations.start();
|
||||
SkCanvas* canvas = new SkCanvas(*bitmap);
|
||||
|
@ -259,6 +276,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLib
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
void* bitmapData = NULL;
|
||||
size_t bitmapDataSize = 0;
|
||||
extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_NativeLibrary_generateRenderingIndirect( JNIEnv* ienv,
|
||||
|
@ -298,17 +316,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_NativeLibrary_generateRende
|
|||
|
||||
initObjects.pause();
|
||||
// Main part do rendering
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("defaultColor")) {
|
||||
rc.setDefaultColor(req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE));
|
||||
}
|
||||
req->clearState();
|
||||
req->setIntFilter(req->props()->R_MINZOOM, rc.getZoom());
|
||||
if (req->searchRenderingAttribute("shadowRendering")) {
|
||||
rc.setShadowRenderingMode(req->getIntPropertyValue(req->props()->R_ATTR_INT_VALUE));
|
||||
rc.setShadowRenderingColor(req->getIntPropertyValue(req->props()->R_SHADOW_COLOR));
|
||||
}
|
||||
fillRenderingAttributes(rc, req);
|
||||
|
||||
|
||||
SkCanvas* canvas = new SkCanvas(*bitmap);
|
||||
|
@ -517,9 +525,6 @@ void pullFromJavaRenderingContext(JNIEnv* env, jobject jrc, JNIRenderingContext*
|
|||
rc->setTileDivisor(env->GetFloatField( jrc, jfield_RenderingContext_tileDivisor ));
|
||||
rc->setRotate(env->GetFloatField( jrc, jfield_RenderingContext_rotate ));
|
||||
rc->setDensityScale(env->GetFloatField( jrc, jfield_RenderingContext_density ));
|
||||
rc->setShadowRenderingMode(env->GetIntField( jrc, jfield_RenderingContext_shadowRenderingMode ));
|
||||
rc->setShadowRenderingColor(env->GetIntField( jrc, jfield_RenderingContext_shadowRenderingColor ));
|
||||
rc->setDefaultColor(env->GetIntField( jrc, jfield_RenderingContext_defaultColor ));
|
||||
rc->setUseEnglishNames(env->GetBooleanField( jrc, jfield_RenderingContext_useEnglishNames ));
|
||||
rc->javaRenderingContext = jrc;
|
||||
}
|
||||
|
|
|
@ -595,25 +595,18 @@ void drawObject(RenderingContext* rc, SkCanvas* cv, RenderingRuleSearchRequest*
|
|||
SkPaint* paint, vector<MapDataObjectPrimitive>& array, int objOrder) {
|
||||
|
||||
double polygonLimit = 100;
|
||||
// int roadsLimit = 500;
|
||||
// float orderToSwitch = 0;
|
||||
float orderToSwitch = 0;
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
rc->allObjects++;
|
||||
MapDataObject* mObj = array[i].obj;
|
||||
tag_value pair = mObj->types.at(array[i].typeInd);
|
||||
if (objOrder == 0) {
|
||||
if (array[i].order < polygonLimit) {
|
||||
if (array[i].order < rc->polygonMinSizeToDisplay) {
|
||||
return;
|
||||
}
|
||||
// polygon
|
||||
drawPolygon(mObj, req, cv, paint, rc, pair);
|
||||
} else if (objOrder == 1 || objOrder == 2) {
|
||||
// if(--roadsLimit == 0) {
|
||||
// orderToSwitch = array[i].order;
|
||||
// } else if(roadsLimit < 0 && orderToSwitch != array[i].order){
|
||||
// // break here
|
||||
// return;
|
||||
// }
|
||||
drawPolyline(mObj, req, cv, paint, rc, pair, mObj->getSimpleLayer(), objOrder == 1);
|
||||
} else if (objOrder == 3) {
|
||||
drawPoint(mObj, req, cv, paint, rc, pair, array[i].typeInd == 0);
|
||||
|
@ -677,9 +670,54 @@ double polygonArea(MapDataObject* obj, float mult) {
|
|||
return std::abs(area) * mult * mult * .5;
|
||||
}
|
||||
|
||||
|
||||
void filterLinesByDensity(RenderingContext* rc, std::vector<MapDataObjectPrimitive>& linesResArray,
|
||||
std::vector<MapDataObjectPrimitive>& linesArray) {
|
||||
int roadsLimit = rc->roadsDensityLimitPerTile;
|
||||
int densityZ = rc->roadDensityZoomTile;
|
||||
if(densityZ == 0 || roadsLimit == 0) {
|
||||
linesResArray = linesArray;
|
||||
return;
|
||||
}
|
||||
linesResArray.reserve(linesArray.size());
|
||||
UNORDERED(map)<int64_t, pair<int, int> > densityMap;
|
||||
for (int i = linesArray.size() - 1; i >= 0; i--) {
|
||||
bool accept = true;
|
||||
int o = linesArray[i].order;
|
||||
MapDataObject* line = linesArray[i].obj;
|
||||
tag_value& ts = line->types[linesArray[i].typeInd];
|
||||
if (ts.first == "highway") {
|
||||
accept = false;
|
||||
int64_t prev = 0;
|
||||
for (int k = 0; k < line->points.size(); k++) {
|
||||
int dz = rc->getZoom() + densityZ;
|
||||
int64_t x = (line->points[k].first) >> (31 - dz);
|
||||
int64_t y = (line->points[k].second) >> (31 - dz);
|
||||
int64_t tl = (x << dz) + y;
|
||||
if (prev != tl) {
|
||||
prev = tl;
|
||||
pair<int, int>& p = densityMap[tl];
|
||||
if (p.first < roadsLimit/* && p.second > o */) {
|
||||
accept = true;
|
||||
p.first++;
|
||||
p.second = o;
|
||||
densityMap[tl] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(accept) {
|
||||
linesResArray.push_back(linesArray[i]);
|
||||
}
|
||||
}
|
||||
reverse(linesResArray.begin(), linesResArray.end());
|
||||
}
|
||||
bool sortByOrder(const MapDataObjectPrimitive& i,const MapDataObjectPrimitive& j) {
|
||||
if( i.order == j.order) return i.typeInd < j.typeInd;
|
||||
if( i.order == j.order) {
|
||||
if(i.typeInd == j.typeInd) {
|
||||
return i.obj->points.size() < j.obj->points.size() ;
|
||||
}
|
||||
return i.typeInd < j.typeInd;
|
||||
}
|
||||
return (i.order<j.order); }
|
||||
bool sortPolygonsOrder(const MapDataObjectPrimitive& i,const MapDataObjectPrimitive& j) {
|
||||
if( i.order == j.order) return i.typeInd < j.typeInd;
|
||||
|
@ -688,8 +726,9 @@ bool sortPolygonsOrder(const MapDataObjectPrimitive& i,const MapDataObjectPrimit
|
|||
void sortObjectsByProperOrder(std::vector <MapDataObject* > mapDataObjects,
|
||||
RenderingRuleSearchRequest* req, RenderingContext* rc,
|
||||
std::vector<MapDataObjectPrimitive>& polygonsArray, std::vector<MapDataObjectPrimitive>& pointsArray,
|
||||
std::vector<MapDataObjectPrimitive>& linesArray) {
|
||||
std::vector<MapDataObjectPrimitive>& linesResArray) {
|
||||
if (req != NULL) {
|
||||
std::vector<MapDataObjectPrimitive> linesArray;
|
||||
req->clearState();
|
||||
const int size = mapDataObjects.size();
|
||||
float mult = 1. / getPowZoom(max(31 - (rc->getZoom() + 8), 0));
|
||||
|
@ -740,6 +779,7 @@ void sortObjectsByProperOrder(std::vector <MapDataObject* > mapDataObjects,
|
|||
sort(polygonsArray.begin(), polygonsArray.end(), sortPolygonsOrder);
|
||||
sort(pointsArray.begin(), pointsArray.end(), sortByOrder);
|
||||
sort(linesArray.begin(), linesArray.end(), sortByOrder);
|
||||
filterLinesByDensity(rc, linesResArray, linesArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue