Build simple pc app
This commit is contained in:
parent
76643bfc26
commit
535c517d56
16 changed files with 747 additions and 651 deletions
1
Osmand-kernel/freetype/.gitignore
vendored
Normal file
1
Osmand-kernel/freetype/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build/
|
|
@ -1,18 +1,12 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
include $(LOCAL_PATH)/Common.mk
|
||||
|
||||
# compile in ARM mode, since the glyph loader/renderer is a hotspot
|
||||
# when loading complex pages in the browser
|
||||
#
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
ifeq ($(OSMAND_FREETYPE_LOC),)
|
||||
OSMAND_FREETYPE_LOC := ./freetype_library
|
||||
endif
|
||||
ifeq ($(OSMAND_FREETYPE_ABS),)
|
||||
OSMAND_FREETYPE_ABS := $(LOCAL_PATH)/freetype_library
|
||||
endif
|
||||
|
||||
ifneq ($(OSMAND_BUILDING_NEON_LIBRARY),true)
|
||||
LOCAL_MODULE := ft2_static
|
||||
else
|
||||
|
@ -22,43 +16,6 @@ endif
|
|||
|
||||
ifneq ($(OSMAND_USE_PREBUILT),true)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftbbox.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftbitmap.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftfstype.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftglyph.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftlcdfil.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftstroke.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/fttype1.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftxf86.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftbase.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftsystem.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftinit.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftgasp.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/raster/raster.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/sfnt/sfnt.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/smooth/smooth.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/autofit/autofit.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/truetype/truetype.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/cff/cff.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/psnames/psnames.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/pshinter/pshinter.c
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(OSMAND_FREETYPE_ABS)/builds \
|
||||
$(OSMAND_FREETYPE_ABS)/include
|
||||
|
||||
LOCAL_CFLAGS += -W -Wall
|
||||
LOCAL_CFLAGS += -fPIC -DPIC
|
||||
LOCAL_CFLAGS += "-DDARWIN_NO_CARBON"
|
||||
LOCAL_CFLAGS += "-DFT2_BUILD_LIBRARY"
|
||||
|
||||
# the following is for testing only, and should not be used in final builds
|
||||
# of the product
|
||||
#LOCAL_CFLAGS += "-DTT_CONFIG_OPTION_BYTECODE_INTERPRETER"
|
||||
|
||||
LOCAL_CFLAGS += -O2
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
else
|
||||
|
|
41
Osmand-kernel/freetype/Common.mk
Normal file
41
Osmand-kernel/freetype/Common.mk
Normal file
|
@ -0,0 +1,41 @@
|
|||
OSMAND_FREETYPE_LOC := ./freetype_library
|
||||
|
||||
OSMAND_FREETYPE_ABS := $(LOCAL_PATH)/freetype_library
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftbbox.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftbitmap.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftfstype.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftglyph.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftlcdfil.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftstroke.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/fttype1.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftxf86.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftbase.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftsystem.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftinit.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/base/ftgasp.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/raster/raster.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/sfnt/sfnt.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/smooth/smooth.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/autofit/autofit.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/truetype/truetype.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/cff/cff.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/psnames/psnames.c \
|
||||
$(OSMAND_FREETYPE_LOC)/src/pshinter/pshinter.c
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(OSMAND_FREETYPE_ABS)/builds \
|
||||
$(OSMAND_FREETYPE_ABS)/include
|
||||
|
||||
LOCAL_CFLAGS += -W -Wall
|
||||
LOCAL_CFLAGS += -fPIC -DPIC
|
||||
LOCAL_CFLAGS += "-DDARWIN_NO_CARBON"
|
||||
LOCAL_CFLAGS += "-DFT2_BUILD_LIBRARY"
|
||||
|
||||
# the following is for testing only, and should not be used in final builds
|
||||
# of the product
|
||||
#LOCAL_CFLAGS += "-DTT_CONFIG_OPTION_BYTECODE_INTERPRETER"
|
||||
|
||||
LOCAL_CFLAGS += -O2
|
||||
|
24
Osmand-kernel/freetype/Makefile
Normal file
24
Osmand-kernel/freetype/Makefile
Normal file
|
@ -0,0 +1,24 @@
|
|||
LOCAL_PATH = .
|
||||
include Common.mk
|
||||
|
||||
CPP_FILE_EXTENSION = c
|
||||
LIBNAME := libft2.a
|
||||
PREBUILT_DIR = ../jni-prebuilt/linux-x86/
|
||||
OBJECTS = $(LOCAL_SRC_FILES:%.$(CPP_FILE_EXTENSION)=build/obj/%.o)
|
||||
C_INCLUDES := $(addprefix -I, $(LOCAL_C_INCLUDES))
|
||||
CPPFLAGS = $(LOCAL_CFLAGS) $(C_INCLUDES)
|
||||
|
||||
target : $(PREBUILT_DIR)/$(LIBNAME)
|
||||
|
||||
$(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
||||
cp build/$(LIBNAME) $(PREBUILT_DIR)/$(LIBNAME)
|
||||
|
||||
build/$(LIBNAME): $(OBJECTS)
|
||||
ar -rf build/$(LIBNAME) $(OBJECTS)
|
||||
|
||||
build/obj/%.o : %.$(CPP_FILE_EXTENSION) $(LOCAL_C_INCLUDES)
|
||||
@mkdir -p `dirname $@`
|
||||
$(CXX) -o $@ -c $*.$(CPP_FILE_EXTENSION) $(CPPFLAGS)
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJECTS) build/$(LIBNAME)
|
|
@ -17,6 +17,7 @@ LOCAL_SRC_FILES := \
|
|||
src/osmand_log.cpp \
|
||||
src/common.cpp \
|
||||
src/mapObjects.cpp \
|
||||
src/multipolygons.cpp \
|
||||
src/renderRules.cpp \
|
||||
src/rendering.cpp \
|
||||
src/binaryRead.cpp
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
LOCAL_PATH := .
|
||||
PREBUILT_DIR = ../jni-prebuilt/linux-x86/
|
||||
LIBNAME := osmand.lib
|
||||
include Common.mk
|
||||
RUNFILE := osmand_main
|
||||
include ./Common.mk
|
||||
|
||||
LOCAL_SRC_FILES += src/osmand_main.cpp
|
||||
|
||||
LDFLAGS = -Wl,--hash-style=both -shared
|
||||
LDLIBS = -L$(PREBUILT_DIR) -lskia -lproto
|
||||
LDRUNFLAGS = -Wl,--hash-style=both
|
||||
|
||||
LDLIBS = -L$(PREBUILT_DIR) -lskia -lproto -lpthread -lrt -lft2
|
||||
CPP_FILE_EXTENSION = cpp
|
||||
OBJECTS = $(LOCAL_SRC_FILES:src/%.$(CPP_FILE_EXTENSION)=build/obj/%.o)
|
||||
|
||||
|
@ -18,8 +23,16 @@ CPPFLAGS := \
|
|||
-c -fpic -I$(JAVA_HOME)/include \
|
||||
-DHAVING_HASH \
|
||||
$(C_INCLUDES)
|
||||
|
||||
target : ../$(RUNFILE)
|
||||
#target : $(PREBUILT_DIR)/$(LIBNAME) ../$(RUNFILE)
|
||||
|
||||
$(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
||||
|
||||
../$(RUNFILE) : $(OBJECTS) $(PREBUILT_DIR)/libskia.a $(PREBUILT_DIR)/libproto.a
|
||||
$(CXX) $(LDRUNFLAGS) -o ../$(RUNFILE) $(OBJECTS) $(LDLIBS)
|
||||
@chmod +x ../$(RUNFILE)
|
||||
|
||||
$(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
||||
cp build/$(LIBNAME) $(PREBUILT_DIR)/$(LIBNAME)
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
#ifndef _OSMAND_BINARY_READ
|
||||
#define _OSMAND_BINARY_READ
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <osmand_log.h>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "binaryRead.h"
|
||||
#include "osmand_log.h"
|
||||
#include "google/protobuf/io/zero_copy_stream_impl.h"
|
||||
#include "google/protobuf/wire_format_lite.h"
|
||||
#include "google/protobuf/wire_format_lite.cc"
|
||||
|
@ -18,7 +11,6 @@
|
|||
#include "common.h"
|
||||
#include "mapObjects.h"
|
||||
#include "multipolygons.h"
|
||||
//#include "multipolygons.h"
|
||||
#include "proto/osmand_odb.pb.h"
|
||||
using namespace std;
|
||||
|
||||
|
@ -29,8 +21,6 @@ using namespace google::protobuf::internal;
|
|||
static const int MAP_VERSION = 2;
|
||||
static const int BASEMAP_ZOOM = 11;
|
||||
|
||||
|
||||
|
||||
struct BinaryMapFile;
|
||||
std::map<std::string, BinaryMapFile*> openFiles;
|
||||
|
||||
|
@ -101,106 +91,6 @@ struct SearchQuery {
|
|||
}
|
||||
};
|
||||
|
||||
struct MapTreeBounds {
|
||||
uint32 length;
|
||||
uint32 filePointer;
|
||||
uint32 mapDataBlock;
|
||||
uint32 left ;
|
||||
uint32 right ;
|
||||
uint32 top ;
|
||||
uint32 bottom;
|
||||
bool ocean;
|
||||
|
||||
MapTreeBounds() {
|
||||
ocean = -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct MapRoot: MapTreeBounds {
|
||||
int minZoom ;
|
||||
int maxZoom ;
|
||||
std::vector<MapTreeBounds> bounds;
|
||||
};
|
||||
|
||||
struct MapIndex {
|
||||
uint32 length;
|
||||
int filePointer;
|
||||
std::string name;
|
||||
std::vector<MapRoot> levels;
|
||||
|
||||
HMAP::hash_map<int, tag_value > decodingRules;
|
||||
// DEFINE hash
|
||||
//HMAP::hash_map<tag_value, int> encodingRules;
|
||||
|
||||
int nameEncodingType;
|
||||
int refEncodingType;
|
||||
int coastlineEncodingType;
|
||||
int coastlineBrokenEncodingType;
|
||||
int landEncodingType;
|
||||
int onewayAttribute ;
|
||||
int onewayReverseAttribute ;
|
||||
HMAP::hash_set< int > positiveLayers;
|
||||
HMAP::hash_set< int > negativeLayers;
|
||||
|
||||
MapIndex(){
|
||||
nameEncodingType = refEncodingType = coastlineBrokenEncodingType = coastlineEncodingType = -1;
|
||||
landEncodingType = onewayAttribute = onewayReverseAttribute = -1;
|
||||
}
|
||||
|
||||
void finishInitializingTags() {
|
||||
int free = decodingRules.size() * 2 + 1;
|
||||
coastlineBrokenEncodingType = free++;
|
||||
initMapEncodingRule(0, coastlineBrokenEncodingType, "natural", "coastline_broken");
|
||||
if (landEncodingType == -1) {
|
||||
landEncodingType = free++;
|
||||
initMapEncodingRule(0, landEncodingType, "natural", "land");
|
||||
}
|
||||
}
|
||||
|
||||
void initMapEncodingRule(uint32 type, uint32 id, std::string tag, std::string val) {
|
||||
tag_value pair = tag_value(tag, val);
|
||||
// DEFINE hash
|
||||
//encodingRules[pair] = id;
|
||||
decodingRules[id] = pair;
|
||||
|
||||
if ("name" == tag) {
|
||||
nameEncodingType = id;
|
||||
} else if ("natural" == tag && "coastline" == val) {
|
||||
coastlineEncodingType = id;
|
||||
} else if ("natural" == tag && "land" == val) {
|
||||
landEncodingType = id;
|
||||
} else if ("oneway" == tag && "yes" == val) {
|
||||
onewayAttribute = id;
|
||||
} else if ("oneway" == tag && "-1" == val) {
|
||||
onewayReverseAttribute = id;
|
||||
} else if ("ref" == tag) {
|
||||
refEncodingType = id;
|
||||
} else if ("layer" == tag) {
|
||||
if (val != "" && val != "0") {
|
||||
if (val[0] == '-') {
|
||||
negativeLayers.insert(id);
|
||||
} else {
|
||||
positiveLayers.insert(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BinaryMapFile {
|
||||
std::string inputName;
|
||||
std::vector<MapIndex> mapIndexes;
|
||||
FILE* f;
|
||||
bool basemap;
|
||||
|
||||
bool isBasemap(){
|
||||
return basemap;
|
||||
}
|
||||
|
||||
~BinaryMapFile() {
|
||||
fclose(f);
|
||||
}
|
||||
};
|
||||
|
||||
bool readMapTreeBounds(io::CodedInputStream* input, MapTreeBounds* tree, MapRoot* root) {
|
||||
int init = 0;
|
||||
|
|
123
Osmand-kernel/osmand/src/binaryRead.h
Normal file
123
Osmand-kernel/osmand/src/binaryRead.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
#ifndef _OSMAND_BINARY_READ_H
|
||||
#define _OSMAND_BINARY_READ_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "google/protobuf/wire_format_lite.h"
|
||||
#include "common.h"
|
||||
#include "mapObjects.h"
|
||||
|
||||
|
||||
|
||||
struct MapTreeBounds {
|
||||
uint32 length;
|
||||
uint32 filePointer;
|
||||
uint32 mapDataBlock;
|
||||
uint32 left ;
|
||||
uint32 right ;
|
||||
uint32 top ;
|
||||
uint32 bottom;
|
||||
bool ocean;
|
||||
|
||||
MapTreeBounds() {
|
||||
ocean = -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct MapRoot: MapTreeBounds {
|
||||
int minZoom ;
|
||||
int maxZoom ;
|
||||
std::vector<MapTreeBounds> bounds;
|
||||
};
|
||||
|
||||
|
||||
struct MapIndex {
|
||||
uint32 length;
|
||||
int filePointer;
|
||||
std::string name;
|
||||
std::vector<MapRoot> levels;
|
||||
|
||||
HMAP::hash_map<int, tag_value > decodingRules;
|
||||
// DEFINE hash
|
||||
//HMAP::hash_map<tag_value, int> encodingRules;
|
||||
|
||||
int nameEncodingType;
|
||||
int refEncodingType;
|
||||
int coastlineEncodingType;
|
||||
int coastlineBrokenEncodingType;
|
||||
int landEncodingType;
|
||||
int onewayAttribute ;
|
||||
int onewayReverseAttribute ;
|
||||
HMAP::hash_set< int > positiveLayers;
|
||||
HMAP::hash_set< int > negativeLayers;
|
||||
|
||||
MapIndex(){
|
||||
nameEncodingType = refEncodingType = coastlineBrokenEncodingType = coastlineEncodingType = -1;
|
||||
landEncodingType = onewayAttribute = onewayReverseAttribute = -1;
|
||||
}
|
||||
|
||||
void finishInitializingTags() {
|
||||
int free = decodingRules.size() * 2 + 1;
|
||||
coastlineBrokenEncodingType = free++;
|
||||
initMapEncodingRule(0, coastlineBrokenEncodingType, "natural", "coastline_broken");
|
||||
if (landEncodingType == -1) {
|
||||
landEncodingType = free++;
|
||||
initMapEncodingRule(0, landEncodingType, "natural", "land");
|
||||
}
|
||||
}
|
||||
|
||||
void initMapEncodingRule(uint32 type, uint32 id, std::string tag, std::string val) {
|
||||
tag_value pair = tag_value(tag, val);
|
||||
// DEFINE hash
|
||||
//encodingRules[pair] = id;
|
||||
decodingRules[id] = pair;
|
||||
|
||||
if ("name" == tag) {
|
||||
nameEncodingType = id;
|
||||
} else if ("natural" == tag && "coastline" == val) {
|
||||
coastlineEncodingType = id;
|
||||
} else if ("natural" == tag && "land" == val) {
|
||||
landEncodingType = id;
|
||||
} else if ("oneway" == tag && "yes" == val) {
|
||||
onewayAttribute = id;
|
||||
} else if ("oneway" == tag && "-1" == val) {
|
||||
onewayReverseAttribute = id;
|
||||
} else if ("ref" == tag) {
|
||||
refEncodingType = id;
|
||||
} else if ("layer" == tag) {
|
||||
if (val != "" && val != "0") {
|
||||
if (val[0] == '-') {
|
||||
negativeLayers.insert(id);
|
||||
} else {
|
||||
positiveLayers.insert(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct BinaryMapFile {
|
||||
std::string inputName;
|
||||
std::vector<MapIndex> mapIndexes;
|
||||
FILE* f;
|
||||
bool basemap;
|
||||
|
||||
bool isBasemap(){
|
||||
return basemap;
|
||||
}
|
||||
|
||||
~BinaryMapFile() {
|
||||
fclose(f);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_initBinaryMapFile(JNIEnv* ienv,
|
||||
jobject obj, jobject path);
|
||||
|
||||
|
||||
#endif
|
|
@ -8,6 +8,28 @@
|
|||
#include <hash_map>
|
||||
#include <hash_set>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef __int8 int8;
|
||||
typedef __int16 int16;
|
||||
typedef __int32 int32;
|
||||
typedef __int64 int64;
|
||||
|
||||
typedef unsigned __int8 uint8;
|
||||
typedef unsigned __int16 uint16;
|
||||
typedef unsigned __int32 uint32;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
typedef int64_t int64;
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
#endif
|
||||
|
||||
#ifdef HAVING_HASH
|
||||
|
||||
#define HMAP __gnu_cxx
|
||||
|
|
497
Osmand-kernel/osmand/src/multipolygons.cpp
Normal file
497
Osmand-kernel/osmand/src/multipolygons.cpp
Normal file
|
@ -0,0 +1,497 @@
|
|||
#ifndef _MULTIPOLYGONS_CPP
|
||||
#define _MULTIPOLYGONS_CPP
|
||||
|
||||
#include "multipolygons.h"
|
||||
#include "osmand_log.h"
|
||||
|
||||
void processCoastlines(std::vector<MapDataObject*>& coastLines, int leftX, int rightX, int bottomY, int topY, int zoom,
|
||||
bool showIncompleted, std::vector<MapDataObject*>& res) {
|
||||
std::vector<coordinates> completedRings;
|
||||
std::vector<coordinates > uncompletedRings;
|
||||
std::vector<MapDataObject*>::iterator val = coastLines.begin();
|
||||
res.reserve(coastLines.size());
|
||||
long long dbId = 0;
|
||||
for (; val != coastLines.end(); val++) {
|
||||
MapDataObject* o = *val;
|
||||
int len = o->points.size();
|
||||
if (len < 2) {
|
||||
continue;
|
||||
}
|
||||
dbId = o->id >> 1;
|
||||
coordinates* cs = new coordinates();
|
||||
int px = o->points.at(0).first;
|
||||
int py = o->points.at(0).second;
|
||||
int x = px;
|
||||
int y = py;
|
||||
bool pinside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
|
||||
if (pinside) {
|
||||
cs->push_back(int_pair(x, y));
|
||||
}
|
||||
for (int i = 1; i < len; i++) {
|
||||
x = o->points.at(i).first;
|
||||
y = o->points.at(i).second;
|
||||
bool inside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
|
||||
bool lineEnded = calculateLineCoordinates(inside, x, y, pinside, px, py, leftX, rightX, bottomY, topY, *cs);
|
||||
if (lineEnded) {
|
||||
combineMultipolygonLine(completedRings, uncompletedRings, *cs);
|
||||
// create new line if it goes outside
|
||||
cs = new coordinates();
|
||||
}
|
||||
px = x;
|
||||
py = y;
|
||||
pinside = inside;
|
||||
}
|
||||
combineMultipolygonLine(completedRings, uncompletedRings, *cs);
|
||||
}
|
||||
if (completedRings.size() == 0 && uncompletedRings.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (uncompletedRings.size() > 0) {
|
||||
unifyIncompletedRings(uncompletedRings, completedRings, leftX, rightX, bottomY, topY, dbId, zoom);
|
||||
}
|
||||
if (!showIncompleted && uncompletedRings.size() > 0) {
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
bool clockwiseFound = false;
|
||||
for (int i = 0; i < completedRings.size(); i++) {
|
||||
bool clockwise = isClockwiseWay(completedRings[i]);
|
||||
clockwiseFound = clockwiseFound || clockwise;
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points = completedRings[i];
|
||||
if (clockwise) {
|
||||
o->types.push_back(tag_value("natural", "coastline"));
|
||||
} else {
|
||||
o->types.push_back(tag_value("natural", "land"));
|
||||
}
|
||||
o->id = dbId;
|
||||
o->area = true;
|
||||
res.push_back(o);
|
||||
}
|
||||
|
||||
// draw uncompleted for debug purpose
|
||||
for (int i = 0; i < uncompletedRings.size(); i++) {
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points = uncompletedRings[i];
|
||||
o->types.push_back(tag_value("natural", "coastline_broken"));
|
||||
//res.push_back(o);
|
||||
}
|
||||
if (!clockwiseFound && uncompletedRings.size() == 0) {
|
||||
// add complete water tile
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points.push_back(int_pair(leftX, topY));
|
||||
o->points.push_back(int_pair(rightX, topY));
|
||||
o->points.push_back(int_pair(rightX, bottomY));
|
||||
o->points.push_back(int_pair(leftX, bottomY));
|
||||
o->points.push_back(int_pair(leftX, topY));
|
||||
o->id = dbId;
|
||||
o->types.push_back(tag_value("natural", "coastline"));
|
||||
osmand_log_print(LOG_ERROR, "!!! Isolated islands !!!");
|
||||
res.push_back(o);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from MapAlgorithms
|
||||
int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) {
|
||||
// prev node above line
|
||||
// x,y node below line
|
||||
if (prevY > y) {
|
||||
int tx = x;
|
||||
int ty = y;
|
||||
x = prevX;
|
||||
y = prevY;
|
||||
prevX = tx;
|
||||
prevY = ty;
|
||||
}
|
||||
if (y == middleY || prevY == middleY) {
|
||||
middleY -= 1;
|
||||
}
|
||||
if (prevY > middleY || y < middleY) {
|
||||
return INT_MIN;
|
||||
} else {
|
||||
if (y == prevY) {
|
||||
// the node on the boundary !!!
|
||||
return x;
|
||||
}
|
||||
// that tested on all cases (left/right)
|
||||
double rx = x + ((double) middleY - y) * ((double) x - prevX) / (((double) y - prevY));
|
||||
return (int) rx;
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from MapAlgorithms
|
||||
bool isClockwiseWay(std::vector<int_pair>& c) {
|
||||
if (c.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// calculate middle Y
|
||||
long long middleY = 0;
|
||||
for (size_t i = 0; i < c.size(); i++) {
|
||||
middleY += c.at(i).second;
|
||||
}
|
||||
middleY /= (long long) c.size();
|
||||
|
||||
double clockwiseSum = 0;
|
||||
|
||||
bool firstDirectionUp = false;
|
||||
int previousX = INT_MIN;
|
||||
int firstX = INT_MIN;
|
||||
|
||||
int prevX = c.at(0).first;
|
||||
int prevY = c.at(0).second;
|
||||
|
||||
for (size_t i = 1; i < c.size(); i++) {
|
||||
int x = c.at(i).first;
|
||||
int y = c.at(i).second;
|
||||
int rX = ray_intersect_x(prevX, prevY, x, y, (int) middleY);
|
||||
if (rX != INT_MIN) {
|
||||
bool skipSameSide = (y <= middleY) == (prevY <= middleY);
|
||||
if (skipSameSide) {
|
||||
continue;
|
||||
}
|
||||
bool directionUp = prevY >= middleY;
|
||||
if (firstX == INT_MIN) {
|
||||
firstDirectionUp = directionUp;
|
||||
firstX = rX;
|
||||
} else {
|
||||
bool clockwise = (!directionUp) == (previousX < rX);
|
||||
if (clockwise) {
|
||||
clockwiseSum += abs(previousX - rX);
|
||||
} else {
|
||||
clockwiseSum -= abs(previousX - rX);
|
||||
}
|
||||
}
|
||||
previousX = rX;
|
||||
}
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
if (firstX != INT_MIN) {
|
||||
bool clockwise = (!firstDirectionUp) == (previousX < firstX);
|
||||
if (clockwise) {
|
||||
clockwiseSum += abs(previousX - firstX);
|
||||
} else {
|
||||
clockwiseSum -= abs(previousX - firstX);
|
||||
}
|
||||
}
|
||||
|
||||
return clockwiseSum >= 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void combineMultipolygonLine(std::vector<coordinates>& completedRings, std::vector<coordinates>& incompletedRings,
|
||||
coordinates& coordinates) {
|
||||
if (coordinates.size() > 0) {
|
||||
if (coordinates.at(0) == coordinates.at(coordinates.size() - 1)) {
|
||||
completedRings.push_back(coordinates);
|
||||
} else {
|
||||
bool add = true;
|
||||
for (size_t k = 0; k < incompletedRings.size();) {
|
||||
bool remove = false;
|
||||
std::vector<int_pair> i = incompletedRings.at(k);
|
||||
if (coordinates.at(0) == i.at(i.size() - 1)) {
|
||||
std::vector<int_pair>::iterator tit = coordinates.begin();
|
||||
i.insert(i.end(), ++tit, coordinates.end());
|
||||
remove = true;
|
||||
coordinates = i;
|
||||
} else if (coordinates.at(coordinates.size() - 1) == i.at(0)) {
|
||||
std::vector<int_pair>::iterator tit = i.begin();
|
||||
coordinates.insert(coordinates.end(), ++tit, i.end());
|
||||
remove = true;
|
||||
}
|
||||
if (remove) {
|
||||
std::vector<std::vector<int_pair> >::iterator ti = incompletedRings.begin();
|
||||
ti += k;
|
||||
incompletedRings.erase(ti);
|
||||
} else {
|
||||
k++;
|
||||
}
|
||||
if (coordinates.at(0) == coordinates.at(coordinates.size() - 1)) {
|
||||
completedRings.push_back(coordinates);
|
||||
add = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
incompletedRings.push_back(coordinates);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int safelyAddDelta(int number, int delta) {
|
||||
int res = number + delta;
|
||||
if (delta > 0 && res < number) {
|
||||
return INT_MAX;
|
||||
} else if (delta < 0 && res > number) {
|
||||
return INT_MIN;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void unifyIncompletedRings(std::vector<std::vector<int_pair> >& toProccess, std::vector<std::vector<int_pair> >& completedRings,
|
||||
int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
|
||||
std::set<int> nonvisitedRings;
|
||||
std::vector<coordinates > incompletedRings(toProccess);
|
||||
toProccess.clear();
|
||||
std::vector<coordinates >::iterator ir = incompletedRings.begin();
|
||||
int j = 0;
|
||||
for (j = 0; ir != incompletedRings.end(); ir++,j++) {
|
||||
int x = ir->at(0).first;
|
||||
int y = ir->at(0).second;
|
||||
int sx = ir->at(ir->size() - 1).first;
|
||||
int sy = ir->at(ir->size() - 1).second;
|
||||
bool st = y == topY || x == rightX || y == bottomY || x == leftX;
|
||||
bool end = sy == topY || sx == rightX || sy == bottomY || sx == leftX;
|
||||
// something goes wrong
|
||||
// These exceptions are used to check logic about processing multipolygons
|
||||
// However this situation could happen because of broken multipolygons (so it should data causes app error)
|
||||
// that's why these exceptions could be replaced with return; statement.
|
||||
if (!end || !st) {
|
||||
osmand_log_print(LOG_ERROR, "Error processing multipolygon");
|
||||
toProccess.push_back(*ir);
|
||||
} else {
|
||||
nonvisitedRings.insert(j);
|
||||
}
|
||||
}
|
||||
ir = incompletedRings.begin();
|
||||
for (j = 0; ir != incompletedRings.end(); ir++, j++) {
|
||||
if (nonvisitedRings.find(j) == nonvisitedRings.end()) {
|
||||
continue;
|
||||
}
|
||||
int x = ir->at(ir->size() - 1).first;
|
||||
int y = ir->at(ir->size() - 1).second;
|
||||
// 31 - (zoom + 8)
|
||||
const int EVAL_DELTA = 6 << (23 - zoom);
|
||||
const int UNDEFINED_MIN_DIFF = -1 - EVAL_DELTA;
|
||||
while (true) {
|
||||
int st = 0; // st already checked to be one of the four
|
||||
if (y == topY) {
|
||||
st = 0;
|
||||
} else if (x == rightX) {
|
||||
st = 1;
|
||||
} else if (y == bottomY) {
|
||||
st = 2;
|
||||
} else if (x == leftX) {
|
||||
st = 3;
|
||||
}
|
||||
int nextRingIndex = -1;
|
||||
// BEGIN go clockwise around rectangle
|
||||
for (int h = st; h < st + 4; h++) {
|
||||
|
||||
// BEGIN find closest nonvisited start (including current)
|
||||
int mindiff = UNDEFINED_MIN_DIFF;
|
||||
std::vector<std::vector<int_pair> >::iterator cni = incompletedRings.begin();
|
||||
int cnik = 0;
|
||||
for (;cni != incompletedRings.end(); cni++, cnik ++) {
|
||||
if (nonvisitedRings.find(cnik) == nonvisitedRings.end()) {
|
||||
continue;
|
||||
}
|
||||
int csx = cni->at(0).first;
|
||||
int csy = cni->at(0).second;
|
||||
if (h % 4 == 0) {
|
||||
// top
|
||||
if (csy == topY && csx >= safelyAddDelta(x, -EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (csx - x) <= mindiff) {
|
||||
mindiff = (csx - x);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
} else if (h % 4 == 1) {
|
||||
// right
|
||||
if (csx == rightX && csy >= safelyAddDelta(y, -EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (csy - y) <= mindiff) {
|
||||
mindiff = (csy - y);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
} else if (h % 4 == 2) {
|
||||
// bottom
|
||||
if (csy == bottomY && csx <= safelyAddDelta(x, EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (x - csx) <= mindiff) {
|
||||
mindiff = (x - csx);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
} else if (h % 4 == 3) {
|
||||
// left
|
||||
if (csx == leftX && csy <= safelyAddDelta(y, EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (y - csy) <= mindiff) {
|
||||
mindiff = (y - csy);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // END find closest start (including current)
|
||||
|
||||
// we found start point
|
||||
if (mindiff != UNDEFINED_MIN_DIFF) {
|
||||
break;
|
||||
} else {
|
||||
if (h % 4 == 0) {
|
||||
// top
|
||||
y = topY;
|
||||
x = rightX;
|
||||
} else if (h % 4 == 1) {
|
||||
// right
|
||||
y = bottomY;
|
||||
x = rightX;
|
||||
} else if (h % 4 == 2) {
|
||||
// bottom
|
||||
y = bottomY;
|
||||
x = leftX;
|
||||
} else if (h % 4 == 3) {
|
||||
y = topY;
|
||||
x = leftX;
|
||||
}
|
||||
ir->push_back(int_pair(x, y));
|
||||
}
|
||||
|
||||
} // END go clockwise around rectangle
|
||||
if (nextRingIndex == -1) {
|
||||
// it is impossible (current start should always be found)
|
||||
} else if (nextRingIndex == j) {
|
||||
ir->push_back(ir->at(0));
|
||||
nonvisitedRings.erase(j);
|
||||
break;
|
||||
} else {
|
||||
std::vector<int_pair> p = incompletedRings.at(nextRingIndex);
|
||||
ir->insert(ir->end(), p.begin(), p.end());
|
||||
nonvisitedRings.erase(nextRingIndex);
|
||||
// get last point and start again going clockwise
|
||||
x = ir->at(ir->size() - 1).first;
|
||||
y = ir->at(ir->size() - 1).second;
|
||||
}
|
||||
}
|
||||
|
||||
completedRings.push_back(*ir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return -1 if there is no instersection or x<<32 | y
|
||||
*/
|
||||
bool calculateIntersection(int x, int y, int px, int py, int leftX, int rightX, int bottomY, int topY, int_pair& b) {
|
||||
// firstly try to search if the line goes in
|
||||
if (py < topY && y >= topY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (topY - py)) / (y - py));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = topY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (py > bottomY && y <= bottomY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (py - bottomY)) / (py - y));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = bottomY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (px < leftX && x >= leftX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (leftX - px)) / (x - px));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = leftX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (px > rightX && x <= rightX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (px - rightX)) / (px - x));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = rightX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// try to search if point goes out
|
||||
if (py > topY && y <= topY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (topY - py)) / (y - py));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = topY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (py < bottomY && y >= bottomY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (py - bottomY)) / (py - y));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = bottomY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (px > leftX && x <= leftX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (leftX - px)) / (x - px));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = leftX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (px < rightX && x >= rightX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (px - rightX)) / (px - x));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = rightX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (px == rightX || px == leftX || py == topY || py == bottomY) {
|
||||
b.first = px;
|
||||
b.second = py;
|
||||
// return true;
|
||||
// Is it right? to not return anything?
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool calculateLineCoordinates(bool inside, int x, int y, bool pinside, int px, int py, int leftX, int rightX,
|
||||
int bottomY, int topY, std::vector<int_pair>& coordinates) {
|
||||
bool lineEnded = false;
|
||||
int_pair b(x, y);
|
||||
if (pinside) {
|
||||
if (!inside) {
|
||||
bool is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY, b);
|
||||
if (!is) {
|
||||
b.first = px;
|
||||
b.second = py;
|
||||
}
|
||||
coordinates.push_back(b);
|
||||
lineEnded = true;
|
||||
} else {
|
||||
coordinates.push_back(b);
|
||||
}
|
||||
} else {
|
||||
bool is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY, b);
|
||||
if (inside) {
|
||||
// assert is != -1;
|
||||
coordinates.push_back(b);
|
||||
int_pair n(x, y);
|
||||
coordinates.push_back(n);
|
||||
} else if (is) {
|
||||
coordinates.push_back(b);
|
||||
calculateIntersection(x, y, b.first, b.second, leftX, rightX, bottomY, topY, b);
|
||||
coordinates.push_back(b);
|
||||
lineEnded = true;
|
||||
}
|
||||
}
|
||||
|
||||
return lineEnded;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,3 +1,5 @@
|
|||
#ifndef _MULTIPOLYGONS_H
|
||||
#define _MULTIPOLYGONS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
|
@ -9,6 +11,7 @@
|
|||
|
||||
/// !!! Fuly copied from MapRenderRepositories.java, should be carefully synchroinized
|
||||
bool isClockwiseWay(std::vector<int_pair>& c) ;
|
||||
|
||||
bool calculateLineCoordinates(bool inside, int x, int y, bool pinside, int px, int py, int leftX, int rightX,
|
||||
int bottomY, int topY, std::vector<int_pair>& coordinates);
|
||||
|
||||
|
@ -20,491 +23,6 @@ void unifyIncompletedRings(std::vector<std::vector<int_pair> >& incompletedRings
|
|||
|
||||
|
||||
void processCoastlines(std::vector<MapDataObject*>& coastLines, int leftX, int rightX, int bottomY, int topY, int zoom,
|
||||
bool showIncompleted, std::vector<MapDataObject*>& res) {
|
||||
std::vector<coordinates> completedRings;
|
||||
std::vector<coordinates > uncompletedRings;
|
||||
std::vector<MapDataObject*>::iterator val = coastLines.begin();
|
||||
res.reserve(coastLines.size());
|
||||
long long dbId = 0;
|
||||
for (; val != coastLines.end(); val++) {
|
||||
MapDataObject* o = *val;
|
||||
int len = o->points.size();
|
||||
if (len < 2) {
|
||||
continue;
|
||||
}
|
||||
dbId = o->id >> 1;
|
||||
coordinates* cs = new coordinates();
|
||||
int px = o->points.at(0).first;
|
||||
int py = o->points.at(0).second;
|
||||
int x = px;
|
||||
int y = py;
|
||||
bool pinside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
|
||||
if (pinside) {
|
||||
cs->push_back(int_pair(x, y));
|
||||
}
|
||||
for (int i = 1; i < len; i++) {
|
||||
x = o->points.at(i).first;
|
||||
y = o->points.at(i).second;
|
||||
bool inside = leftX <= x && x <= rightX && y >= topY && y <= bottomY;
|
||||
bool lineEnded = calculateLineCoordinates(inside, x, y, pinside, px, py, leftX, rightX, bottomY, topY, *cs);
|
||||
if (lineEnded) {
|
||||
combineMultipolygonLine(completedRings, uncompletedRings, *cs);
|
||||
// create new line if it goes outside
|
||||
cs = new coordinates();
|
||||
}
|
||||
px = x;
|
||||
py = y;
|
||||
pinside = inside;
|
||||
}
|
||||
combineMultipolygonLine(completedRings, uncompletedRings, *cs);
|
||||
}
|
||||
if (completedRings.size() == 0 && uncompletedRings.size() == 0) {
|
||||
return;
|
||||
}
|
||||
if (uncompletedRings.size() > 0) {
|
||||
unifyIncompletedRings(uncompletedRings, completedRings, leftX, rightX, bottomY, topY, dbId, zoom);
|
||||
}
|
||||
if (!showIncompleted && uncompletedRings.size() > 0) {
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
bool clockwiseFound = false;
|
||||
for (int i = 0; i < completedRings.size(); i++) {
|
||||
bool clockwise = isClockwiseWay(completedRings[i]);
|
||||
clockwiseFound = clockwiseFound || clockwise;
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points = completedRings[i];
|
||||
if (clockwise) {
|
||||
o->types.push_back(tag_value("natural", "coastline"));
|
||||
} else {
|
||||
o->types.push_back(tag_value("natural", "land"));
|
||||
}
|
||||
o->id = dbId;
|
||||
o->area = true;
|
||||
res.push_back(o);
|
||||
}
|
||||
bool showIncompleted, std::vector<MapDataObject*>& res);
|
||||
|
||||
// draw uncompleted for debug purpose
|
||||
for (int i = 0; i < uncompletedRings.size(); i++) {
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points = uncompletedRings[i];
|
||||
o->types.push_back(tag_value("natural", "coastline_broken"));
|
||||
//res.push_back(o);
|
||||
}
|
||||
if (!clockwiseFound && uncompletedRings.size() == 0) {
|
||||
// add complete water tile
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points.push_back(int_pair(leftX, topY));
|
||||
o->points.push_back(int_pair(rightX, topY));
|
||||
o->points.push_back(int_pair(rightX, bottomY));
|
||||
o->points.push_back(int_pair(leftX, bottomY));
|
||||
o->points.push_back(int_pair(leftX, topY));
|
||||
o->id = dbId;
|
||||
o->types.push_back(tag_value("natural", "coastline"));
|
||||
osmand_log_print(LOG_ERROR, "!!! Isolated islands !!!");
|
||||
res.push_back(o);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from MapAlgorithms
|
||||
int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) {
|
||||
// prev node above line
|
||||
// x,y node below line
|
||||
if (prevY > y) {
|
||||
int tx = x;
|
||||
int ty = y;
|
||||
x = prevX;
|
||||
y = prevY;
|
||||
prevX = tx;
|
||||
prevY = ty;
|
||||
}
|
||||
if (y == middleY || prevY == middleY) {
|
||||
middleY -= 1;
|
||||
}
|
||||
if (prevY > middleY || y < middleY) {
|
||||
return INT_MIN;
|
||||
} else {
|
||||
if (y == prevY) {
|
||||
// the node on the boundary !!!
|
||||
return x;
|
||||
}
|
||||
// that tested on all cases (left/right)
|
||||
double rx = x + ((double) middleY - y) * ((double) x - prevX) / (((double) y - prevY));
|
||||
return (int) rx;
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from MapAlgorithms
|
||||
bool isClockwiseWay(std::vector<int_pair>& c) {
|
||||
if (c.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// calculate middle Y
|
||||
long long middleY = 0;
|
||||
for (size_t i = 0; i < c.size(); i++) {
|
||||
middleY += c.at(i).second;
|
||||
}
|
||||
middleY /= (long long) c.size();
|
||||
|
||||
double clockwiseSum = 0;
|
||||
|
||||
bool firstDirectionUp = false;
|
||||
int previousX = INT_MIN;
|
||||
int firstX = INT_MIN;
|
||||
|
||||
int prevX = c.at(0).first;
|
||||
int prevY = c.at(0).second;
|
||||
|
||||
for (size_t i = 1; i < c.size(); i++) {
|
||||
int x = c.at(i).first;
|
||||
int y = c.at(i).second;
|
||||
int rX = ray_intersect_x(prevX, prevY, x, y, (int) middleY);
|
||||
if (rX != INT_MIN) {
|
||||
bool skipSameSide = (y <= middleY) == (prevY <= middleY);
|
||||
if (skipSameSide) {
|
||||
continue;
|
||||
}
|
||||
bool directionUp = prevY >= middleY;
|
||||
if (firstX == INT_MIN) {
|
||||
firstDirectionUp = directionUp;
|
||||
firstX = rX;
|
||||
} else {
|
||||
bool clockwise = (!directionUp) == (previousX < rX);
|
||||
if (clockwise) {
|
||||
clockwiseSum += abs(previousX - rX);
|
||||
} else {
|
||||
clockwiseSum -= abs(previousX - rX);
|
||||
}
|
||||
}
|
||||
previousX = rX;
|
||||
}
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
if (firstX != INT_MIN) {
|
||||
bool clockwise = (!firstDirectionUp) == (previousX < firstX);
|
||||
if (clockwise) {
|
||||
clockwiseSum += abs(previousX - firstX);
|
||||
} else {
|
||||
clockwiseSum -= abs(previousX - firstX);
|
||||
}
|
||||
}
|
||||
|
||||
return clockwiseSum >= 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void combineMultipolygonLine(std::vector<coordinates>& completedRings, std::vector<coordinates>& incompletedRings,
|
||||
coordinates& coordinates) {
|
||||
if (coordinates.size() > 0) {
|
||||
if (coordinates.at(0) == coordinates.at(coordinates.size() - 1)) {
|
||||
completedRings.push_back(coordinates);
|
||||
} else {
|
||||
bool add = true;
|
||||
for (size_t k = 0; k < incompletedRings.size();) {
|
||||
bool remove = false;
|
||||
std::vector<int_pair> i = incompletedRings.at(k);
|
||||
if (coordinates.at(0) == i.at(i.size() - 1)) {
|
||||
std::vector<int_pair>::iterator tit = coordinates.begin();
|
||||
i.insert(i.end(), ++tit, coordinates.end());
|
||||
remove = true;
|
||||
coordinates = i;
|
||||
} else if (coordinates.at(coordinates.size() - 1) == i.at(0)) {
|
||||
std::vector<int_pair>::iterator tit = i.begin();
|
||||
coordinates.insert(coordinates.end(), ++tit, i.end());
|
||||
remove = true;
|
||||
}
|
||||
if (remove) {
|
||||
std::vector<std::vector<int_pair> >::iterator ti = incompletedRings.begin();
|
||||
ti += k;
|
||||
incompletedRings.erase(ti);
|
||||
} else {
|
||||
k++;
|
||||
}
|
||||
if (coordinates.at(0) == coordinates.at(coordinates.size() - 1)) {
|
||||
completedRings.push_back(coordinates);
|
||||
add = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
incompletedRings.push_back(coordinates);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int safelyAddDelta(int number, int delta) {
|
||||
int res = number + delta;
|
||||
if (delta > 0 && res < number) {
|
||||
return INT_MAX;
|
||||
} else if (delta < 0 && res > number) {
|
||||
return INT_MIN;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void unifyIncompletedRings(std::vector<std::vector<int_pair> >& toProccess, std::vector<std::vector<int_pair> >& completedRings,
|
||||
int leftX, int rightX, int bottomY, int topY, long dbId, int zoom) {
|
||||
std::set<int> nonvisitedRings;
|
||||
std::vector<coordinates > incompletedRings(toProccess);
|
||||
toProccess.clear();
|
||||
std::vector<coordinates >::iterator ir = incompletedRings.begin();
|
||||
int j = 0;
|
||||
for (j = 0; ir != incompletedRings.end(); ir++,j++) {
|
||||
int x = ir->at(0).first;
|
||||
int y = ir->at(0).second;
|
||||
int sx = ir->at(ir->size() - 1).first;
|
||||
int sy = ir->at(ir->size() - 1).second;
|
||||
bool st = y == topY || x == rightX || y == bottomY || x == leftX;
|
||||
bool end = sy == topY || sx == rightX || sy == bottomY || sx == leftX;
|
||||
// something goes wrong
|
||||
// These exceptions are used to check logic about processing multipolygons
|
||||
// However this situation could happen because of broken multipolygons (so it should data causes app error)
|
||||
// that's why these exceptions could be replaced with return; statement.
|
||||
if (!end || !st) {
|
||||
osmand_log_print(LOG_ERROR, "Error processing multipolygon");
|
||||
toProccess.push_back(*ir);
|
||||
} else {
|
||||
nonvisitedRings.insert(j);
|
||||
}
|
||||
}
|
||||
ir = incompletedRings.begin();
|
||||
for (j = 0; ir != incompletedRings.end(); ir++, j++) {
|
||||
if (nonvisitedRings.find(j) == nonvisitedRings.end()) {
|
||||
continue;
|
||||
}
|
||||
int x = ir->at(ir->size() - 1).first;
|
||||
int y = ir->at(ir->size() - 1).second;
|
||||
// 31 - (zoom + 8)
|
||||
const int EVAL_DELTA = 6 << (23 - zoom);
|
||||
const int UNDEFINED_MIN_DIFF = -1 - EVAL_DELTA;
|
||||
while (true) {
|
||||
int st = 0; // st already checked to be one of the four
|
||||
if (y == topY) {
|
||||
st = 0;
|
||||
} else if (x == rightX) {
|
||||
st = 1;
|
||||
} else if (y == bottomY) {
|
||||
st = 2;
|
||||
} else if (x == leftX) {
|
||||
st = 3;
|
||||
}
|
||||
int nextRingIndex = -1;
|
||||
// BEGIN go clockwise around rectangle
|
||||
for (int h = st; h < st + 4; h++) {
|
||||
|
||||
// BEGIN find closest nonvisited start (including current)
|
||||
int mindiff = UNDEFINED_MIN_DIFF;
|
||||
std::vector<std::vector<int_pair> >::iterator cni = incompletedRings.begin();
|
||||
int cnik = 0;
|
||||
for (;cni != incompletedRings.end(); cni++, cnik ++) {
|
||||
if (nonvisitedRings.find(cnik) == nonvisitedRings.end()) {
|
||||
continue;
|
||||
}
|
||||
int csx = cni->at(0).first;
|
||||
int csy = cni->at(0).second;
|
||||
if (h % 4 == 0) {
|
||||
// top
|
||||
if (csy == topY && csx >= safelyAddDelta(x, -EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (csx - x) <= mindiff) {
|
||||
mindiff = (csx - x);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
} else if (h % 4 == 1) {
|
||||
// right
|
||||
if (csx == rightX && csy >= safelyAddDelta(y, -EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (csy - y) <= mindiff) {
|
||||
mindiff = (csy - y);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
} else if (h % 4 == 2) {
|
||||
// bottom
|
||||
if (csy == bottomY && csx <= safelyAddDelta(x, EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (x - csx) <= mindiff) {
|
||||
mindiff = (x - csx);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
} else if (h % 4 == 3) {
|
||||
// left
|
||||
if (csx == leftX && csy <= safelyAddDelta(y, EVAL_DELTA)) {
|
||||
if (mindiff == UNDEFINED_MIN_DIFF || (y - csy) <= mindiff) {
|
||||
mindiff = (y - csy);
|
||||
nextRingIndex = cnik;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // END find closest start (including current)
|
||||
|
||||
// we found start point
|
||||
if (mindiff != UNDEFINED_MIN_DIFF) {
|
||||
break;
|
||||
} else {
|
||||
if (h % 4 == 0) {
|
||||
// top
|
||||
y = topY;
|
||||
x = rightX;
|
||||
} else if (h % 4 == 1) {
|
||||
// right
|
||||
y = bottomY;
|
||||
x = rightX;
|
||||
} else if (h % 4 == 2) {
|
||||
// bottom
|
||||
y = bottomY;
|
||||
x = leftX;
|
||||
} else if (h % 4 == 3) {
|
||||
y = topY;
|
||||
x = leftX;
|
||||
}
|
||||
ir->push_back(int_pair(x, y));
|
||||
}
|
||||
|
||||
} // END go clockwise around rectangle
|
||||
if (nextRingIndex == -1) {
|
||||
// it is impossible (current start should always be found)
|
||||
} else if (nextRingIndex == j) {
|
||||
ir->push_back(ir->at(0));
|
||||
nonvisitedRings.erase(j);
|
||||
break;
|
||||
} else {
|
||||
std::vector<int_pair> p = incompletedRings.at(nextRingIndex);
|
||||
ir->insert(ir->end(), p.begin(), p.end());
|
||||
nonvisitedRings.erase(nextRingIndex);
|
||||
// get last point and start again going clockwise
|
||||
x = ir->at(ir->size() - 1).first;
|
||||
y = ir->at(ir->size() - 1).second;
|
||||
}
|
||||
}
|
||||
|
||||
completedRings.push_back(*ir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return -1 if there is no instersection or x<<32 | y
|
||||
*/
|
||||
bool calculateIntersection(int x, int y, int px, int py, int leftX, int rightX, int bottomY, int topY, int_pair& b) {
|
||||
// firstly try to search if the line goes in
|
||||
if (py < topY && y >= topY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (topY - py)) / (y - py));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = topY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (py > bottomY && y <= bottomY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (py - bottomY)) / (py - y));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = bottomY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (px < leftX && x >= leftX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (leftX - px)) / (x - px));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = leftX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (px > rightX && x <= rightX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (px - rightX)) / (px - x));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = rightX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// try to search if point goes out
|
||||
if (py > topY && y <= topY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (topY - py)) / (y - py));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = topY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (py < bottomY && y >= bottomY) {
|
||||
int tx = (int) (px + ((double) (x - px) * (py - bottomY)) / (py - y));
|
||||
if (leftX <= tx && tx <= rightX) {
|
||||
b.first = tx;
|
||||
b.second = bottomY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (px > leftX && x <= leftX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (leftX - px)) / (x - px));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = leftX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (px < rightX && x >= rightX) {
|
||||
int ty = (int) (py + ((double) (y - py) * (px - rightX)) / (px - x));
|
||||
if (ty >= topY && ty <= bottomY) {
|
||||
b.first = rightX;
|
||||
b.second = ty;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (px == rightX || px == leftX || py == topY || py == bottomY) {
|
||||
b.first = px;
|
||||
b.second = py;
|
||||
// return true;
|
||||
// Is it right? to not return anything?
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool calculateLineCoordinates(bool inside, int x, int y, bool pinside, int px, int py, int leftX, int rightX,
|
||||
int bottomY, int topY, std::vector<int_pair>& coordinates) {
|
||||
bool lineEnded = false;
|
||||
int_pair b(x, y);
|
||||
if (pinside) {
|
||||
if (!inside) {
|
||||
bool is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY, b);
|
||||
if (!is) {
|
||||
b.first = px;
|
||||
b.second = py;
|
||||
}
|
||||
coordinates.push_back(b);
|
||||
lineEnded = true;
|
||||
} else {
|
||||
coordinates.push_back(b);
|
||||
}
|
||||
} else {
|
||||
bool is = calculateIntersection(x, y, px, py, leftX, rightX, bottomY, topY, b);
|
||||
if (inside) {
|
||||
// assert is != -1;
|
||||
coordinates.push_back(b);
|
||||
int_pair n(x, y);
|
||||
coordinates.push_back(n);
|
||||
} else if (is) {
|
||||
coordinates.push_back(b);
|
||||
calculateIntersection(x, y, b.first, b.second, leftX, rightX, bottomY, topY, b);
|
||||
coordinates.push_back(b);
|
||||
lineEnded = true;
|
||||
}
|
||||
}
|
||||
|
||||
return lineEnded;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,7 +25,7 @@ void osmand_log_print(int type, const char* msg, ...) {
|
|||
va_list args;
|
||||
va_start( args, msg);
|
||||
// TODO by type
|
||||
printf(msg, msg, args);
|
||||
printf(msg, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
6
Osmand-kernel/osmand/src/osmand_main.cpp
Normal file
6
Osmand-kernel/osmand/src/osmand_main.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "binaryRead.h"
|
||||
|
||||
int main() {
|
||||
|
||||
printf("Hello world \n");
|
||||
}
|
BIN
Osmand-kernel/osmand_main
Executable file
BIN
Osmand-kernel/osmand_main
Executable file
Binary file not shown.
|
@ -1,7 +1,9 @@
|
|||
include Common.mk
|
||||
|
||||
CPP_FILE_EXTENSION = cpp
|
||||
LIBNAME := libproto.a
|
||||
PREBUILT_DIR = ../jni-prebuilt/linux-x86/
|
||||
OBJECTS = $(LOCAL_SRC_FILES:%.cc=build/obj/%.o)
|
||||
OBJECTS = $(LOCAL_SRC_FILES:%.$(CPP_FILE_EXTENSION)=build/obj/%.o)
|
||||
CPPFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI -I.
|
||||
LDLIBS = -lpthread
|
||||
|
||||
|
@ -13,9 +15,9 @@ $(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
|||
build/$(LIBNAME): $(OBJECTS)
|
||||
ar -rf build/$(LIBNAME) $(OBJECTS)
|
||||
|
||||
build/obj/%.o :
|
||||
build/obj/%.o : %.$(CPP_FILE_EXTENSION) $(LOCAL_C_INCLUDES)
|
||||
@mkdir -p `dirname $@`
|
||||
$(CXX) -o $@ -c $*.cc $(CPPFLAGS)
|
||||
$(CXX) -o $@ -c $*.$(CPP_FILE_EXTENSION) $(CPPFLAGS)
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJECTS) build/$(LIBNAME)
|
|
@ -12,6 +12,7 @@ LOCAL_SRC_FILES += \
|
|||
$(OSMAND_SKIA_LOC)/src/ports/SkThread_pthread.cpp \
|
||||
$(OSMAND_SKIA_LOC)/src/ports/SkDebug_stdio.cpp \
|
||||
$(OSMAND_SKIA_LOC)/src/ports/SkFontHost_FreeType.cpp \
|
||||
$(OSMAND_SKIA_LOC)/src/ports/SkFontHost_linux.cpp \
|
||||
$(OSMAND_SKIA_LOC)/src/ports/SkOSFile_stdio.cpp \
|
||||
$(OSMAND_SKIA_LOC)/src/ports/SkTime_Unix.cpp \
|
||||
$(OSMAND_SKIA_LOC)/src/ports/SkMemory_malloc.cpp \
|
||||
|
@ -40,7 +41,7 @@ build/$(LIBNAME): $(OBJECTS)
|
|||
ar -rf build/$(LIBNAME) $(OBJECTS)
|
||||
cp build/$(LIBNAME) ../jni-prebuilt/linux-x86/$(LIBNAME)
|
||||
|
||||
build/obj/%.o :
|
||||
build/obj/%.o : %.$(CPP_FILE_EXTENSION) $(LOCAL_C_INCLUDES)
|
||||
@mkdir -p `dirname $@`
|
||||
$(CXX) -o $@ -c $*.$(CPP_FILE_EXTENSION) $(CPPFLAGS)
|
||||
|
||||
|
|
Loading…
Reference in a new issue