mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-09 13:54:37 +00:00
Compare commits
6 Commits
zyphlar-pa
...
zy-panoram
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7722cc7d46 | ||
|
|
5eeeaeb288 | ||
|
|
899df496ba | ||
|
|
47f959ec07 | ||
|
|
6e8a0f22e6 | ||
|
|
2a2007a473 |
@@ -17,6 +17,17 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
# TODO: enable
|
||||
# run-panoramax:
|
||||
# description: 'Update Panoramax imagery?'
|
||||
# required: false
|
||||
# default: true
|
||||
# type: boolean
|
||||
run-cleanup:
|
||||
description: 'Clean up old build files?'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
run-tiger:
|
||||
description: 'Update TIGER address data?'
|
||||
required: false
|
||||
@@ -80,11 +91,49 @@ env:
|
||||
ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }}
|
||||
MWMTEST: ${{ inputs.map-generator-test }}
|
||||
MWMCONTINUE: ${{ inputs.map-generator-continue }}
|
||||
# MWMCOUNTRIES: ${{ inputs.map-generator-countries }}
|
||||
#TODO: undo ${{ inputs.map-generator-countries }}
|
||||
MWMCOUNTRIES: US_Oregon_Portland
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
TZ: Etc/UTC
|
||||
|
||||
jobs:
|
||||
cleanup-old-files:
|
||||
if: inputs.run-cleanup
|
||||
name: Clean Up Old Files
|
||||
runs-on: mapfilemaker
|
||||
container:
|
||||
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||
volumes:
|
||||
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: Remove intermediate data
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Checking for intermediate map build data in /mnt/4tbexternal/osm-maps..."
|
||||
cd /mnt/4tbexternal/osm-maps/
|
||||
# List all dated directories, sort by name (newest first)
|
||||
ls -1d */ 2>/dev/null | grep -E '^[0-9]{4}_[0-9]{2}_[0-9]{2}__[0-9]{2}_[0-9]{2}_[0-9]{2}/$' | while read dir; do
|
||||
echo "Removing any intermediate data: $dir"
|
||||
rm -rf "$dir/intermediate_data"
|
||||
rm -rf "$dir/osm2ft"
|
||||
rm -rf "$dir/world_roads.o5m"
|
||||
done
|
||||
echo "Intermediate data cleaned up."
|
||||
- name: Remove old map builds (keep last 6)
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Checking for old map builds in /mnt/4tbexternal/osm-maps..."
|
||||
cd /mnt/4tbexternal/osm-maps/
|
||||
# List all dated directories, sort by name (newest first), skip first 6, delete the rest
|
||||
ls -1d */ 2>/dev/null | grep -E '^[0-9]{4}_[0-9]{2}_[0-9]{2}__[0-9]{2}_[0-9]{2}_[0-9]{2}/$' | sort -r | tail -n +7 | while read dir; do
|
||||
echo "Removing old build: $dir"
|
||||
rm -rf "$dir"
|
||||
done
|
||||
echo "Old map builds cleaned up."
|
||||
clone-repos:
|
||||
name: Clone Git Repos
|
||||
runs-on: mapfilemaker
|
||||
@@ -209,6 +258,70 @@ jobs:
|
||||
--data-urlencode topic=codeberg-bot \
|
||||
--data-urlencode 'content=Isolines are done!'
|
||||
|
||||
update-panoramax:
|
||||
# TODO: uncommenbt
|
||||
# if: inputs.run-panoramax
|
||||
name: Update Panoramax
|
||||
runs-on: mapfilemaker
|
||||
needs:
|
||||
- clone-repos
|
||||
container:
|
||||
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||
volumes:
|
||||
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: "~"
|
||||
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Install Python dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install pyarrow duckdb
|
||||
- name: Download Panoramax Geoparquet
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p /home/planet/panoramax
|
||||
cd /home/planet/panoramax
|
||||
# Download the global Panoramax geoparquet file (20GB)
|
||||
if [ ! -f panoramax.parquet ]; then
|
||||
echo "Downloading Panoramax geoparquet..."
|
||||
curl -L -o panoramax.parquet https://api.panoramax.xyz/data/geoparquet/panoramax.parquet
|
||||
else
|
||||
echo "panoramax.parquet already exists, skipping download"
|
||||
fi
|
||||
- name: Process Panoramax to per-country files
|
||||
shell: bash
|
||||
run: |
|
||||
cd ~/comaps
|
||||
mkdir -p /home/planet/panoramax/countries
|
||||
python3 tools/python/maps_generator/panoramax_preprocessor.py \
|
||||
--input /home/planet/panoramax/panoramax.parquet \
|
||||
--output /home/planet/panoramax/countries \
|
||||
--polygons ~/comaps/data/packed_polygons.bin
|
||||
- name: Check panoramax files
|
||||
shell: bash
|
||||
run: |
|
||||
NUMPANO=$(ls -1 /home/planet/panoramax/countries/*.panoramax 2>/dev/null | wc -l)
|
||||
echo "Found $NUMPANO panoramax country files"
|
||||
if [ $NUMPANO -lt 5 ]; then
|
||||
echo "ERROR: Did generation fail? Expected at least 5 country files"
|
||||
exit 1
|
||||
fi
|
||||
- name: Notify Zulip
|
||||
run: |
|
||||
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
|
||||
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
|
||||
--data-urlencode type=stream \
|
||||
--data-urlencode 'to="DevOps"' \
|
||||
--data-urlencode topic=codeberg-bot \
|
||||
--data-urlencode 'content=Panoramax processing is done!'
|
||||
|
||||
update-tiger:
|
||||
if: inputs.run-tiger
|
||||
name: Update TIGER
|
||||
@@ -574,4 +687,3 @@ jobs:
|
||||
--data-urlencode 'to="DevOps"' \
|
||||
--data-urlencode topic=codeberg-bot \
|
||||
--data-urlencode 'content=Upload is done!'
|
||||
|
||||
|
||||
@@ -28,13 +28,7 @@ jobs:
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: "~"
|
||||
key: cache-${{ github.run_id }}-${{ github.run_attempt }}}
|
||||
- name: Checkout main repo
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
|
||||
cd ~
|
||||
git clone --depth 1 --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
|
||||
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Checkout subways repo
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -152,7 +152,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
|
||||
if (mInputValidator != null)
|
||||
{
|
||||
final String maybeError = mInputValidator.validate(activity, input);
|
||||
mEtInputLayout.getEditText().setError(maybeError);
|
||||
mEtInputLayout.setError(maybeError);
|
||||
mEtInputLayout.requestFocus();
|
||||
return maybeError == null;
|
||||
}
|
||||
|
||||
@@ -196,10 +196,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
{
|
||||
final Context context = mInputBuildingLevels.getContext();
|
||||
final boolean isValid = Editor.nativeIsLevelValid(s.toString());
|
||||
UiUtils.setInputError(mInputBuildingLevels,
|
||||
isValid ? null
|
||||
: context.getString(R.string.error_enter_correct_storey_number,
|
||||
Editor.nativeGetMaxEditableBuildingLevels()));
|
||||
mInputBuildingLevels.setError(isValid ? null : context.getString(R.string.error_enter_correct_storey_number,
|
||||
Editor.nativeGetMaxEditableBuildingLevels()));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.WindowCompat;
|
||||
@@ -209,15 +208,7 @@ public final class UiUtils
|
||||
}
|
||||
public static void setInputError(@NonNull TextInputLayout layout, @StringRes int error)
|
||||
{
|
||||
setInputError(layout, error == 0 ? null : layout.getContext().getString(error));
|
||||
}
|
||||
|
||||
public static void setInputError(@NonNull TextInputLayout layout, String error)
|
||||
{
|
||||
layout.getEditText().setError(error);
|
||||
layout.getEditText().setTextColor(error == null
|
||||
? ThemeUtils.getColor(layout.getContext(), android.R.attr.textColorPrimary)
|
||||
: ContextCompat.getColor(layout.getContext(), R.color.base_red));
|
||||
layout.setError(error == 0 ? null : layout.getContext().getString(error));
|
||||
}
|
||||
|
||||
public static void setFullscreen(@NonNull Activity activity, boolean fullscreen)
|
||||
|
||||
@@ -74,6 +74,11 @@ public class PlacePageButtonFactory
|
||||
titleId = R.string.avoid_ferry;
|
||||
yield R.drawable.ic_avoid_ferry;
|
||||
}
|
||||
case PANORAMAX ->
|
||||
{
|
||||
titleId = R.string.panoramax;
|
||||
yield R.drawable.ic_camera;
|
||||
}
|
||||
case MORE ->
|
||||
{
|
||||
titleId = R.string.placepage_more_button;
|
||||
|
||||
@@ -144,6 +144,7 @@ public final class PlacePageButtons extends Fragment implements Observer<List<Pl
|
||||
ROUTE_AVOID_TOLL,
|
||||
ROUTE_AVOID_FERRY,
|
||||
ROUTE_AVOID_UNPAVED,
|
||||
PANORAMAX,
|
||||
MORE
|
||||
}
|
||||
|
||||
|
||||
@@ -428,6 +428,7 @@ public class PlacePageController
|
||||
case ROUTE_AVOID_TOLL -> onAvoidTollBtnClicked();
|
||||
case ROUTE_AVOID_UNPAVED -> onAvoidUnpavedBtnClicked();
|
||||
case ROUTE_AVOID_FERRY -> onAvoidFerryBtnClicked();
|
||||
case PANORAMAX -> onPanoramaxBtnClicked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,6 +500,19 @@ public class PlacePageController
|
||||
requireActivity().finish();
|
||||
}
|
||||
|
||||
private void onPanoramaxBtnClicked()
|
||||
{
|
||||
if (mMapObject == null)
|
||||
return;
|
||||
String url = Framework.nativeGetPanoramaxUrl();
|
||||
if (!TextUtils.isEmpty(url))
|
||||
{
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(android.net.Uri.parse(url));
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void onRouteFromBtnClicked()
|
||||
{
|
||||
if (mMapObject == null)
|
||||
@@ -637,6 +651,10 @@ public class PlacePageController
|
||||
buttons.add(mapObject.isBookmark() ? PlacePageButtons.ButtonType.BOOKMARK_DELETE
|
||||
: PlacePageButtons.ButtonType.BOOKMARK_SAVE);
|
||||
}
|
||||
|
||||
// Add Panoramax button if imagery is available
|
||||
if (Framework.nativeHasPanoramax())
|
||||
buttons.add(PlacePageButtons.ButtonType.PANORAMAX);
|
||||
}
|
||||
mViewModel.setCurrentButtons(buttons);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M80,360v-160q0,-33 23.5,-56.5T160,120h640q33,0 56.5,23.5T880,200v160h-80v-160L160,200v160L80,360ZM160,720q-33,0 -56.5,-23.5T80,640v-200h80v200h640v-200h80v200q0,33 -23.5,56.5T800,720L160,720ZM40,840v-80h880v80L40,840ZM480,420ZM80,440v-80h240q11,0 21,6t15,16l47,93 123,-215q5,-9 14,-14.5t20,-5.5q11,0 21,5.5t15,16.5l49,98h235v80L620,440q-11,0 -21,-5.5T584,418l-26,-53 -123,215q-5,10 -15,15t-21,5q-11,0 -20.5,-6T364,578l-69,-138L80,440Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?colorControlNormal"
|
||||
android:tint="?iconTint"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="960"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M480,840q-150,0 -255,-105T120,480q0,-150 105,-255t255,-105q14,0 27.5,1t26.5,3q-41,29 -65.5,75.5T444,300q0,90 63,153t153,63q55,0 101,-24.5t75,-65.5q2,13 3,26.5t1,27.5q0,150 -105,255T480,840ZM480,760q88,0 158,-48.5T740,585q-20,5 -40,8t-40,3q-123,0 -209.5,-86.5T364,300q0,-20 3,-40t8,-40q-78,32 -126.5,102T200,480q0,116 82,198t198,82ZM470,490Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M19,9h-4v-6h-6v6h-4l7,7 7,-7ZM5,18v2h14v-2h-14Z"
|
||||
android:fillColor="#FFF"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M216,784q-45,-45 -70.5,-104T120,558q0,-63 24,-124.5T222,318q35,-35 86.5,-60t122,-39.5Q501,204 591.5,201t202.5,7q8,106 5,195t-16.5,160.5q-13.5,71.5 -38,125T684,778q-53,53 -112.5,77.5T450,880q-65,0 -127,-25.5T216,784ZM328,768q29,17 59.5,24.5T450,800q46,0 91,-18.5t86,-59.5q18,-18 36.5,-50.5t32,-85Q709,534 716,459.5t2,-177.5q-49,-2 -110.5,-1.5T485,290q-61,9 -116,29t-90,55q-45,45 -62,89t-17,85q0,59 22.5,103.5T262,714q42,-80 111,-153.5T534,440q-72,63 -125.5,142.5T328,768ZM328,768ZM328,768Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M200,800v-280h-80v-80h240v80h-80v280h-80ZM200,360v-200h80v200h-80ZM360,360v-80h80v-120h80v120h80v80L360,360ZM440,800v-360h80v360h-80ZM680,800v-120h-80v-80h240v80h-80v120h-80ZM680,520v-360h80v360h-80Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v124q18,7 29,22t11,34v80q0,19 -11,34t-29,22v404q0,33 -23.5,56.5T680,920L280,920ZM280,840h400v-720L280,120v720ZM280,840v-720,720ZM394,640h172q14,0 24,-10t10,-24v-132q0,-14 -10,-24t-24,-10h-6v-40q0,-33 -23.5,-56.5T480,320q-33,0 -56.5,23.5T400,400v40h-6q-14,0 -24,10t-10,24v132q0,14 10,24t24,10ZM440,440v-40q0,-17 11.5,-28.5T480,360q17,0 28.5,11.5T520,400v40h-80Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M339,698q22,-22 49.5,-36t58.5,-19q-5,19 -8,38t-3,39q0,24 3.5,47t11.5,44L339,698ZM254,614 L170,528q62,-62 142,-95t168,-33q49,0 96,10.5t90,30.5q-44,8 -81.5,29T517,522q-9,-1 -18.5,-1.5T480,520q-64,0 -122.5,24.5T254,614ZM84,444 L0,360q95,-97 219.5,-148.5T480,160q136,0 260.5,51.5T960,360l-84,84q-79,-79 -181.5,-121.5T480,280q-112,0 -214.5,42.5T84,444ZM760,520 L772,580q12,5 22.5,10.5T816,604l58,-18 40,68 -46,40q2,12 2,26t-2,26l46,40 -40,68 -58,-18q-11,8 -21.5,13.5T772,860l-12,60h-80l-12,-60q-12,-5 -22.5,-10.5T624,836l-58,18 -40,-68 46,-40q-2,-12 -2,-26t2,-26l-46,-40 40,-68 58,18q11,-8 21.5,-13.5T668,580l12,-60h80ZM720,640q-33,0 -56.5,23.5T640,720q0,33 23.5,56.5T720,800q33,0 56.5,-23.5T800,720q0,-33 -23.5,-56.5T720,640Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M480,480q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM160,800v-112q0,-34 17.5,-62.5T224,582q62,-31 126,-46.5T480,520q66,0 130,15.5T736,582q29,15 46.5,43.5T800,688v112L160,800ZM240,720h480v-32q0,-11 -5.5,-20T700,654q-54,-27 -109,-40.5T480,600q-56,0 -111,13.5T260,654q-9,5 -14.5,14t-5.5,20v32ZM480,400q33,0 56.5,-23.5T560,320q0,-33 -23.5,-56.5T480,240q-33,0 -56.5,23.5T400,320q0,33 23.5,56.5T480,400ZM480,320ZM480,720Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="m798,638 l-62,-62q44,-41 69,-97t25,-119q0,-63 -25,-118t-69,-96l62,-64q56,53 89,125t33,153q0,81 -33,153t-89,125ZM670,510l-64,-64q18,-17 29,-38.5t11,-47.5q0,-26 -11,-47.5T606,274l64,-64q32,29 50,67.5t18,82.5q0,44 -18,82.5T670,510ZM360,520q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM40,840v-112q0,-33 17,-62t47,-44q51,-26 115,-44t141,-18q77,0 141,18t115,44q30,15 47,44t17,62v112L40,840ZM120,760h480v-32q0,-11 -5.5,-20T580,694q-36,-18 -92.5,-36T360,640q-71,0 -127.5,18T140,694q-9,5 -14.5,14t-5.5,20v32ZM360,440q33,0 56.5,-23.5T440,360q0,-33 -23.5,-56.5T360,280q-33,0 -56.5,23.5T280,360q0,33 23.5,56.5T360,440ZM360,360ZM360,760Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M360,440h80v-160h-80v160ZM480,440h80v-160h-80v160ZM600,440h80v-160h-80v160ZM240,880q-33,0 -56.5,-23.5T160,800v-480l240,-240h320q33,0 56.5,23.5T800,160v640q0,33 -23.5,56.5T720,880L240,880ZM240,800h480v-640L434,160L240,354v446ZM240,800h480,-480Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M13.26,3C8.17,2.86 4,6.95 4,12L2.21,12c-0.45,0 -0.67,0.54 -0.35,0.85l2.79,2.8c0.2,0.2 0.51,0.2 0.71,0l2.79,-2.8c0.31,-0.31 0.09,-0.85 -0.36,-0.85L6,12c0,-3.9 3.18,-7.05 7.1,-7 3.72,0.05 6.85,3.18 6.9,6.9 0.05,3.91 -3.1,7.1 -7,7.1 -1.61,0 -3.1,-0.55 -4.28,-1.48 -0.4,-0.31 -0.96,-0.28 -1.32,0.08 -0.42,0.42 -0.39,1.13 0.08,1.49C9,20.29 10.91,21 13,21c5.05,0 9.14,-4.17 9,-9.26 -0.13,-4.69 -4.05,-8.61 -8.74,-8.74zM12.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v3.68c0,0.35 0.19,0.68 0.49,0.86l3.12,1.85c0.36,0.21 0.82,0.09 1.03,-0.26 0.21,-0.36 0.09,-0.82 -0.26,-1.03l-2.88,-1.71v-3.4c0,-0.4 -0.34,-0.74 -0.75,-0.74z"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M480,560q-33,0 -56.5,-23.5T400,480q0,-33 23.5,-56.5T480,400q33,0 56.5,23.5T560,480q0,33 -23.5,56.5T480,560ZM480,840q-139,0 -241,-91.5T122,520h82q14,104 92.5,172T480,760q117,0 198.5,-81.5T760,480q0,-117 -81.5,-198.5T480,200q-69,0 -129,32t-101,88h110v80L120,400v-240h80v94q51,-64 124.5,-99T480,120q75,0 140.5,28.5t114,77q48.5,48.5 77,114T840,480q0,75 -28.5,140.5t-77,114q-48.5,48.5 -114,77T480,840Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M160,720q-33,0 -56.5,-23.5T80,640v-320q0,-33 23.5,-56.5T160,240h640q33,0 56.5,23.5T880,320v320q0,33 -23.5,56.5T800,720L160,720ZM160,640h640v-320L680,320v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160L160,320v320ZM280,480h80,-80ZM440,480h80,-80ZM600,480h80,-80ZM480,480Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M280,800v-520L80,280v-120h520v120L400,280v520L280,800ZM640,800v-320L520,480v-120h360v120L760,480v320L640,800Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480h80q0,115 72.5,203T418,794l-58,-58 56,-56L598,862q-29,10 -58.5,14T480,880ZM500,600v-240h120q17,0 28.5,11.5T660,400v160q0,17 -11.5,28.5T620,600L500,600ZM300,600v-60h100v-40h-60v-40h60v-40L300,420v-60h120q17,0 28.5,11.5T460,400v160q0,17 -11.5,28.5T420,600L300,600ZM560,540h40v-120h-40v120ZM800,480q0,-115 -72.5,-203T542,166l58,58 -56,56 -182,-182q29,-10 58.5,-14t59.5,-4q83,0 156,31.5T763,197q54,54 85.5,127T880,480h-80Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM160,760l-56,-56 202,-202q-35,-35 -63.5,-80T190,320h84q20,39 40,68t48,58q33,-33 68.5,-92.5T484,240L40,240v-80h280v-80h80v80h280v80L564,240q-21,72 -63,148t-83,116l96,98 -30,82 -122,-125 -202,201ZM628,688h144l-72,-204 -72,204Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM628,688h144l-72,-204 -72,204ZM254,640q-66,0 -123.5,-38.5T44,498l72,-36q21,42 58,70t79,28q38,0 62.5,-23.5T340,480q0,-33 -23.5,-56.5T260,400h-60v-80h60q25,0 42.5,-17.5T320,260q0,-25 -17,-42.5T261,200q-23,0 -41,15t-32,33l-63,-49q26,-32 60,-55.5t77,-23.5q57,0 97.5,40.5T400,259q0,27 -10,52.5T361,357q10,10 18.5,20.5T396,400h124v-200h-80v-80h240v80h-80v116l-61,164L420,480v4q0,63 -46,109.5T254,640Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?colorControlNormal">
|
||||
android:tint="?iconTint">
|
||||
<path
|
||||
android:pathData="M480,840 L0,359q93,-93 215.5,-146T480,160q142,0 264.5,53T960,359l-56,57q-81,-81 -190,-128.5T480,240q-103,0 -195,32.5T117,363l419,420 -56,57ZM864,800L761,698q-18,11 -38,16.5t-43,5.5q-68,0 -114,-46t-46,-114q0,-68 46,-114t114,-46q68,0 114,46t46,114q0,23 -5.5,43T818,641l102,103 -56,56ZM680,640q34,0 57,-23t23,-57q0,-34 -23,-57t-57,-23q-34,0 -57,23t-23,57q0,34 23,57t57,23ZM480,783Z"
|
||||
android:fillColor="#fff"/>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about_headline"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline6"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
app:layout_constraintTop_toTopOf="@id/version" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
android:layout_marginBottom="@dimen/margin_base"
|
||||
android:text="@string/about_headline"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline6"
|
||||
android:textColor="?android:textColorPrimary" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
app:tint="?colorSecondary"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/head_message"
|
||||
style="@style/TextAppearance.Headline6"
|
||||
style="@style/MwmTextAppearance.Headline6"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_base"
|
||||
@@ -48,7 +48,7 @@
|
||||
android:text="@string/download_map_title" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/download_message"
|
||||
style="@style/TextAppearance.Body2"
|
||||
style="@style/MwmTextAppearance.Body2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/aa_connected_title"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Headline4"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline4"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
@@ -36,7 +36,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/car_used_on_the_car_screen"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Body1" />
|
||||
android:textAppearance="@style/MwmTextAppearance.Body1" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
android:layout_marginStart="32dp"
|
||||
android:text="@string/aa_request_permission_activity_text"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Headline4"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline4"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="@style/TextAppearance.Headline6"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline6"
|
||||
tools:text="Title" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:text="@string/download_country_ask"
|
||||
android:textAppearance="@style/TextAppearance.Body2"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body2"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
app:buttonTint="@null"/>
|
||||
|
||||
<RadioButton
|
||||
style="@style/TextAppearance.Subtitle1"
|
||||
style="@style/MwmTextAppearance.Subtitle1"
|
||||
android:id="@+id/sort_by_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -47,7 +47,7 @@
|
||||
app:buttonTint="@null"/>
|
||||
|
||||
<RadioButton
|
||||
style="@style/TextAppearance.Subtitle1"
|
||||
style="@style/MwmTextAppearance.Subtitle1"
|
||||
android:id="@+id/sort_by_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -57,7 +57,7 @@
|
||||
app:buttonTint="@null"/>
|
||||
|
||||
<RadioButton
|
||||
style="@style/TextAppearance.Subtitle1"
|
||||
style="@style/MwmTextAppearance.Subtitle1"
|
||||
android:id="@+id/sort_by_distance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -67,7 +67,7 @@
|
||||
app:buttonTint="@null"/>
|
||||
|
||||
<RadioButton
|
||||
style="@style/TextAppearance.Subtitle1"
|
||||
style="@style/MwmTextAppearance.Subtitle1"
|
||||
android:id="@+id/sort_by_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:paddingTop="@dimen/margin_half"
|
||||
android:paddingBottom="@dimen/margin_base"
|
||||
android:textAppearance="@style/TextAppearance.Headline6"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline6"
|
||||
tools:text="Xindian Shitoushan Trail" />
|
||||
<include
|
||||
layout="@layout/item_divider"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginTop="@dimen/margin_base"
|
||||
android:text="@string/layers_title"
|
||||
android:textAppearance="@style/TextAppearance.Headline6"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline6"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
android:ellipsize="middle"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Body1"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body1"
|
||||
tools:text="Bookmark name looooooooooooooooooongasdasdasd" />
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom_line_container"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
android:layout_marginEnd="@dimen/bookmark_collection_item_end_margin"
|
||||
android:ellipsize="middle"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Body1"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body1"
|
||||
tools:text="Bookmark name looooooooooooooooooongasdasdasd" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/size"
|
||||
@@ -37,7 +37,7 @@
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
style="@style/TextAppearance.Body2"
|
||||
style="@style/MwmTextAppearance.Body2"
|
||||
tools:text="42000000" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
android:paddingBottom="@dimen/margin_half_plus">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_message"
|
||||
style="@style/TextAppearance.Headline6"
|
||||
style="@style/MwmTextAppearance.Headline6"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/text"
|
||||
style="@style/TextAppearance.Headline6"
|
||||
style="@style/MwmTextAppearance.Headline6"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?windowBackgroundForced"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
android:gravity="center"
|
||||
android:maxWidth="500dp"
|
||||
android:text="@string/editor_category_unsuitable_title"
|
||||
android:textAppearance="@style/TextAppearance.Headline6"
|
||||
android:textAppearance="@style/MwmTextAppearance.Headline6"
|
||||
android:textStyle="bold" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/editor_category_unsuitable_text"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
android:layout_marginTop="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/bookmark_collection_item_end_margin"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.Body1"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body1"
|
||||
tools:text="@string/tracks_title" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tv__bookmark_distance"
|
||||
@@ -39,7 +39,7 @@
|
||||
android:layout_marginBottom="@dimen/margin_half_plus"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textAppearance="@style/TextAppearance.Body2"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body2"
|
||||
tools:text="@string/by_distance" />
|
||||
</LinearLayout>
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/place_page_last_checked"
|
||||
style="@style/TextAppearance.Caption"
|
||||
style="@style/MwmTextAppearance.Caption"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_half"
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/oh_check_date"
|
||||
style="@style/TextAppearance.Caption"
|
||||
style="@style/MwmTextAppearance.Caption"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
|
||||
@@ -923,7 +923,6 @@
|
||||
<string name="advanced">Avançat</string>
|
||||
<string name="download_resources_custom_url_title">Servidor de Mapes Personalitzat</string>
|
||||
<string name="download_resources_custom_url_message">Sobreescriu el servidor de descàrrega de mapes per defecte. Deixa en blanc per a emprar el servidor per defecte de CoMaps.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">No establert</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Per favor introdueix una URL completa que comence amb https:// i acabe amb /</string>
|
||||
</resources>
|
||||
|
||||
@@ -915,7 +915,6 @@
|
||||
<string name="navigation_start_tts_disabled_message">Hlasové pokyny vypnuty: služba TTS není dostupná</string>
|
||||
<string name="download_resources_custom_url_title">Vlastní mapový server</string>
|
||||
<string name="download_resources_custom_url_message">Přepsat výchozí server používaný ke stahování map. Nechte pole prázdné, pokud chcete použít výchozí server CoMaps.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Zadejte prosím celou adresu URL začínající na https:// a končící s /</string>
|
||||
<string name="advanced">Pokročilé</string>
|
||||
<string name="download_resources_custom_url_summary_none">Není nastaveno</string>
|
||||
|
||||
@@ -920,5 +920,4 @@
|
||||
<string name="download_resources_custom_url_summary_none">Nicht konfiguriert</string>
|
||||
<string name="download_resources_custom_url_message">Standardserver für Kartendownloads überschreiben. Leer lassen, um den CoMaps-Standardserver zu nutzen.</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Bitte eine vollständige URL eingeben, die mit https:// beginnt und mit / endet</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
</resources>
|
||||
|
||||
@@ -927,5 +927,4 @@
|
||||
<string name="download_resources_custom_url_message">Sobreescribe el servidor de mapas por defecto. Deja en blanco para usar el servidor de CoMaps por defecto.</string>
|
||||
<string name="download_resources_custom_url_summary_none">No establecido</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Por favor introduce un URL completo empezando con https:// y terminando con /</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
</resources>
|
||||
|
||||
@@ -915,6 +915,5 @@
|
||||
<string name="advanced">Täiendavad seadistused</string>
|
||||
<string name="download_resources_custom_url_title">Sinu oma kaardiserver</string>
|
||||
<string name="download_resources_custom_url_message">Kui tahad kasutada oma kaardiserverit, siis lisa ta siia. CoMapsi vaikimisi serveri kasutamiseks jäta tühjaks.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Palun sisesta täismahuline võrguaadress, mille alguses on https:// ja lõpus /</string>
|
||||
</resources>
|
||||
|
||||
@@ -923,7 +923,6 @@
|
||||
<string name="navigation_start_tts_disabled_message">Instructions vocales désactivées : moteur de synthèse vocale non disponible</string>
|
||||
<string name="advanced">Avancé</string>
|
||||
<string name="download_resources_custom_url_summary_none">Non défini</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_title">Serveur de cartes personnalisé</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Veuillez saisir une URL complète débutant par https:// et se terminant par /</string>
|
||||
<string name="download_resources_custom_url_message">Serveur pour télécharger les cartes. Laissez vide pour utiliser le serveur par défaut CoMaps.</string>
|
||||
|
||||
@@ -908,7 +908,6 @@
|
||||
<string name="navigation_start_tts_message">"Inizio Navigazione, lingua per istruzioni vocali: "</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Aggiungere un URL che inizia con https:// e finisce con /</string>
|
||||
<string name="download_resources_custom_url_summary_none">Non impostato</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_message">Sovrascrivi il server da cui scaricare le mappe. Lascia vuoto per usare i server default di CoMaps.</string>
|
||||
<string name="download_resources_custom_url_title">Server mappe personalizzato</string>
|
||||
<string name="advanced">Avanzate</string>
|
||||
|
||||
@@ -899,7 +899,6 @@
|
||||
<string name="advanced">Kita</string>
|
||||
<string name="download_resources_custom_url_title">Pasirinktinis žemėlapių serveris</string>
|
||||
<string name="download_resources_custom_url_message">Žemėlapiams parsisiųsti galite nurodyti kitą, nei numatytasis, serverį. Palikite lauką tuščią, jei norite naudoti numatytąjį „CoMaps“ serverį.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Nenurodytas</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Įveskite visą URL adresą, pradedant „https://“ ir baigiant „/“</string>
|
||||
</resources>
|
||||
|
||||
@@ -853,7 +853,6 @@
|
||||
<string name="navigation_start_tts_disabled_message">Balss norādes atspējotas: nav pieejams teksta pārveidošanas runā dzinējs</string>
|
||||
<string name="prefs_speed_cameras_information">Brīdinājumi par ātruma noteikšanas kamerā ir atspējoti valstīs, kurās šādus brīdinājumus aizliedz vietējais likums.</string>
|
||||
<string name="navigation_start_tts_message">"Uzsāk navigāciju, balss norāžu valoda: "</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Nav iestatīts</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Lūgums ievadīt pilnu URL, kas sākas ar https:// un beidzas ar /</string>
|
||||
<string name="advanced">Iestatījumi: izvērsta kopa</string>
|
||||
|
||||
@@ -909,7 +909,6 @@
|
||||
<string name="advanced">Avansert</string>
|
||||
<string name="download_resources_custom_url_summary_none">Ikke angitt</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Angi en fullstendig nettadresse som starter med https:// og slutter med /</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_message">Overstyr standardserveren som brukes til nedlasting av kart. La det stå tomt for å bruke CoMaps standardserver.</string>
|
||||
<string name="download_resources_custom_url_title">Tilpasset kartserver</string>
|
||||
</resources>
|
||||
|
||||
@@ -918,7 +918,6 @@
|
||||
<string name="advanced">Geavanceerd</string>
|
||||
<string name="download_resources_custom_url_title">Aangepaste server voor kaarten</string>
|
||||
<string name="download_resources_custom_url_message">Overschrijf de standaard kaartdownloadserver die wordt gebruikt voor kaartdownloads. Laat leeg om de standaardserver van CoMaps te gebruiken.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Niet ingesteld</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Voer een volledige URL in, beginnend met https:// en eindigend met /</string>
|
||||
</resources>
|
||||
|
||||
@@ -912,7 +912,6 @@
|
||||
<string name="advanced">Avançadas</string>
|
||||
<string name="download_resources_custom_url_title">Servidor de Mapa Personalizado</string>
|
||||
<string name="download_resources_custom_url_message">Substitui o servidor de download de mapas normal. Deixe em branco para usar o servidor do CoMaps padrão.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Indefinido</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Por favor insira um URL inteiro começando com https:// e acabando com /</string>
|
||||
</resources>
|
||||
|
||||
@@ -662,5 +662,4 @@
|
||||
<string name="download_resources_custom_url_message">Prepiši privzeti strežnik za prenos zemljevidov, ki se uporablja za prenos zemljevidov. Pustite prazno, če želite uporabiti privzeti strežnik CoMaps.</string>
|
||||
<string name="download_resources_custom_url_summary_none">Ni nastavljeno</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Prosimo, vnesite polni URL, ki se začne z https:// in konča z /</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
</resources>
|
||||
|
||||
@@ -917,7 +917,6 @@
|
||||
<string name="advanced">Напредно</string>
|
||||
<string name="download_resources_custom_url_title">Сопствени сервер мапа</string>
|
||||
<string name="download_resources_custom_url_message">Замени подразумевани сервер за преузимање мапа који се користи за преузимања мапа. Оставите празно да бисте користили CoMaps сервер.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Није постављено</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Унесите пуну УРЛ адресу која почиње са https:// и која се завршава са /</string>
|
||||
</resources>
|
||||
|
||||
@@ -917,7 +917,6 @@
|
||||
<string name="place_page_app_too_old_description">您当前的地图数据非常旧,请更新 CoMaps 应用。</string>
|
||||
<string name="place_page_update_too_old_map">更新地图区域</string>
|
||||
<string name="place_page_too_old_to_edit">由于地图数据太旧,OpenStreetMap 编辑被禁用。</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">未设置</string>
|
||||
<string name="download_resources_custom_url_error_scheme">请输入以 https:// 开头、以 / 结尾的完整 URL</string>
|
||||
<string name="advanced">高级</string>
|
||||
|
||||
@@ -105,4 +105,5 @@
|
||||
<string name="count_label" translatable="false">× %d</string>
|
||||
<string name="kw_label" translatable="false">%s kW</string>
|
||||
<string name="phone_format" translatable="false">+ XX X XX XX XX</string>
|
||||
<string name="download_resources_custom_url_hint" translatable="false">https://cdn-fi-1.comaps.app/</string>
|
||||
</resources>
|
||||
|
||||
@@ -971,7 +971,6 @@
|
||||
<!-- Custom Download URL -->
|
||||
<string name="download_resources_custom_url_title">Custom Map Server</string>
|
||||
<string name="download_resources_custom_url_message">Override the default map download server used for map downloads. Leave empty to use CoMaps default server.</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Not set</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Please enter a full URL starting with https:// and ending with /</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,12 +15,6 @@
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmTextAppearance.Headline">
|
||||
<item name="android:textSize">@dimen/text_size_headline</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:fontFamily">@string/robotoMedium</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmTextAppearance.Body1" parent="TextAppearance.MaterialComponents.Headline6">
|
||||
<item name="android:textSize">@dimen/text_size_body_1</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
@@ -176,94 +170,59 @@
|
||||
<item name="android:textColor">@color/white_secondary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Headline1"
|
||||
<style name="MwmTextAppearance.Headline1"
|
||||
parent="TextAppearance.Material3.DisplayLarge">
|
||||
<item name="fontFamily">@string/robotoLight</item>
|
||||
<item name="android:fontFamily">@string/robotoLight</item>
|
||||
<item name="android:textSize">96sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Headline2"
|
||||
<style name="MwmTextAppearance.Headline2"
|
||||
parent="TextAppearance.Material3.DisplayLarge">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">60sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Headline3"
|
||||
<style name="MwmTextAppearance.Headline3"
|
||||
parent="TextAppearance.Material3.DisplayMedium">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">48sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Headline4"
|
||||
<style name="MwmTextAppearance.Headline4"
|
||||
parent="TextAppearance.Material3.HeadlineLarge">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">34sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Headline5"
|
||||
<style name="MwmTextAppearance.Headline5"
|
||||
parent="TextAppearance.Material3.HeadlineMedium">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Headline6"
|
||||
<style name="MwmTextAppearance.Headline6"
|
||||
parent="TextAppearance.Material3.HeadlineSmall">
|
||||
<item name="fontFamily">@string/robotoMedium</item>
|
||||
<item name="android:fontFamily">@string/robotoMedium</item>
|
||||
<item name="android:textSize">20sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Subtitle1"
|
||||
<style name="MwmTextAppearance.Subtitle1"
|
||||
parent="TextAppearance.Material3.TitleMedium">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Subtitle2"
|
||||
<style name="MwmTextAppearance.Subtitle2"
|
||||
parent="TextAppearance.Material3.TitleSmall">
|
||||
<item name="fontFamily">@string/robotoMedium</item>
|
||||
<item name="android:fontFamily">@string/robotoMedium</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Body1"
|
||||
parent="TextAppearance.Material3.BodyLarge">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Body2"
|
||||
parent="TextAppearance.Material3.BodyMedium">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Button"
|
||||
parent="TextAppearance.MaterialComponents.Button">
|
||||
<item name="fontFamily">@string/robotoMedium</item>
|
||||
<item name="android:fontFamily">@string/robotoMedium</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Caption"
|
||||
parent="TextAppearance.Material3.LabelMedium">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Overline"
|
||||
parent="TextAppearance.MaterialComponents.Overline">
|
||||
<item name="fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:fontFamily">@string/robotoRegular</item>
|
||||
<item name="android:textSize">10sp</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -1764,6 +1764,16 @@ JNIEXPORT jboolean JNICALL Java_app_organicmaps_sdk_Framework_nativeHasPlacePage
|
||||
return static_cast<jboolean>(frm()->HasPlacePageInfo());
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_app_organicmaps_sdk_Framework_nativeHasPanoramax(JNIEnv *, jclass)
|
||||
{
|
||||
return static_cast<jboolean>(g_framework->GetPlacePageInfo().HasPanoramax());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_app_organicmaps_sdk_Framework_nativeGetPanoramaxUrl(JNIEnv * env, jclass)
|
||||
{
|
||||
return jni::ToJavaString(env, g_framework->GetPlacePageInfo().GetPanoramaxUrl());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_app_organicmaps_sdk_Framework_nativeMemoryWarning(JNIEnv *, jclass)
|
||||
{
|
||||
return frm()->MemoryWarning();
|
||||
|
||||
@@ -349,6 +349,8 @@ public class Framework
|
||||
* @return true if c++ framework has initialized internal place page object, otherwise - false.
|
||||
*/
|
||||
public static native boolean nativeHasPlacePageInfo();
|
||||
public static native boolean nativeHasPanoramax();
|
||||
public static native String nativeGetPanoramaxUrl();
|
||||
|
||||
public static native void nativeMemoryWarning();
|
||||
public static native void nativeSaveRoute();
|
||||
|
||||
@@ -1758,3 +1758,4 @@ amenity|luggage_locker;1629;
|
||||
building|guardhouse;[building=guardhouse],[amenity=security_booth],[amenity=checkpoint];;;;1630;
|
||||
office|security;1631;
|
||||
shop|lighting;1632;
|
||||
panoramax|image;1633;
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 16.
|
@@ -7,6 +7,7 @@
|
||||
#include "generator/feature_builder.hpp"
|
||||
#include "generator/final_processor_utils.hpp"
|
||||
#include "generator/isolines_generator.hpp"
|
||||
#include "generator/panoramax_generator.hpp"
|
||||
#include "generator/mini_roundabout_transformer.hpp"
|
||||
#include "generator/node_mixer.hpp"
|
||||
#include "generator/osm2type.hpp"
|
||||
@@ -68,6 +69,10 @@ void CountryFinalProcessor::Process()
|
||||
if (!m_isolinesPath.empty())
|
||||
AddIsolines();
|
||||
|
||||
LOG(LINFO, ("Adding panoramax..."));
|
||||
if (!m_panoramaxPath.empty())
|
||||
AddPanoramax();
|
||||
|
||||
// DropProhibitedSpeedCameras();
|
||||
LOG(LINFO, ("Processing building parts..."));
|
||||
ProcessBuildingParts();
|
||||
@@ -293,6 +298,22 @@ void CountryFinalProcessor::AddAddresses()
|
||||
LOG(LINFO, ("Total addresses:", totalStats));
|
||||
}
|
||||
|
||||
void CountryFinalProcessor::AddPanoramax()
|
||||
{
|
||||
if (m_panoramaxPath.empty())
|
||||
return;
|
||||
|
||||
PanoramaxFeaturesGenerator panoramaxGenerator(m_panoramaxPath);
|
||||
ForEachMwmTmp(m_temporaryMwmPath, [&](auto const & name, auto const & path)
|
||||
{
|
||||
if (!IsCountry(name))
|
||||
return;
|
||||
|
||||
FeatureBuilderWriter<serialization_policy::MaxAccuracy> writer(path, FileWriter::Op::OP_APPEND);
|
||||
panoramaxGenerator.GeneratePanoramax(name, [&](auto const & fb) { writer.Write(fb); });
|
||||
}, m_threadsCount);
|
||||
}
|
||||
|
||||
void CountryFinalProcessor::ProcessCoastline()
|
||||
{
|
||||
/// @todo We can remove MinSize at all.
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
|
||||
void SetIsolinesDir(std::string const & dir) { m_isolinesPath = dir; }
|
||||
void SetAddressesDir(std::string const & dir) { m_addressPath = dir; }
|
||||
void SetPanoramaxDir(std::string const & dir) { m_panoramaxPath = dir; }
|
||||
|
||||
void SetCityBoundariesFiles(std::string const & collectorFile) { m_boundariesCollectorFile = collectorFile; }
|
||||
|
||||
@@ -39,6 +40,7 @@ private:
|
||||
void AddFakeNodes();
|
||||
void AddIsolines();
|
||||
void AddAddresses();
|
||||
void AddPanoramax();
|
||||
void DropProhibitedSpeedCameras();
|
||||
// void Finish();
|
||||
|
||||
@@ -47,7 +49,7 @@ private:
|
||||
std::string m_borderPath;
|
||||
std::string m_temporaryMwmPath;
|
||||
std::string m_intermediateDir;
|
||||
std::string m_isolinesPath, m_addressPath;
|
||||
std::string m_isolinesPath, m_addressPath, m_panoramaxPath;
|
||||
std::string m_boundariesCollectorFile;
|
||||
std::string m_coastlineGeomFilename;
|
||||
std::string m_worldCoastsFilename;
|
||||
|
||||
@@ -39,8 +39,8 @@ struct GenerateInfo
|
||||
|
||||
std::string m_cacheDir;
|
||||
|
||||
// External folders with additional preprocessed data (isolines, addresses).
|
||||
std::string m_isolinesDir, m_addressesDir;
|
||||
// External folders with additional preprocessed data (isolines, addresses, panoramax).
|
||||
std::string m_isolinesDir, m_addressesDir, m_panoramaxDir;
|
||||
|
||||
// Current generated file name if --output option is defined.
|
||||
std::string m_fileName;
|
||||
|
||||
@@ -107,6 +107,7 @@ DEFINE_string(nodes_list_path, "",
|
||||
DEFINE_bool(generate_isolines_info, false, "Generate the isolines info section");
|
||||
DEFINE_string(isolines_path, "", "Path to isolines directory. If set, adds isolines linear features.");
|
||||
DEFINE_string(addresses_path, "", "Path to addresses directory. If set, adds addr:interpolation features.");
|
||||
DEFINE_string(panoramax_path, "", "Path to panoramax directory. If set, adds panoramax imagery point features.");
|
||||
|
||||
// Routing.
|
||||
DEFINE_bool(make_routing_index, false, "Make sections with the routing information.");
|
||||
@@ -243,6 +244,7 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
||||
genInfo.m_complexHierarchyFilename = FLAGS_complex_hierarchy_data;
|
||||
genInfo.m_isolinesDir = FLAGS_isolines_path;
|
||||
genInfo.m_addressesDir = FLAGS_addresses_path;
|
||||
genInfo.m_panoramaxDir = FLAGS_panoramax_path;
|
||||
|
||||
// Use merged style.
|
||||
GetStyleReader().SetCurrentStyle(MapStyleMerged);
|
||||
|
||||
144
generator/panoramax_generator.cpp
Normal file
144
generator/panoramax_generator.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "generator/panoramax_generator.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/feature_meta.hpp"
|
||||
|
||||
#include "coding/file_reader.hpp"
|
||||
#include "coding/read_write_utils.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/logging.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
|
||||
namespace generator
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::string_view const kPanoramax = "panoramax";
|
||||
std::string_view const kImage = "image";
|
||||
|
||||
std::string GetPanoramaxFilePath(std::string const & countryName, std::string const & panoramaxDir)
|
||||
{
|
||||
return panoramaxDir + "/" + countryName + ".panoramax";
|
||||
}
|
||||
|
||||
struct PanoramaxPoint
|
||||
{
|
||||
double lat;
|
||||
double lon;
|
||||
std::string imageId;
|
||||
};
|
||||
|
||||
bool LoadPanoramaxPoints(std::string const & filePath, std::vector<PanoramaxPoint> & points)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
if (!file.is_open())
|
||||
{
|
||||
LOG(LWARNING, ("Can't open panoramax file", filePath));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read header
|
||||
uint32_t version;
|
||||
uint64_t pointCount;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&version), sizeof(version));
|
||||
file.read(reinterpret_cast<char*>(&pointCount), sizeof(pointCount));
|
||||
|
||||
if (version != 1)
|
||||
{
|
||||
LOG(LERROR, ("Unsupported panoramax file version", version));
|
||||
return false;
|
||||
}
|
||||
|
||||
points.reserve(static_cast<size_t>(pointCount));
|
||||
|
||||
// Read points
|
||||
for (uint64_t i = 0; i < pointCount; ++i)
|
||||
{
|
||||
PanoramaxPoint point;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&point.lat), sizeof(point.lat));
|
||||
file.read(reinterpret_cast<char*>(&point.lon), sizeof(point.lon));
|
||||
|
||||
// Read image_id (length-prefixed string)
|
||||
uint32_t imageIdLength;
|
||||
file.read(reinterpret_cast<char*>(&imageIdLength), sizeof(imageIdLength));
|
||||
|
||||
if (imageIdLength > 0 && imageIdLength < 10000) // Sanity check
|
||||
{
|
||||
point.imageId.resize(imageIdLength);
|
||||
file.read(&point.imageId[0], imageIdLength);
|
||||
}
|
||||
|
||||
if (file.fail())
|
||||
{
|
||||
LOG(LERROR, ("Error reading panoramax point", i, "from", filePath));
|
||||
return false;
|
||||
}
|
||||
|
||||
points.push_back(std::move(point));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
LOG(LERROR, ("Exception loading panoramax file", filePath, ":", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
PanoramaxFeaturesGenerator::PanoramaxFeaturesGenerator(std::string const & panoramaxDir)
|
||||
: m_panoramaxDir(panoramaxDir)
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
m_panoramaxType = c.GetTypeByPath({kPanoramax, kImage});
|
||||
}
|
||||
|
||||
void PanoramaxFeaturesGenerator::GeneratePanoramax(std::string const & countryName,
|
||||
FeaturesCollectFn const & fn) const
|
||||
{
|
||||
auto const panoramaxPath = GetPanoramaxFilePath(countryName, m_panoramaxDir);
|
||||
|
||||
std::vector<PanoramaxPoint> points;
|
||||
if (!LoadPanoramaxPoints(panoramaxPath, points))
|
||||
{
|
||||
LOG(LWARNING, ("Can't load panoramax points for", countryName));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(LINFO, ("Generating", points.size(), "panoramax points for", countryName));
|
||||
|
||||
for (auto const & point : points)
|
||||
{
|
||||
feature::FeatureBuilder fb;
|
||||
|
||||
// Set point geometry
|
||||
m2::PointD const mercatorPoint = mercator::FromLatLon(point.lat, point.lon);
|
||||
fb.SetCenter(mercatorPoint);
|
||||
|
||||
// Add classificator type
|
||||
fb.AddType(m_panoramaxType);
|
||||
|
||||
// Add metadata with image ID
|
||||
if (!point.imageId.empty())
|
||||
{
|
||||
fb.GetMetadata().Set(feature::Metadata::FMD_PANORAMAX, point.imageId);
|
||||
}
|
||||
|
||||
// Panoramax points are POI features (point geometry)
|
||||
fb.SetPoint();
|
||||
|
||||
fn(std::move(fb));
|
||||
}
|
||||
}
|
||||
} // namespace generator
|
||||
24
generator/panoramax_generator.hpp
Normal file
24
generator/panoramax_generator.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "generator/feature_builder.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace generator
|
||||
{
|
||||
// Generates Panoramax imagery point features from binary files.
|
||||
// Binary files are created by the panoramax_preprocessor.py script.
|
||||
class PanoramaxFeaturesGenerator
|
||||
{
|
||||
public:
|
||||
explicit PanoramaxFeaturesGenerator(std::string const & panoramaxDir);
|
||||
|
||||
using FeaturesCollectFn = std::function<void(feature::FeatureBuilder && fb)>;
|
||||
void GeneratePanoramax(std::string const & countryName, FeaturesCollectFn const & fn) const;
|
||||
|
||||
private:
|
||||
std::string m_panoramaxDir;
|
||||
uint32_t m_panoramaxType; // Classificator type for panoramax|image
|
||||
};
|
||||
} // namespace generator
|
||||
@@ -182,6 +182,7 @@ RawGenerator::FinalProcessorPtr RawGenerator::CreateCountryFinalProcessor(Affili
|
||||
auto finalProcessor = std::make_shared<CountryFinalProcessor>(affiliations, m_genInfo.m_tmpDir, m_threadsCount);
|
||||
finalProcessor->SetIsolinesDir(m_genInfo.m_isolinesDir);
|
||||
finalProcessor->SetAddressesDir(m_genInfo.m_addressesDir);
|
||||
finalProcessor->SetPanoramaxDir(m_genInfo.m_panoramaxDir);
|
||||
finalProcessor->SetMiniRoundabouts(m_genInfo.GetIntermediateFileName(MINI_ROUNDABOUTS_FILENAME));
|
||||
finalProcessor->SetAddrInterpolation(m_genInfo.GetIntermediateFileName(ADDR_INTERPOL_FILENAME));
|
||||
if (addAds)
|
||||
|
||||
@@ -706,6 +706,7 @@ void Framework::FillInfoFromFeatureType(FeatureType & ft, place_page::Info & inf
|
||||
info.SetFromFeatureType(ft);
|
||||
|
||||
FillDescription(ft, info);
|
||||
CheckPanoramaxImagery(info);
|
||||
|
||||
auto const mwmInfo = ft.GetID().m_mwmId.GetInfo();
|
||||
bool const isMapVersionEditable = CanEditMapForPosition(info.GetMercator());
|
||||
@@ -3263,6 +3264,43 @@ void Framework::FillDescription(FeatureType & ft, place_page::Info & info) const
|
||||
}
|
||||
}
|
||||
|
||||
void Framework::CheckPanoramaxImagery(place_page::Info & info) const
|
||||
{
|
||||
// Query features within 50m radius
|
||||
auto constexpr radiusM = 50.0;
|
||||
auto const center = info.GetMercator();
|
||||
auto const rect = mercator::RectByCenterXYAndSizeInMeters(center, radiusM);
|
||||
|
||||
auto const panoramaxType = classif().GetTypeByPath({"panoramax", "image"});
|
||||
|
||||
bool hasPanoramax = false;
|
||||
std::string panoramaxImageId;
|
||||
std::string panoramaxUrl;
|
||||
|
||||
m_featuresFetcher.GetDataSource().ForEachInRect([&](FeatureType & ft)
|
||||
{
|
||||
if (ft.GetTypes().Has(panoramaxType))
|
||||
{
|
||||
auto const imageId = ft.GetMetadata(feature::Metadata::FMD_PANORAMAX);
|
||||
if (!imageId.empty())
|
||||
{
|
||||
hasPanoramax = true;
|
||||
panoramaxImageId = std::string(imageId);
|
||||
panoramaxUrl = "https://panoramax.openstreetmap.fr/#focus=pic:" + panoramaxImageId;
|
||||
return base::ControlFlow::Break; // Found one, stop searching
|
||||
}
|
||||
}
|
||||
return base::ControlFlow::Continue;
|
||||
}, rect, df::GetDrawTileScale(rect));
|
||||
|
||||
if (hasPanoramax)
|
||||
{
|
||||
info.m_hasPanoramax = true;
|
||||
info.m_panoramaxImageId = std::move(panoramaxImageId);
|
||||
info.m_panoramaxUrl = std::move(panoramaxUrl);
|
||||
}
|
||||
}
|
||||
|
||||
void Framework::OnPowerFacilityChanged(power_management::Facility const facility, bool enabled)
|
||||
{
|
||||
if (facility == power_management::Facility::PerspectiveView || facility == power_management::Facility::Buildings3d)
|
||||
|
||||
@@ -640,6 +640,7 @@ private:
|
||||
void FillTrackInfo(Track const & track, m2::PointD const & trackPoint, place_page::Info & info) const;
|
||||
void SetPlacePageLocation(place_page::Info & info);
|
||||
void FillDescription(FeatureType & ft, place_page::Info & info) const;
|
||||
void CheckPanoramaxImagery(place_page::Info & info) const;
|
||||
|
||||
public:
|
||||
search::ReverseGeocoder::Address GetAddressAtPoint(m2::PointD const & pt) const;
|
||||
|
||||
@@ -114,6 +114,9 @@ public:
|
||||
bool HasApiUrl() const { return !m_apiUrl.empty(); }
|
||||
/// TODO: Support all possible Internet types in UI. @See MapObject::GetInternet().
|
||||
bool HasWifi() const { return GetInternet() == feature::Internet::Wlan; }
|
||||
/// @returns true if Panoramax imagery is available within 50m.
|
||||
bool HasPanoramax() const { return m_hasPanoramax; }
|
||||
std::string const & GetPanoramaxUrl() const { return m_panoramaxUrl; }
|
||||
/// Should be used by UI code to generate cool name for new bookmarks.
|
||||
// TODO: Tune new bookmark name. May be add address or some other data.
|
||||
kml::LocalizableString FormatNewBookmarkName() const;
|
||||
@@ -258,6 +261,11 @@ private:
|
||||
/// Formatted feature address for inner using.
|
||||
std::string m_address;
|
||||
|
||||
/// Panoramax
|
||||
bool m_hasPanoramax = false;
|
||||
std::string m_panoramaxImageId;
|
||||
std::string m_panoramaxUrl;
|
||||
|
||||
/// Routing
|
||||
RouteMarkType m_routeMarkType;
|
||||
size_t m_intermediateIndex = 0;
|
||||
|
||||
@@ -351,6 +351,10 @@ class PathProvider:
|
||||
def addresses_path() -> AnyStr:
|
||||
return settings.ADDRESSES_PATH
|
||||
|
||||
@staticmethod
|
||||
def panoramax_path() -> AnyStr:
|
||||
return settings.PANORAMAX_PATH
|
||||
|
||||
@staticmethod
|
||||
def borders_path() -> AnyStr:
|
||||
return os.path.join(settings.USER_RESOURCE_PATH, "borders")
|
||||
|
||||
@@ -121,6 +121,7 @@ US_POSTCODES_URL = ""
|
||||
SRTM_PATH = ""
|
||||
ISOLINES_PATH = ""
|
||||
ADDRESSES_PATH = ""
|
||||
PANORAMAX_PATH = ""
|
||||
|
||||
# Stats section:
|
||||
STATS_TYPES_CONFIG = os.path.join(ETC_DIR, "stats_types_config.txt")
|
||||
@@ -278,6 +279,7 @@ def init(default_settings_path: AnyStr):
|
||||
global SRTM_PATH
|
||||
global ISOLINES_PATH
|
||||
global ADDRESSES_PATH
|
||||
global PANORAMAX_PATH
|
||||
|
||||
PLANET_URL = cfg.get_opt_path("External", "PLANET_URL", PLANET_URL)
|
||||
PLANET_MD5_URL = cfg.get_opt_path("External", "PLANET_MD5_URL", md5_ext(PLANET_URL))
|
||||
@@ -306,6 +308,7 @@ def init(default_settings_path: AnyStr):
|
||||
SRTM_PATH = cfg.get_opt_path("External", "SRTM_PATH", SRTM_PATH)
|
||||
ISOLINES_PATH = cfg.get_opt_path("External", "ISOLINES_PATH", ISOLINES_PATH)
|
||||
ADDRESSES_PATH = cfg.get_opt_path("External", "ADDRESSES_PATH", ADDRESSES_PATH)
|
||||
PANORAMAX_PATH = cfg.get_opt_path("External", "PANORAMAX_PATH", PANORAMAX_PATH)
|
||||
|
||||
# Stats section:
|
||||
global STATS_TYPES_CONFIG
|
||||
|
||||
@@ -134,6 +134,8 @@ class StageFeatures(Stage):
|
||||
if is_accepted(env, StageIsolinesInfo):
|
||||
extra.update({"isolines_path": PathProvider.isolines_path()})
|
||||
extra.update({"addresses_path": PathProvider.addresses_path()})
|
||||
if PathProvider.panoramax_path():
|
||||
extra.update({"panoramax_path": PathProvider.panoramax_path()})
|
||||
|
||||
steps.step_features(env, **extra)
|
||||
if os.path.exists(env.paths.packed_polygons_path):
|
||||
|
||||
260
tools/python/maps_generator/panoramax_preprocessor.py
Normal file
260
tools/python/maps_generator/panoramax_preprocessor.py
Normal file
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Panoramax Preprocessor
|
||||
|
||||
Converts the global Panoramax geoparquet file into per-country binary files
|
||||
for use in the map generator.
|
||||
|
||||
The script streams the large geoparquet file (20GB+) using DuckDB to avoid
|
||||
loading everything into memory, performs a spatial join with country polygons,
|
||||
and writes compact binary files for each country.
|
||||
|
||||
Binary Format:
|
||||
Header:
|
||||
uint32 version (=1)
|
||||
uint64 point_count
|
||||
Data (repeated point_count times):
|
||||
double lat (8 bytes)
|
||||
double lon (8 bytes)
|
||||
string image_id (length-prefixed: uint32 length + bytes)
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import struct
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
from collections import defaultdict
|
||||
|
||||
try:
|
||||
import duckdb
|
||||
except ImportError:
|
||||
print("Error: duckdb is required. Install with: pip install duckdb", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_country_polygons(polygons_file: Path) -> Dict[str, any]:
|
||||
"""
|
||||
Load country polygons from packed_polygons.bin file.
|
||||
|
||||
This is a placeholder - actual implementation would need to parse the binary format.
|
||||
For now, we'll use a simpler approach with DuckDB spatial functions.
|
||||
"""
|
||||
# TODO: Implement actual polygon loading from packed_polygons.bin
|
||||
# For MVP, we can use a simplified approach or require pre-processed country boundaries
|
||||
logger.warning("Country polygon loading not yet implemented - using fallback method")
|
||||
return {}
|
||||
|
||||
|
||||
def determine_country_from_coords(lat: float, lon: float, conn: duckdb.DuckDBPyConnection) -> str:
|
||||
"""
|
||||
Determine which country a coordinate belongs to.
|
||||
|
||||
This uses a simple approach for MVP - can be enhanced later.
|
||||
Returns country name or "Unknown" if not found.
|
||||
"""
|
||||
# Simplified country detection for MVP
|
||||
# TODO: Use actual country polygons for accurate spatial join
|
||||
|
||||
# For now, return a simplified country code based on rough lat/lon bounds
|
||||
# This is just for initial testing - real implementation needs proper spatial join
|
||||
if 40 < lat < 52 and -5 < lon < 10:
|
||||
return "France"
|
||||
elif 45 < lat < 48 and 5 < lon < 11:
|
||||
return "Switzerland"
|
||||
elif 43 < lat < 44 and 7 < lon < 8:
|
||||
return "Monaco"
|
||||
else:
|
||||
return "Unknown"
|
||||
|
||||
|
||||
def write_binary_file(output_path: Path, points: List[Tuple[float, float, str]]):
|
||||
"""
|
||||
Write panoramax points to binary file.
|
||||
|
||||
Format:
|
||||
Header:
|
||||
uint32 version = 1
|
||||
uint64 point_count
|
||||
Data:
|
||||
For each point:
|
||||
double lat
|
||||
double lon
|
||||
uint32 image_id_length
|
||||
bytes image_id
|
||||
"""
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(output_path, 'wb') as f:
|
||||
# Write header
|
||||
version = 1
|
||||
point_count = len(points)
|
||||
f.write(struct.pack('<I', version)) # uint32 version
|
||||
f.write(struct.pack('<Q', point_count)) # uint64 point_count
|
||||
|
||||
# Write points
|
||||
for lat, lon, image_id in points:
|
||||
f.write(struct.pack('<d', lat)) # double lat
|
||||
f.write(struct.pack('<d', lon)) # double lon
|
||||
|
||||
# Write image_id as length-prefixed string
|
||||
image_id_bytes = image_id.encode('utf-8')
|
||||
f.write(struct.pack('<I', len(image_id_bytes))) # uint32 length
|
||||
f.write(image_id_bytes) # bytes
|
||||
|
||||
logger.info(f"Wrote {point_count} points to {output_path}")
|
||||
|
||||
|
||||
def process_parquet_streaming(parquet_url: str, output_dir: Path, batch_size: int = 100000):
|
||||
"""
|
||||
Stream the Panoramax parquet file and write per-country binary files.
|
||||
|
||||
Uses DuckDB to stream the large parquet file without loading it entirely into memory.
|
||||
"""
|
||||
conn = duckdb.connect(database=':memory:')
|
||||
|
||||
# Enable httpfs extension for remote file access
|
||||
try:
|
||||
conn.execute("INSTALL httpfs;")
|
||||
conn.execute("LOAD httpfs;")
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not load httpfs extension: {e}")
|
||||
|
||||
# Install spatial extension for future country boundary support
|
||||
try:
|
||||
conn.execute("INSTALL spatial;")
|
||||
conn.execute("LOAD spatial;")
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not load spatial extension: {e}")
|
||||
|
||||
logger.info(f"Reading parquet file: {parquet_url}")
|
||||
|
||||
# Dictionary to accumulate points per country
|
||||
country_points: Dict[str, List[Tuple[float, float, str]]] = defaultdict(list)
|
||||
|
||||
# Stream the parquet file in batches
|
||||
# Assuming parquet has columns: latitude, longitude, id (or similar)
|
||||
# Adjust column names based on actual Panoramax parquet schema
|
||||
query = f"""
|
||||
SELECT
|
||||
latitude as lat,
|
||||
longitude as lon,
|
||||
id as image_id
|
||||
FROM read_parquet('{parquet_url}')
|
||||
WHERE latitude IS NOT NULL AND longitude IS NOT NULL
|
||||
"""
|
||||
|
||||
try:
|
||||
result = conn.execute(query)
|
||||
|
||||
batch_count = 0
|
||||
total_points = 0
|
||||
|
||||
while True:
|
||||
batch = result.fetchmany(batch_size)
|
||||
if not batch:
|
||||
break
|
||||
|
||||
batch_count += 1
|
||||
batch_size_actual = len(batch)
|
||||
total_points += batch_size_actual
|
||||
|
||||
logger.info(f"Processing batch {batch_count}: {batch_size_actual} points (total: {total_points})")
|
||||
|
||||
for row in batch:
|
||||
lat, lon, image_id = row
|
||||
|
||||
# Determine country
|
||||
country = determine_country_from_coords(lat, lon, conn)
|
||||
|
||||
# Skip unknown countries for now (or save to separate file)
|
||||
if country != "Unknown":
|
||||
country_points[country].append((lat, lon, str(image_id)))
|
||||
|
||||
# Periodically write to disk to avoid memory issues
|
||||
if batch_count % 10 == 0:
|
||||
for country, points in country_points.items():
|
||||
if len(points) > 100000: # Write if accumulated > 100k points
|
||||
output_file = output_dir / f"{country}.panoramax"
|
||||
# Append mode for incremental writing
|
||||
# TODO: Implement append mode or accumulate all then write once
|
||||
logger.info(f"Country {country} has {len(points)} points accumulated")
|
||||
|
||||
logger.info(f"Finished processing {total_points} total points")
|
||||
logger.info(f"Countries found: {list(country_points.keys())}")
|
||||
|
||||
# Write final output files
|
||||
for country, points in country_points.items():
|
||||
if points:
|
||||
output_file = output_dir / f"{country}.panoramax"
|
||||
write_binary_file(output_file, points)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing parquet: {e}")
|
||||
raise
|
||||
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Convert Panoramax geoparquet to per-country binary files",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=__doc__
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--input',
|
||||
default='https://api.panoramax.xyz/data/geoparquet/panoramax.parquet',
|
||||
help='Path or URL to Panoramax geoparquet file (default: official Panoramax URL)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--output',
|
||||
type=Path,
|
||||
required=True,
|
||||
help='Output directory for per-country .panoramax files'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--polygons',
|
||||
type=Path,
|
||||
help='Path to packed_polygons.bin file (optional, for accurate country detection)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=100000,
|
||||
help='Number of rows to process per batch (default: 100000)'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
logger.info("Panoramax Preprocessor starting")
|
||||
logger.info(f"Input: {args.input}")
|
||||
logger.info(f"Output directory: {args.output}")
|
||||
logger.info(f"Batch size: {args.batch_size}")
|
||||
|
||||
if args.polygons:
|
||||
logger.info(f"Country polygons: {args.polygons}")
|
||||
# TODO: Load and use country polygons for accurate spatial join
|
||||
else:
|
||||
logger.warning("No country polygons provided - using simplified country detection")
|
||||
|
||||
# Create output directory
|
||||
args.output.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Process the parquet file
|
||||
process_parquet_streaming(args.input, args.output, args.batch_size)
|
||||
|
||||
logger.info("Panoramax preprocessing complete!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -80,6 +80,7 @@ SUBWAY_URL: file:///home/planet/subway/subways.transit.json
|
||||
SRTM_PATH: /home/planet/SRTM-patched-europe/
|
||||
ISOLINES_PATH: /home/planet/isolines/
|
||||
ADDRESSES_PATH: /home/planet/tiger/
|
||||
PANORAMAX_PATH: /home/planet/panoramax/countries/
|
||||
|
||||
# Local path (not url!) to .csv files.
|
||||
UK_POSTCODES_URL: /home/planet/postcodes/gb-postcode-data/gb_postcodes.csv
|
||||
|
||||
@@ -13,6 +13,7 @@ mkdir -p /home/planet/postcodes/gb-postcode-data/
|
||||
mkdir -p /home/planet/postcodes/us-postcodes/
|
||||
mkdir -p /home/planet/SRTM-patched-europe/
|
||||
mkdir -p /home/planet/subway
|
||||
mkdir -p /home/planet/panoramax/countries/
|
||||
|
||||
echo "<$(date +%T)> Running ./configure.sh ..."
|
||||
cd ~/comaps
|
||||
|
||||
Reference in New Issue
Block a user