Skip to content

Commit

Permalink
Merge pull request #4318 from osmandapp/attach_to_the_roads
Browse files Browse the repository at this point in the history
Attach to the roads
  • Loading branch information
alex-osm authored Jan 27, 2025
2 parents 0c78527 + df9459a commit 115f1c3
Show file tree
Hide file tree
Showing 26 changed files with 1,013 additions and 235 deletions.
32 changes: 32 additions & 0 deletions OsmAnd.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Resources/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@
"screen_alerts" = "Screen alerts";
"vehicle_parameters" = "Vehicle parameters";
"map_during_navigation" = "Map during navigation";
"detailed_track_guidance" = "Detailed track guidance";
"detailed_track_guidance_description" = "OsmAnd will match your track to nearby roads for enhanced turn-by-turn guidance.";
"ask_every_time" = "Ask every time";
"attach_roads_descr" = "Attach your track to roads to get detailed route information with turn instructions and road attributes.";
"change_map_behavior" = "Change map behavior during navigation";
"nav_type_descr" = "Select how to calculate a route for this profile";
"nav_type_osmand" = "OsmAnd (offline routing)";
Expand Down
16 changes: 16 additions & 0 deletions Sources/Controllers/Cells/AttachRoadsBannerCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// AttachRoadsBannerCell.swift
// OsmAnd Maps
//
// Created by Dmitry Svetlichny on 19.01.2025.
// Copyright © 2025 OsmAnd. All rights reserved.
//

import UIKit

@objcMembers
final class AttachRoadsBannerCell: UITableViewCell {
@IBOutlet weak var contentContainer: UIView!
@IBOutlet weak var label: UILabel!
@IBOutlet weak var button: UIButton!
}
13 changes: 13 additions & 0 deletions Sources/Controllers/Cells/ImageHeaderCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// ImageHeaderCell.swift
// OsmAnd Maps
//
// Created by Dmitry Svetlichny on 08.01.2025.
// Copyright © 2025 OsmAnd. All rights reserved.
//

import UIKit

final class ImageHeaderCell: UITableViewCell {
@IBOutlet weak var backgroundImageView: UIImageView!
}
97 changes: 97 additions & 0 deletions Sources/Controllers/Cells/Xibs/AttachRoadsBannerCell.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="AttachRoadsBannerCell" rowHeight="134" id="tUb-iS-Yqk" userLabel="AttachRoadsBannerCell" customClass="AttachRoadsBannerCell" customModule="OsmAnd_Maps" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="393" height="134"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="tUb-iS-Yqk" id="YfM-iR-X4y">
<rect key="frame" x="0.0" y="0.0" width="393" height="134"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nJE-Cm-rxU" userLabel="Content Container">
<rect key="frame" x="14" y="4" width="365" height="120"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hdr-qR-uSf">
<rect key="frame" x="20" y="0.0" width="345" height="84"/>
<constraints>
<constraint firstAttribute="height" constant="84" id="MzR-Ab-ibA"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" name="textColorPrimary"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FnC-WM-WP2" userLabel="Separator View">
<rect key="frame" x="20" y="84" width="345" height="1"/>
<color key="backgroundColor" name="customSeparator"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="hd9-48-hhe"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fIu-LW-wzj">
<rect key="frame" x="20" y="85" width="345" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="wmk-rK-T8l"/>
</constraints>
<color key="tintColor" name="textColorActive"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" title="Button" titleAlignment="leading">
<directionalEdgeInsets key="contentInsets" top="0.0" leading="0.0" bottom="0.0" trailing="0.0"/>
</buttonConfiguration>
</button>
</subviews>
<color key="backgroundColor" name="groupBg"/>
<constraints>
<constraint firstItem="fIu-LW-wzj" firstAttribute="top" secondItem="FnC-WM-WP2" secondAttribute="bottom" id="Ax3-d5-R52"/>
<constraint firstItem="FnC-WM-WP2" firstAttribute="top" secondItem="Hdr-qR-uSf" secondAttribute="bottom" id="CoG-vx-sqT"/>
<constraint firstAttribute="bottom" secondItem="fIu-LW-wzj" secondAttribute="bottom" priority="999" id="FaO-8E-1Gq"/>
<constraint firstAttribute="trailing" secondItem="Hdr-qR-uSf" secondAttribute="trailing" id="Gq4-hl-FFl"/>
<constraint firstItem="Hdr-qR-uSf" firstAttribute="top" secondItem="nJE-Cm-rxU" secondAttribute="top" id="UHS-Ls-vWK"/>
<constraint firstItem="Hdr-qR-uSf" firstAttribute="leading" secondItem="nJE-Cm-rxU" secondAttribute="leading" constant="20" symbolic="YES" id="bGo-YU-dfJ"/>
<constraint firstAttribute="trailing" secondItem="FnC-WM-WP2" secondAttribute="trailing" id="cfj-nb-v7c"/>
<constraint firstItem="FnC-WM-WP2" firstAttribute="leading" secondItem="nJE-Cm-rxU" secondAttribute="leading" constant="20" symbolic="YES" id="iJX-U2-AlS"/>
<constraint firstAttribute="trailing" secondItem="fIu-LW-wzj" secondAttribute="trailing" id="uOP-5w-SFm"/>
<constraint firstItem="fIu-LW-wzj" firstAttribute="leading" secondItem="nJE-Cm-rxU" secondAttribute="leading" constant="20" symbolic="YES" id="zWc-gE-oGm"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" name="groupBg"/>
<constraints>
<constraint firstItem="nJE-Cm-rxU" firstAttribute="leading" secondItem="YfM-iR-X4y" secondAttribute="leading" constant="14" id="4Xb-Rf-6V5"/>
<constraint firstAttribute="trailing" secondItem="nJE-Cm-rxU" secondAttribute="trailing" constant="14" id="KqP-YM-vc1"/>
<constraint firstAttribute="bottom" secondItem="nJE-Cm-rxU" secondAttribute="bottom" constant="10" id="Y4p-H3-7JM"/>
<constraint firstItem="nJE-Cm-rxU" firstAttribute="top" secondItem="YfM-iR-X4y" secondAttribute="top" constant="4" id="e0Q-cH-vpt"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" name="groupBg"/>
<connections>
<outlet property="button" destination="fIu-LW-wzj" id="h6w-id-hxN"/>
<outlet property="contentContainer" destination="nJE-Cm-rxU" id="lJ6-JX-Vqf"/>
<outlet property="label" destination="Hdr-qR-uSf" id="FYs-fJ-dFy"/>
</connections>
<point key="canvasLocation" x="67.938931297709928" y="-2.8169014084507045"/>
</tableViewCell>
</objects>
<resources>
<namedColor name="customSeparator">
<color red="0.79607843137254897" green="0.7803921568627451" blue="0.81960784313725488" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="groupBg">
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="textColorActive">
<color red="0.3411764705882353" green="0.078431372549019607" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="textColorPrimary">
<color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
</resources>
</document>
55 changes: 55 additions & 0 deletions Sources/Controllers/Cells/Xibs/ImageHeaderCell.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" rowHeight="202" id="NNk-QA-fBF" userLabel="ImageHeaderCell" customClass="ImageHeaderCell" customModule="OsmAnd_Maps" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="350" height="202"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="NNk-QA-fBF" id="BcU-IY-elF">
<rect key="frame" x="0.0" y="0.0" width="350" height="202"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lLD-YM-RnZ">
<rect key="frame" x="0.0" y="0.0" width="350" height="202"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Aav-UU-hsW" userLabel="backgroundImageView">
<rect key="frame" x="6" y="10" width="338" height="182"/>
</imageView>
</subviews>
<color key="backgroundColor" name="groupBg"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="Aav-UU-hsW" secondAttribute="bottom" constant="10" id="0cf-KC-ciO"/>
<constraint firstItem="Aav-UU-hsW" firstAttribute="leading" secondItem="lLD-YM-RnZ" secondAttribute="leading" constant="6" id="1O8-Qt-7oZ"/>
<constraint firstAttribute="trailing" secondItem="Aav-UU-hsW" secondAttribute="trailing" constant="6" id="QV2-c8-i18"/>
<constraint firstItem="Aav-UU-hsW" firstAttribute="top" secondItem="lLD-YM-RnZ" secondAttribute="top" constant="10" id="a6L-sD-1zg"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="lLD-YM-RnZ" secondAttribute="trailing" id="09h-vF-vHY"/>
<constraint firstItem="lLD-YM-RnZ" firstAttribute="leading" secondItem="BcU-IY-elF" secondAttribute="leading" id="AHR-a6-tNk"/>
<constraint firstAttribute="bottom" secondItem="lLD-YM-RnZ" secondAttribute="bottom" id="Ar3-Dj-s0P"/>
<constraint firstItem="lLD-YM-RnZ" firstAttribute="top" secondItem="BcU-IY-elF" secondAttribute="top" id="Hqz-aj-WG9"/>
<constraint firstItem="lLD-YM-RnZ" firstAttribute="centerX" secondItem="BcU-IY-elF" secondAttribute="centerX" id="gF6-m2-Ll5"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="backgroundImageView" destination="Aav-UU-hsW" id="Yvi-Ig-tQv"/>
</connections>
<point key="canvasLocation" x="36.231884057971016" y="167.41071428571428"/>
</tableViewCell>
</objects>
<resources>
<namedColor name="groupBg">
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
</resources>
</document>
11 changes: 11 additions & 0 deletions Sources/Controllers/Map/OAMapActions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#import "OAAppData.h"
#import "OAAddWaypointBottomSheetViewController.h"
#import "OAUninstallSpeedCamerasViewController.h"
#import "OAGpxApproximationParams.h"
#import "OsmAndSharedWrapper.h"
#import "OsmAnd_Maps-Swift.h"

Expand Down Expand Up @@ -164,6 +165,16 @@ - (void) setGPXRouteParamsWithDocument:(OASGpxFile *)doc path:(NSString *)path
[params setUseIntermediatePointsRTE:_settings.gpxCalculateRtept.get];
[params setCalculateOsmAndRoute:_settings.gpxRouteCalc.get];
[params setSelectedSegment:_settings.gpxRouteSegment.get];

OAApplicationMode *appMode = [_routingHelper getAppMode];
if (![doc isAttachedToRoads] && [_settings.detailedTrackGuidance get:appMode] == EOATrackApproximationAutomatic)
{
OAGpxApproximationParams *approximationParams = [[OAGpxApproximationParams alloc] init];
[approximationParams setAppMode:appMode];
[approximationParams setDistanceThreshold:[_settings.gpxApproximationDistance get:[_routingHelper getAppMode]]];
[params setApproximationParams:approximationParams];
}

NSArray<CLLocation *> *ps = [params getPoints];
[_routingHelper setGpxParams:params];
[_settings.followTheGpxRoute set:path];
Expand Down
46 changes: 46 additions & 0 deletions Sources/Controllers/RouteInfoMenu/OARouteInfoView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
#import "OARequiredMapsResourceViewController.h"
#import "OAResourcesUIHelper.h"
#import "OsmAndSharedWrapper.h"
#import "OASnapTrackWarningViewController.h"
#import "OAGpxData.h"
#import "OAMeasurementEditingContext.h"

#include <OsmAndCore/Map/FavoriteLocationsPresenter.h>

Expand Down Expand Up @@ -203,6 +206,7 @@ - (void) awakeFromNib
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:ElevationChartCell.reuseIdentifier owner:self options:nil];
_routeStatsCell = (ElevationChartCell *)[nib objectAtIndex:0];
_routeStatsCell.heightConstraint.constant = 90;
[_tableView registerNib:[UINib nibWithNibName:AttachRoadsBannerCell.reuseIdentifier bundle:nil] forCellReuseIdentifier:AttachRoadsBannerCell.reuseIdentifier];

[GpxUIHelper setupElevationChartWithChartView:_routeStatsCell.chartView
topOffset:10
Expand Down Expand Up @@ -647,6 +651,15 @@ - (void) updateData
[section addObject:@{
@"cell" : kCellReuseIdentifier
}];
if ([self shouldShowAttachRoadsOption])
{
[section addObject:@{
@"cell" : AttachRoadsBannerCell.reuseIdentifier,
@"title" : OALocalizedString(@"attach_roads_descr"),
@"buttonTitle" : OALocalizedString(@"attach_to_the_roads"),
@"key" : @"attach_roads"
}];
}
[section addObject:@{
@"cell" : [OAFilledButtonCell getCellIdentifier],
@"title" : OALocalizedString(@"shared_string_details"),
Expand Down Expand Up @@ -738,6 +751,12 @@ - (BOOL) isGpxTrackFollowingMode
return _routingHelper.getCurrentGPXRoute != nil;
}

- (BOOL) shouldShowAttachRoadsOption
{
OASGpxFile *gpx = _routingHelper.getCurrentGPXRoute.file;
return gpx && ![gpx isAttachedToRoads] && [self isGpxTrackFollowingMode] && [_settings.detailedTrackGuidance get:[_routingHelper getAppMode]] == EOATrackApproximationManual;
}

- (NSAttributedString *) getFirstLineDescrAttributed:(SHARED_PTR<TransportRouteResult>)res
{
NSMutableAttributedString *attributedStr = [NSMutableAttributedString new];
Expand Down Expand Up @@ -1031,6 +1050,20 @@ - (void) openRouteDetails
[[OARootViewController instance].mapPanel openTargetViewWithRouteDetails:_gpx analysis:_trackAnalysis];
}

- (void) openAttachToTheRoadsScreen
{
if (_gpx)
{
OAGpxData *gpxData = [[OAGpxData alloc] initWithFile:_gpx];
OAMeasurementEditingContext *editingContext = [[OAMeasurementEditingContext alloc] init];
editingContext.gpxData = gpxData;
editingContext.appMode = OARoutingHelper.sharedInstance.getAppMode;
editingContext.selectedSegment = OAAppSettings.sharedManager.gpxRouteSegment.get;
[[OARootViewController instance].mapPanel closeRouteInfo];
[[OARootViewController instance].mapPanel showScrollableHudViewController:[[OARoutePlanningHudViewController alloc] initWithEditingContext:editingContext followTrackMode:YES showSnapWarning:YES]];
}
}

- (void) calcPedestrianRoute
{
[_appModeView setSelectedMode:OAApplicationMode.PEDESTRIAN];
Expand Down Expand Up @@ -1522,6 +1555,19 @@ - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(
{
return _routeStatsCell;
}
else if ([item[@"cell"] isEqualToString:AttachRoadsBannerCell.reuseIdentifier])
{
AttachRoadsBannerCell *cell = [self.tableView dequeueReusableCellWithIdentifier:AttachRoadsBannerCell.reuseIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentContainer.layer.cornerRadius = 6;
cell.contentContainer.layer.borderWidth = 1;
cell.contentContainer.layer.borderColor = [UIColor colorNamed:ACColorNameCustomSeparator].CGColor;
cell.label.text = item[@"title"];
[cell.button setTitle:item[@"buttonTitle"] forState:UIControlStateNormal];
[cell.button removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.button addTarget:self action:@selector(openAttachToTheRoadsScreen) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
else if ([item[@"cell"] isEqualToString:[OAFilledButtonCell getCellIdentifier]])
{
OAFilledButtonCell* cell;
Expand Down
Loading

0 comments on commit 115f1c3

Please sign in to comment.