[routing] New API for lanes

Signed-off-by: Andrei Shkrob <github@shkrob.dev>
This commit is contained in:
Andrei Shkrob
2025-07-29 22:54:24 +02:00
committed by x7z4w
parent 93293e7b31
commit c014e224b2
36 changed files with 1047 additions and 634 deletions

View File

@@ -26,13 +26,14 @@ set(SRC
app/organicmaps/sdk/search/SearchEngine.cpp
app/organicmaps/sdk/search/SearchRecents.cpp
app/organicmaps/sdk/routing/JunctionInfo.hpp
app/organicmaps/sdk/routing/LaneInfo.cpp
app/organicmaps/sdk/routing/LaneInfo.hpp
app/organicmaps/sdk/routing/RouteMarkData.hpp
app/organicmaps/sdk/routing/RouteMarkType.hpp
app/organicmaps/sdk/routing/RoutePointInfo.hpp
app/organicmaps/sdk/routing/RouteRecommendationType.hpp
app/organicmaps/sdk/routing/RoutingInfo.hpp
app/organicmaps/sdk/routing/RoutingOptions.cpp
app/organicmaps/sdk/routing/SingleLaneInfo.hpp
app/organicmaps/sdk/routing/TransitRouteInfo.hpp
app/organicmaps/sdk/routing/TransitStepInfo.hpp
app/organicmaps/sdk/ChoosePositionMode.cpp

View File

@@ -0,0 +1,50 @@
#include "LaneInfo.hpp"
#include "app/organicmaps/sdk/core/jni_helper.hpp"
#include <vector>
namespace
{
jobject ToJavaLaneWay(JNIEnv * env, routing::turns::lanes::LaneWay const & laneWay)
{
static jclass const laneWayClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/LaneWay");
jfieldID fieldID =
env->GetStaticFieldID(laneWayClass, DebugPrint(laneWay).c_str(), "Lapp/organicmaps/sdk/routing/LaneWay;");
return env->GetStaticObjectField(laneWayClass, fieldID);
}
} // namespace
jobjectArray CreateLanesInfo(JNIEnv * env, routing::turns::lanes::LanesInfo const & lanes)
{
if (lanes.empty())
return nullptr;
static jclass const laneWayClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/LaneWay");
static jclass const laneInfoClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/LaneInfo");
auto const lanesSize = static_cast<jsize>(lanes.size());
jobjectArray jLanes = env->NewObjectArray(lanesSize, laneInfoClass, nullptr);
ASSERT(jLanes, (jni::DescribeException()));
// Java signature : LaneInfo(LaneWay[] laneWays, LaneWay activeLane)
static jmethodID const ctorLaneInfoID = jni::GetConstructorID(
env, laneInfoClass, "([Lapp/organicmaps/sdk/routing/LaneWay;Lapp/organicmaps/sdk/routing/LaneWay;)V");
for (jsize j = 0; j < lanesSize; ++j)
{
auto const laneWays = lanes[j].laneWays.GetActiveLaneWays();
auto const laneWaysSize = static_cast<jsize>(laneWays.size());
jni::TScopedLocalObjectArrayRef jLaneWays(env, env->NewObjectArray(laneWaysSize, laneWayClass, nullptr));
ASSERT(jLanes, (jni::DescribeException()));
for (jsize i = 0; i < laneWaysSize; ++i)
{
jni::TScopedLocalRef jLaneWay(env, ToJavaLaneWay(env, laneWays[i]));
env->SetObjectArrayElement(jLaneWays.get(), i, jLaneWay.get());
}
jni::TScopedLocalRef jLaneInfo(env, env->NewObject(laneInfoClass, ctorLaneInfoID, jLaneWays.get(),
ToJavaLaneWay(env, lanes[j].recommendedWay)));
ASSERT(jLaneInfo.get(), (jni::DescribeException()));
env->SetObjectArrayElement(jLanes, j, jLaneInfo.get());
}
return jLanes;
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <jni.h>
#include "routing/lanes/lane_info.hpp"
jobjectArray CreateLanesInfo(JNIEnv * env, routing::turns::lanes::LanesInfo const & lanes);

View File

@@ -1,7 +1,7 @@
#pragma once
#include "app/organicmaps/sdk/core/jni_helper.hpp"
#include "app/organicmaps/sdk/routing/SingleLaneInfo.hpp"
#include "app/organicmaps/sdk/routing/LaneInfo.hpp"
#include "app/organicmaps/sdk/util/Distance.hpp"
#include "map/routing_manager.hpp"
@@ -13,12 +13,13 @@ jobject CreateRoutingInfo(JNIEnv * env, routing::FollowingInfo const & info, Rou
// String currentStreet, String nextStreet, String nextNextStreet,
// double completionPercent, int vehicleTurnOrdinal, int
// vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum,
// int totalTime, SingleLaneInfo[] lanes)
// int totalTime, LaneInfo[] lanes, double speedLimitMps, boolean speedLimitExceeded,
// boolean shouldPlayWarningSignal)
static jmethodID const ctorRouteInfoID =
jni::GetConstructorID(env, klass,
"(Lapp/organicmaps/sdk/util/Distance;Lapp/organicmaps/sdk/util/Distance;"
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;DIIIII"
"[Lapp/organicmaps/sdk/routing/SingleLaneInfo;DZZ)V");
"[Lapp/organicmaps/sdk/routing/LaneInfo;DZZ)V");
jobjectArray jLanes = CreateLanesInfo(env, info.m_lanes);

View File

@@ -1,34 +0,0 @@
#pragma once
#include "app/organicmaps/sdk/core/jni_helper.hpp"
#include "routing/following_info.hpp"
#include <vector>
jobjectArray CreateLanesInfo(JNIEnv * env, std::vector<routing::FollowingInfo::SingleLaneInfoClient> const & lanes)
{
if (lanes.empty())
return nullptr;
static jclass const laneClass = jni::GetGlobalClassRef(env, "app/organicmaps/sdk/routing/SingleLaneInfo");
auto const lanesSize = static_cast<jsize>(lanes.size());
jobjectArray jLanes = env->NewObjectArray(lanesSize, laneClass, nullptr);
ASSERT(jLanes, (jni::DescribeException()));
static jmethodID const ctorSingleLaneInfoID = jni::GetConstructorID(env, laneClass, "([BZ)V");
for (jsize j = 0; j < lanesSize; ++j)
{
auto const laneSize = static_cast<jsize>(lanes[j].m_lane.size());
jni::TScopedLocalByteArrayRef singleLane(env, env->NewByteArray(laneSize));
ASSERT(singleLane.get(), (jni::DescribeException()));
env->SetByteArrayRegion(singleLane.get(), 0, laneSize, lanes[j].m_lane.data());
jni::TScopedLocalRef singleLaneInfo(
env, env->NewObject(laneClass, ctorSingleLaneInfoID, singleLane.get(), lanes[j].m_isRecommended));
ASSERT(singleLaneInfo.get(), (jni::DescribeException()));
env->SetObjectArrayElement(jLanes, j, singleLaneInfo.get());
}
return jLanes;
}

View File

@@ -0,0 +1,27 @@
package app.organicmaps.sdk.routing;
import androidx.annotation.NonNull;
public final class LaneInfo
{
public final LaneWay[] mLaneWays;
public final LaneWay mActiveLaneWay;
public LaneInfo(@NonNull LaneWay[] laneWays, LaneWay activeLane)
{
mLaneWays = laneWays;
mActiveLaneWay = activeLane;
}
@NonNull
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("LaneInfo{activeLaneWay=").append(mActiveLaneWay.toString()).append(", laneWays=[");
for (LaneWay i : mLaneWays)
sb.append(" ").append(i);
sb.append("]}");
return sb.toString();
}
}

View File

@@ -3,25 +3,20 @@ package app.organicmaps.sdk.routing;
import androidx.annotation.DrawableRes;
import app.organicmaps.sdk.R;
/**
* IMPORTANT : Order of enum values MUST BE the same
* with native LaneWay enum (see routing/turns.hpp for details).
* Information for every lane is composed of some number values below.
* For example, a lane may have THROUGH and RIGHT values.
*/
public enum LaneWay
{
NONE(R.drawable.ic_turn_straight),
REVERSE(R.drawable.ic_turn_uleft),
SHARP_LEFT(R.drawable.ic_turn_left_sharp),
LEFT(R.drawable.ic_turn_left),
SLIGHT_LEFT(R.drawable.ic_turn_left_slight),
MERGE_TO_RIGHT(R.drawable.ic_turn_right_slight),
THROUGH(R.drawable.ic_turn_straight),
MERGE_TO_LEFT(R.drawable.ic_turn_left_slight),
SLIGHT_RIGHT(R.drawable.ic_turn_right_slight),
RIGHT(R.drawable.ic_turn_right),
SHARP_RIGHT(R.drawable.ic_turn_right_sharp);
None(R.drawable.ic_turn_straight),
ReverseLeft(R.drawable.ic_turn_uleft),
SharpLeft(R.drawable.ic_turn_left_sharp),
Left(R.drawable.ic_turn_left),
MergeToLeft(R.drawable.ic_turn_left_slight),
SlightLeft(R.drawable.ic_turn_left_slight),
Through(R.drawable.ic_turn_straight),
SlightRight(R.drawable.ic_turn_right_slight),
MergeToRight(R.drawable.ic_turn_right_slight),
Right(R.drawable.ic_turn_right),
SharpRight(R.drawable.ic_turn_right_sharp),
ReverseRight(R.drawable.ic_turn_uright);
public final int mTurnRes;

View File

@@ -1,6 +1,7 @@
package app.organicmaps.sdk.routing;
import androidx.annotation.Keep;
import androidx.annotation.Nullable;
import app.organicmaps.sdk.util.Distance;
// Called from JNI.
@@ -25,7 +26,8 @@ public final class RoutingInfo
public final CarDirection carDirection;
public final CarDirection nextCarDirection;
public final int exitNum;
public final SingleLaneInfo[] lanes;
@Nullable
public final LaneInfo[] lanes;
// For pedestrian routing.
public final PedestrianTurnDirection pedestrianTurnDirection;
// Current speed limit in meters per second.
@@ -37,7 +39,7 @@ public final class RoutingInfo
private RoutingInfo(Distance distToTarget, Distance distToTurn, String currentStreet, String nextStreet,
String nextNextStreet, double completionPercent, int vehicleTurnOrdinal,
int vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum, int totalTime,
SingleLaneInfo[] lanes, double speedLimitMps, boolean speedLimitExceeded,
@Nullable LaneInfo[] lanes, double speedLimitMps, boolean speedLimitExceeded,
boolean shouldPlayWarningSignal)
{
this.distToTarget = distToTarget;

View File

@@ -1,31 +0,0 @@
package app.organicmaps.sdk.routing;
import androidx.annotation.NonNull;
public final class SingleLaneInfo
{
public LaneWay[] mLane;
public boolean mIsActive;
public SingleLaneInfo(@NonNull byte[] laneOrdinals, boolean isActive)
{
mLane = new LaneWay[laneOrdinals.length];
final LaneWay[] values = LaneWay.values();
for (int i = 0; i < mLane.length; i++)
mLane[i] = values[laneOrdinals[i]];
mIsActive = isActive;
}
@NonNull
@Override
public String toString()
{
final int initialCapacity = 32;
StringBuilder sb = new StringBuilder(initialCapacity);
sb.append("Is the lane active? ").append(mIsActive).append(". The lane directions IDs are");
for (LaneWay i : mLane)
sb.append(" ").append(i.ordinal());
return sb.toString();
}
}