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)
|
LOCAL_PATH:= $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
include $(LOCAL_PATH)/Common.mk
|
||||||
|
|
||||||
# compile in ARM mode, since the glyph loader/renderer is a hotspot
|
# compile in ARM mode, since the glyph loader/renderer is a hotspot
|
||||||
# when loading complex pages in the browser
|
# when loading complex pages in the browser
|
||||||
#
|
#
|
||||||
LOCAL_ARM_MODE := arm
|
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)
|
ifneq ($(OSMAND_BUILDING_NEON_LIBRARY),true)
|
||||||
LOCAL_MODULE := ft2_static
|
LOCAL_MODULE := ft2_static
|
||||||
else
|
else
|
||||||
|
@ -22,43 +16,6 @@ endif
|
||||||
|
|
||||||
ifneq ($(OSMAND_USE_PREBUILT),true)
|
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)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
else
|
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/osmand_log.cpp \
|
||||||
src/common.cpp \
|
src/common.cpp \
|
||||||
src/mapObjects.cpp \
|
src/mapObjects.cpp \
|
||||||
|
src/multipolygons.cpp \
|
||||||
src/renderRules.cpp \
|
src/renderRules.cpp \
|
||||||
src/rendering.cpp \
|
src/rendering.cpp \
|
||||||
src/binaryRead.cpp
|
src/binaryRead.cpp
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
LOCAL_PATH := .
|
LOCAL_PATH := .
|
||||||
PREBUILT_DIR = ../jni-prebuilt/linux-x86/
|
PREBUILT_DIR = ../jni-prebuilt/linux-x86/
|
||||||
LIBNAME := osmand.lib
|
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
|
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
|
CPP_FILE_EXTENSION = cpp
|
||||||
OBJECTS = $(LOCAL_SRC_FILES:src/%.$(CPP_FILE_EXTENSION)=build/obj/%.o)
|
OBJECTS = $(LOCAL_SRC_FILES:src/%.$(CPP_FILE_EXTENSION)=build/obj/%.o)
|
||||||
|
|
||||||
|
@ -19,6 +24,14 @@ CPPFLAGS := \
|
||||||
-DHAVING_HASH \
|
-DHAVING_HASH \
|
||||||
$(C_INCLUDES)
|
$(C_INCLUDES)
|
||||||
|
|
||||||
|
target : ../$(RUNFILE)
|
||||||
|
#target : $(PREBUILT_DIR)/$(LIBNAME) ../$(RUNFILE)
|
||||||
|
|
||||||
|
|
||||||
|
../$(RUNFILE) : $(OBJECTS) $(PREBUILT_DIR)/libskia.a $(PREBUILT_DIR)/libproto.a
|
||||||
|
$(CXX) $(LDRUNFLAGS) -o ../$(RUNFILE) $(OBJECTS) $(LDLIBS)
|
||||||
|
@chmod +x ../$(RUNFILE)
|
||||||
|
|
||||||
$(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
$(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
||||||
cp build/$(LIBNAME) $(PREBUILT_DIR)/$(LIBNAME)
|
cp build/$(LIBNAME) $(PREBUILT_DIR)/$(LIBNAME)
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,8 @@
|
||||||
#ifndef _OSMAND_BINARY_READ
|
#ifndef _OSMAND_BINARY_READ
|
||||||
#define _OSMAND_BINARY_READ
|
#define _OSMAND_BINARY_READ
|
||||||
|
|
||||||
#include <math.h>
|
#include "binaryRead.h"
|
||||||
|
#include "osmand_log.h"
|
||||||
#include <osmand_log.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "google/protobuf/io/zero_copy_stream_impl.h"
|
#include "google/protobuf/io/zero_copy_stream_impl.h"
|
||||||
#include "google/protobuf/wire_format_lite.h"
|
#include "google/protobuf/wire_format_lite.h"
|
||||||
#include "google/protobuf/wire_format_lite.cc"
|
#include "google/protobuf/wire_format_lite.cc"
|
||||||
|
@ -18,7 +11,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "mapObjects.h"
|
#include "mapObjects.h"
|
||||||
#include "multipolygons.h"
|
#include "multipolygons.h"
|
||||||
//#include "multipolygons.h"
|
|
||||||
#include "proto/osmand_odb.pb.h"
|
#include "proto/osmand_odb.pb.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -29,8 +21,6 @@ using namespace google::protobuf::internal;
|
||||||
static const int MAP_VERSION = 2;
|
static const int MAP_VERSION = 2;
|
||||||
static const int BASEMAP_ZOOM = 11;
|
static const int BASEMAP_ZOOM = 11;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct BinaryMapFile;
|
struct BinaryMapFile;
|
||||||
std::map<std::string, BinaryMapFile*> openFiles;
|
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) {
|
bool readMapTreeBounds(io::CodedInputStream* input, MapTreeBounds* tree, MapRoot* root) {
|
||||||
int init = 0;
|
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_map>
|
||||||
#include <hash_set>
|
#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
|
#ifdef HAVING_HASH
|
||||||
|
|
||||||
#define HMAP __gnu_cxx
|
#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 <stdio.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -9,6 +11,7 @@
|
||||||
|
|
||||||
/// !!! Fuly copied from MapRenderRepositories.java, should be carefully synchroinized
|
/// !!! Fuly copied from MapRenderRepositories.java, should be carefully synchroinized
|
||||||
bool isClockwiseWay(std::vector<int_pair>& c) ;
|
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,
|
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);
|
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,
|
void processCoastlines(std::vector<MapDataObject*>& coastLines, int leftX, int rightX, int bottomY, int topY, int zoom,
|
||||||
bool showIncompleted, std::vector<MapDataObject*>& res) {
|
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
|
#endif
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ void osmand_log_print(int type, const char* msg, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start( args, msg);
|
va_start( args, msg);
|
||||||
// TODO by type
|
// TODO by type
|
||||||
printf(msg, msg, args);
|
printf(msg, args);
|
||||||
va_end(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
|
include Common.mk
|
||||||
|
|
||||||
|
CPP_FILE_EXTENSION = cpp
|
||||||
LIBNAME := libproto.a
|
LIBNAME := libproto.a
|
||||||
PREBUILT_DIR = ../jni-prebuilt/linux-x86/
|
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.
|
CPPFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI -I.
|
||||||
LDLIBS = -lpthread
|
LDLIBS = -lpthread
|
||||||
|
|
||||||
|
@ -13,9 +15,9 @@ $(PREBUILT_DIR)/$(LIBNAME) : build/$(LIBNAME)
|
||||||
build/$(LIBNAME): $(OBJECTS)
|
build/$(LIBNAME): $(OBJECTS)
|
||||||
ar -rf build/$(LIBNAME) $(OBJECTS)
|
ar -rf build/$(LIBNAME) $(OBJECTS)
|
||||||
|
|
||||||
build/obj/%.o :
|
build/obj/%.o : %.$(CPP_FILE_EXTENSION) $(LOCAL_C_INCLUDES)
|
||||||
@mkdir -p `dirname $@`
|
@mkdir -p `dirname $@`
|
||||||
$(CXX) -o $@ -c $*.cc $(CPPFLAGS)
|
$(CXX) -o $@ -c $*.$(CPP_FILE_EXTENSION) $(CPPFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) $(OBJECTS) build/$(LIBNAME)
|
$(RM) $(OBJECTS) build/$(LIBNAME)
|
|
@ -12,6 +12,7 @@ LOCAL_SRC_FILES += \
|
||||||
$(OSMAND_SKIA_LOC)/src/ports/SkThread_pthread.cpp \
|
$(OSMAND_SKIA_LOC)/src/ports/SkThread_pthread.cpp \
|
||||||
$(OSMAND_SKIA_LOC)/src/ports/SkDebug_stdio.cpp \
|
$(OSMAND_SKIA_LOC)/src/ports/SkDebug_stdio.cpp \
|
||||||
$(OSMAND_SKIA_LOC)/src/ports/SkFontHost_FreeType.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/SkOSFile_stdio.cpp \
|
||||||
$(OSMAND_SKIA_LOC)/src/ports/SkTime_Unix.cpp \
|
$(OSMAND_SKIA_LOC)/src/ports/SkTime_Unix.cpp \
|
||||||
$(OSMAND_SKIA_LOC)/src/ports/SkMemory_malloc.cpp \
|
$(OSMAND_SKIA_LOC)/src/ports/SkMemory_malloc.cpp \
|
||||||
|
@ -40,7 +41,7 @@ build/$(LIBNAME): $(OBJECTS)
|
||||||
ar -rf build/$(LIBNAME) $(OBJECTS)
|
ar -rf build/$(LIBNAME) $(OBJECTS)
|
||||||
cp build/$(LIBNAME) ../jni-prebuilt/linux-x86/$(LIBNAME)
|
cp build/$(LIBNAME) ../jni-prebuilt/linux-x86/$(LIBNAME)
|
||||||
|
|
||||||
build/obj/%.o :
|
build/obj/%.o : %.$(CPP_FILE_EXTENSION) $(LOCAL_C_INCLUDES)
|
||||||
@mkdir -p `dirname $@`
|
@mkdir -p `dirname $@`
|
||||||
$(CXX) -o $@ -c $*.$(CPP_FILE_EXTENSION) $(CPPFLAGS)
|
$(CXX) -o $@ -c $*.$(CPP_FILE_EXTENSION) $(CPPFLAGS)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue