Merge branch 'organicmaps:master' into etaswitchfeature
This commit is contained in:
commit
64697e0184
15 changed files with 290 additions and 33 deletions
|
@ -104,4 +104,21 @@
|
|||
tools:src="@drawable/ic_then_left_sharp"/>
|
||||
</FrameLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/lanes_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintHeight_percent="@fraction/nav_lane_height"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/nav_next_turn_container"
|
||||
app:layout_constraintTop_toBottomOf="@+id/street_frame"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<include layout="@layout/nav_lanes" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
20
android/res/layout/nav_lanes.xml
Normal file
20
android/res/layout/nav_lanes.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
app:cardBackgroundColor="?navLanesCardBackgroundColor"
|
||||
tools:showIn="@layout/layout_nav_top">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/lanes"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="@dimen/margin_quarter"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
android:orientation="horizontal"
|
||||
tools:listitem="@layout/nav_single_lane"
|
||||
tools:itemCount="6" />
|
||||
</androidx.cardview.widget.CardView>
|
14
android/res/layout/nav_single_lane.xml
Normal file
14
android/res/layout/nav_single_lane.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<app.organicmaps.widget.ArrowView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/lane_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:theme="?navigationTheme"
|
||||
app:tint="?iconTint"
|
||||
app:srcCompat="@drawable/ic_then_right"
|
||||
tools:showIn="@layout/layout_nav_top" />
|
4
android/res/values-land/fractions.xml
Normal file
4
android/res/values-land/fractions.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<fraction name="nav_lane_height">0.15</fraction>
|
||||
</resources>
|
4
android/res/values/fractions.xml
Normal file
4
android/res/values/fractions.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<fraction name="nav_lane_height">0.08</fraction>
|
||||
</resources>
|
|
@ -19,6 +19,7 @@
|
|||
<attr name="ppButtonsBackground" format="color" />
|
||||
<attr name="navNextTurnFrame" format="reference" />
|
||||
<attr name="navNextNextTurnFrame" format="reference" />
|
||||
<attr name="navLanesCardBackgroundColor" format="reference" />
|
||||
<attr name="buttonBackground" format="reference" />
|
||||
<attr name="buttonTextColor" format="color" />
|
||||
<attr name="buttonTextColorDisabled" format="color" />
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
<item name="navNextTurnFrame">@drawable/bg_nav_next_turn</item>
|
||||
<item name="navNextNextTurnFrame">@drawable/bg_nav_next_next_turn</item>
|
||||
<item name="navLanesCardBackgroundColor">@color/base_accent</item>
|
||||
|
||||
<item name="buttonBackground">@drawable/button</item>
|
||||
<item name="buttonTextColor">@color/button_text</item>
|
||||
|
@ -179,6 +180,7 @@
|
|||
|
||||
<item name="navNextTurnFrame">@drawable/bg_nav_next_turn_night</item>
|
||||
<item name="navNextNextTurnFrame">@drawable/bg_nav_next_next_turn_night</item>
|
||||
<item name="navLanesCardBackgroundColor">@color/base_accent_night</item>
|
||||
|
||||
<item name="buttonBackground">@drawable/button_night</item>
|
||||
<item name="buttonTextColor">@color/button_text_night</item>
|
||||
|
|
90
android/src/app/organicmaps/routing/LanesAdapter.java
Normal file
90
android/src/app/organicmaps/routing/LanesAdapter.java
Normal file
|
@ -0,0 +1,90 @@
|
|||
package app.organicmaps.routing;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.widget.ArrowView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LanesAdapter extends RecyclerView.Adapter<LanesAdapter.LanesViewHolder>
|
||||
{
|
||||
@NonNull
|
||||
private final List<SingleLaneInfo> mItems = new ArrayList<>();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public LanesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
|
||||
{
|
||||
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
final View root = inflater.inflate(R.layout.nav_single_lane, parent, false);
|
||||
return new LanesViewHolder(root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull LanesViewHolder holder, int position)
|
||||
{
|
||||
holder.bind(mItems.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
return mItems.size();
|
||||
}
|
||||
|
||||
public void setItems(@NonNull List<SingleLaneInfo> items)
|
||||
{
|
||||
mItems.clear();
|
||||
mItems.addAll(items);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void clearItems()
|
||||
{
|
||||
boolean alreadyEmpty = mItems.isEmpty();
|
||||
mItems.clear();
|
||||
if (!alreadyEmpty)
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class LanesViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
@NonNull
|
||||
private final ArrowView mArrow;
|
||||
|
||||
public LanesViewHolder(@NonNull View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
mArrow = itemView.findViewById(R.id.lane_image);
|
||||
}
|
||||
|
||||
private void setIconTint(@NonNull SingleLaneInfo info)
|
||||
{
|
||||
int iconTint = info.mIsActive ? R.attr.iconTint : R.attr.iconTintLight;
|
||||
TypedValue color = new TypedValue();
|
||||
mArrow.getContext().getTheme().resolveAttribute(iconTint, color, true);
|
||||
mArrow.setImageTintList(ColorStateList.valueOf(color.data));
|
||||
}
|
||||
|
||||
private void setIcon(@NonNull SingleLaneInfo info)
|
||||
{
|
||||
boolean haveLaneData = (info.mLane.length > 0);
|
||||
int imageRes = haveLaneData ? info.mLane[0].mTurnRes : 0;
|
||||
mArrow.setImageResource(imageRes);
|
||||
}
|
||||
|
||||
void bind(@NonNull SingleLaneInfo info)
|
||||
{
|
||||
setIconTint(info);
|
||||
setIcon(info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import androidx.annotation.Nullable;
|
|||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.MwmActivity;
|
||||
|
@ -32,6 +33,8 @@ import app.organicmaps.widget.menu.NavMenu;
|
|||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NavigationController implements Application.ActivityLifecycleCallbacks,
|
||||
TrafficManager.TrafficCallback,
|
||||
NavMenu.NavMenuListener
|
||||
|
@ -50,6 +53,13 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
private final View mStreetFrame;
|
||||
private final TextView mNextStreet;
|
||||
|
||||
@NonNull
|
||||
private final View mLanesFrame;
|
||||
@NonNull
|
||||
private final RecyclerView mLanes;
|
||||
@NonNull
|
||||
private final LanesAdapter mLanesAdapter;
|
||||
|
||||
@NonNull
|
||||
private final MapButtonsController mMapButtonsController;
|
||||
|
||||
|
@ -90,6 +100,12 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
});
|
||||
}
|
||||
|
||||
private void initLanesRecycler()
|
||||
{
|
||||
mLanes.setAdapter(mLanesAdapter);
|
||||
mLanes.setNestedScrollingEnabled(false);
|
||||
}
|
||||
|
||||
public NavigationController(AppCompatActivity activity, @NonNull MapButtonsController mapButtonsController, View.OnClickListener onSettingsClickListener)
|
||||
{
|
||||
mFrame = activity.findViewById(R.id.navigation_frame);
|
||||
|
@ -112,6 +128,11 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
mStreetFrame = topFrame.findViewById(R.id.street_frame);
|
||||
mNextStreet = mStreetFrame.findViewById(R.id.street);
|
||||
|
||||
mLanesFrame = topFrame.findViewById(R.id.lanes_frame);
|
||||
mLanes = mLanesFrame.findViewById(R.id.lanes);
|
||||
mLanesAdapter = new LanesAdapter();
|
||||
initLanesRecycler();
|
||||
|
||||
// Show a blank view below the navbar to hide the menu content
|
||||
final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar);
|
||||
final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container);
|
||||
|
@ -185,6 +206,17 @@ public class NavigationController implements Application.ActivityLifecycleCallba
|
|||
UiUtils.showIf(info.nextCarDirection.containsNextTurn(), mNextNextTurnFrame);
|
||||
if (info.nextCarDirection.containsNextTurn())
|
||||
info.nextCarDirection.setNextTurnDrawable(mNextNextTurnImage);
|
||||
|
||||
if (info.lanes != null)
|
||||
{
|
||||
UiUtils.show(mLanesFrame);
|
||||
mLanesAdapter.setItems(Arrays.asList(info.lanes));
|
||||
}
|
||||
else
|
||||
{
|
||||
UiUtils.hide(mLanesFrame);
|
||||
mLanesAdapter.clearItems();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePedestrian(RoutingInfo info)
|
||||
|
|
|
@ -133,27 +133,6 @@ public class RoutingInfo
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
REVERSE,
|
||||
SHARP_LEFT,
|
||||
LEFT,
|
||||
SLIGHT_LEFT,
|
||||
MERGE_TO_RIGHT,
|
||||
THROUGH,
|
||||
MERGE_TO_LEFT,
|
||||
SLIGHT_RIGHT,
|
||||
RIGHT,
|
||||
SHARP_RIGHT
|
||||
}
|
||||
|
||||
public RoutingInfo(String distToTarget, String units, String distTurn, String turnSuffix, String currentStreet, String nextStreet, double completionPercent,
|
||||
int vehicleTurnOrdinal, int vehicleNextTurnOrdinal, int pedestrianTurnOrdinal, int exitNum,
|
||||
int totalTime, SingleLaneInfo[] lanes, boolean speedLimitExceeded,
|
||||
|
|
|
@ -1,13 +1,48 @@
|
|||
package app.organicmaps.routing;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import app.organicmaps.R;
|
||||
|
||||
public class SingleLaneInfo
|
||||
{
|
||||
byte[] mLane;
|
||||
LaneWay[] mLane;
|
||||
boolean mIsActive;
|
||||
|
||||
SingleLaneInfo(byte[] lane, boolean isActive)
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
mLane = lane;
|
||||
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);
|
||||
|
||||
public final int mTurnRes;
|
||||
|
||||
LaneWay(@DrawableRes int turnRes)
|
||||
{
|
||||
mTurnRes = turnRes;
|
||||
}
|
||||
}
|
||||
|
||||
SingleLaneInfo(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;
|
||||
}
|
||||
|
||||
|
@ -17,8 +52,8 @@ public class SingleLaneInfo
|
|||
final int initialCapacity = 32;
|
||||
StringBuilder sb = new StringBuilder(initialCapacity);
|
||||
sb.append("Is the lane active? ").append(mIsActive).append(". The lane directions IDs are");
|
||||
for (byte i : mLane)
|
||||
sb.append(" ").append(i);
|
||||
for (LaneWay i : mLane)
|
||||
sb.append(" ").append(i.ordinal());
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "routing/data_source.hpp"
|
||||
#include "routing/fake_feature_ids.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
#include "routing/turns.hpp"
|
||||
|
||||
#include "indexer/ftypes_matcher.hpp"
|
||||
|
||||
|
@ -23,6 +24,21 @@ bool IsFakeFeature(uint32_t featureId)
|
|||
return routing::FakeFeatureIds::IsGuidesFeature(featureId) ||
|
||||
routing::FakeFeatureIds::IsTransitFeature(featureId);
|
||||
}
|
||||
|
||||
feature::Metadata::EType GetLanesMetadataTag(FeatureType & ft, bool isForward)
|
||||
{
|
||||
auto directionTag = isForward ? feature::Metadata::FMD_TURN_LANES_FORWARD
|
||||
: feature::Metadata::FMD_TURN_LANES_BACKWARD;
|
||||
if (ft.HasMetadata(directionTag))
|
||||
return directionTag;
|
||||
return feature::Metadata::FMD_TURN_LANES;
|
||||
}
|
||||
|
||||
void LoadLanes(LoadedPathSegment & pathSegment, FeatureType & ft, bool isForward)
|
||||
{
|
||||
auto tag = GetLanesMetadataTag(ft, isForward);
|
||||
ParseLanes(std::string(ft.GetMetadata(tag)), pathSegment.m_lanes);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
DirectionsEngine::DirectionsEngine(MwmDataSource & dataSource, std::shared_ptr<NumMwmIds> numMwmIds)
|
||||
|
@ -48,7 +64,7 @@ unique_ptr<FeatureType> DirectionsEngine::GetFeature(FeatureID const & featureId
|
|||
}
|
||||
|
||||
void DirectionsEngine::LoadPathAttributes(FeatureID const & featureId,
|
||||
LoadedPathSegment & pathSegment)
|
||||
LoadedPathSegment & pathSegment, bool isForward)
|
||||
{
|
||||
if (!featureId.IsValid())
|
||||
return;
|
||||
|
@ -59,6 +75,8 @@ void DirectionsEngine::LoadPathAttributes(FeatureID const & featureId,
|
|||
|
||||
feature::TypesHolder types(*ft);
|
||||
|
||||
LoadLanes(pathSegment, *ft, isForward);
|
||||
|
||||
pathSegment.m_highwayClass = GetHighwayClass(types);
|
||||
ASSERT_NOT_EQUAL(pathSegment.m_highwayClass, HighwayClass::Error, ());
|
||||
ASSERT_NOT_EQUAL(pathSegment.m_highwayClass, HighwayClass::Undefined, ());
|
||||
|
@ -195,7 +213,7 @@ void DirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap(
|
|||
pathSegment.m_path = move(prevJunctions);
|
||||
pathSegment.m_segments = move(prevSegments);
|
||||
|
||||
LoadPathAttributes(segmentRange.GetFeature(), pathSegment); // inEdge.IsForward()
|
||||
LoadPathAttributes(segmentRange.GetFeature(), pathSegment, inEdge.IsForward());
|
||||
|
||||
if (!segmentRange.IsEmpty())
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ protected:
|
|||
RoutingSettings const & vehicleSettings, turns::TurnItem & turn) = 0;
|
||||
virtual void FixupTurns(std::vector<RouteSegment> & routeSegments) = 0;
|
||||
std::unique_ptr<FeatureType> GetFeature(FeatureID const & featureId);
|
||||
void LoadPathAttributes(FeatureID const & featureId, LoadedPathSegment & pathSegment);
|
||||
void LoadPathAttributes(FeatureID const & featureId, LoadedPathSegment & pathSegment, bool isForward);
|
||||
void GetSegmentRangeAndAdjacentEdges(IRoadGraph::EdgeListT const & outgoingEdges,
|
||||
Edge const & inEdge, uint32_t startSegId, uint32_t endSegId,
|
||||
SegmentRange & segmentRange,
|
||||
|
|
|
@ -108,6 +108,18 @@ UNIT_TEST(TestParseSingleLane)
|
|||
TEST(ParseSingleLane("left", ';', result), ());
|
||||
TEST_EQUAL(result.size(), 1, ());
|
||||
TEST_EQUAL(result[0], LaneWay::Left, ());
|
||||
|
||||
TEST(ParseSingleLane("left;", ';', result), ());
|
||||
TSingleLane expected3 = {LaneWay::Left, LaneWay::None};
|
||||
TEST_EQUAL(result, expected3, ());
|
||||
|
||||
TEST(ParseSingleLane(";", ';', result), ());
|
||||
TSingleLane expected4 = {LaneWay::None, LaneWay::None};
|
||||
TEST_EQUAL(result, expected4, ());
|
||||
|
||||
TEST(ParseSingleLane("", ';', result), ());
|
||||
TSingleLane expected5 = {LaneWay::None};
|
||||
TEST_EQUAL(result, expected5, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestParseLanes)
|
||||
|
@ -162,6 +174,17 @@ UNIT_TEST(TestParseLanes)
|
|||
vector<SingleLaneInfo> const expected7 = {
|
||||
{LaneWay::Left}, {LaneWay::Left}, {LaneWay::Through}, {LaneWay::Through}, {LaneWay::Right}};
|
||||
TEST_EQUAL(result, expected7, ());
|
||||
|
||||
TEST(ParseLanes("|||||slight_right", result), ());
|
||||
vector<SingleLaneInfo> const expected8 = {
|
||||
{LaneWay::None},
|
||||
{LaneWay::None},
|
||||
{LaneWay::None},
|
||||
{LaneWay::None},
|
||||
{LaneWay::None},
|
||||
{LaneWay::SlightRight}
|
||||
};
|
||||
TEST_EQUAL(result, expected8, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestFixupTurns)
|
||||
|
|
|
@ -22,8 +22,14 @@ namespace
|
|||
{
|
||||
/// The order is important. Starting with the most frequent tokens according to
|
||||
/// taginfo.openstreetmap.org we minimize the number of the comparisons in ParseSingleLane().
|
||||
array<pair<LaneWay, char const *>, static_cast<size_t>(LaneWay::Count)> const g_laneWayNames = {
|
||||
{{LaneWay::Through, "through"},
|
||||
///
|
||||
/// A `none` lane can be represented either as "none" or as "". That means both "none" and ""
|
||||
/// should be considered names, even though they refer to the same thing. As a result,
|
||||
/// `LaneWay::None` appears twice in this array, which is one longer than the number of
|
||||
/// enum values.
|
||||
array<pair<LaneWay, char const *>, static_cast<size_t>(LaneWay::Count) + 1> const g_laneWayNames = {
|
||||
{{LaneWay::None, ""},
|
||||
{LaneWay::Through, "through"},
|
||||
{LaneWay::Left, "left"},
|
||||
{LaneWay::Right, "right"},
|
||||
{LaneWay::None, "none"},
|
||||
|
@ -34,7 +40,7 @@ array<pair<LaneWay, char const *>, static_cast<size_t>(LaneWay::Count)> const g_
|
|||
{LaneWay::SlightRight, "slight_right"},
|
||||
{LaneWay::SharpRight, "sharp_right"},
|
||||
{LaneWay::Reverse, "reverse"}}};
|
||||
static_assert(g_laneWayNames.size() == static_cast<size_t>(LaneWay::Count),
|
||||
static_assert(g_laneWayNames.size() == static_cast<size_t>(LaneWay::Count) + 1,
|
||||
"Check the size of g_laneWayNames");
|
||||
|
||||
array<pair<CarDirection, char const *>, static_cast<size_t>(CarDirection::Count)> const
|
||||
|
@ -239,12 +245,14 @@ bool IsLaneWayConformedTurnDirection(LaneWay l, CarDirection t)
|
|||
case CarDirection::TurnSharpRight:
|
||||
return l == LaneWay::SharpRight;
|
||||
case CarDirection::TurnSlightRight:
|
||||
case CarDirection::ExitHighwayToRight:
|
||||
return l == LaneWay::SlightRight;
|
||||
case CarDirection::TurnLeft:
|
||||
return l == LaneWay::Left;
|
||||
case CarDirection::TurnSharpLeft:
|
||||
return l == LaneWay::SharpLeft;
|
||||
case CarDirection::TurnSlightLeft:
|
||||
case CarDirection::ExitHighwayToLeft:
|
||||
return l == LaneWay::SlightLeft;
|
||||
case CarDirection::UTurnLeft:
|
||||
case CarDirection::UTurnRight:
|
||||
|
@ -275,6 +283,10 @@ bool IsLaneWayConformedTurnDirectionApproximately(LaneWay l, CarDirection t)
|
|||
case CarDirection::UTurnLeft:
|
||||
case CarDirection::UTurnRight:
|
||||
return l == LaneWay::Reverse;
|
||||
case CarDirection::ExitHighwayToLeft:
|
||||
return l == LaneWay::SlightLeft || l == LaneWay::Left;
|
||||
case CarDirection::ExitHighwayToRight:
|
||||
return l == LaneWay::SlightRight || l == LaneWay::Right;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,7 +304,13 @@ void SplitLanes(string const & lanesString, char delimiter, vector<string> & lan
|
|||
bool ParseSingleLane(string const & laneString, char delimiter, TSingleLane & lane)
|
||||
{
|
||||
lane.clear();
|
||||
istringstream laneStream(laneString);
|
||||
// When `laneString` ends with "" representing none, for example, in "right;",
|
||||
// `getline` will not read any characters, so it exits the loop and does not
|
||||
// handle the "". So, we add a delimiter to the end of `laneString`. Nonempty
|
||||
// final tokens consume the delimiter and act as expected, and empty final tokens
|
||||
// read a the delimiter, so `getline` sets `token` to the empty string rather than
|
||||
// exiting the loop.
|
||||
istringstream laneStream(laneString + delimiter);
|
||||
string token;
|
||||
while (getline(laneStream, token, delimiter))
|
||||
{
|
||||
|
|
Reference in a new issue