Introduce concept of adaptive roads

This commit is contained in:
Victor Shcherb 2012-11-13 20:23:29 +01:00
parent 6f220689d4
commit be50369a77
6 changed files with 139 additions and 49 deletions

View file

@ -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];

View file

@ -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"/>

View file

@ -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();

View file

@ -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");

View file

@ -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;
}

View file

@ -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);
}
}